📄 12-1.cpp
字号:
#pragma comment (lib,"highgui.lib")
#pragma comment (lib,"cxcore.lib")
#pragma comment (lib,"cv.lib")
#include <cv.h>
#include <highgui.h>
#include <stdio.h>
#include <iostream.h>
//指定矩形区域内角点阵列的行数目(满足该条件才保存检测出角点的坐标到文件)
#define rank_num 6
//指定矩形区域内角点阵列的列数目(满足该条件才保存检测出角点的坐标到文件)
#define col_num 6
IplImage *srcImage = 0; //存储读入的图像
IplImage *ImageShow = 0; //存储显示带角点的图像
IplImage *grayImage= 0; //原始图像转变的灰度图像
IplImage *corners1 = 0; //临时图像
IplImage *corners2 = 0; //临时图像
#define max_corners 200 //限定最大能找到的角点数
int cornerCount=max_corners; //实际检测的角点数目
int qualityLevel=0; //最小质量因子
int minDistance=40; //角点的最小距离。这里使用 Euclidean 距离
CvScalar color = CV_RGB(255,0,0); //所绘制角点的颜色(红色
CvPoint2D32f corners[max_corners]; //检测存储角点的点数组
CvRect ROI_rect; //指定检测角点的矩形区域的范围
char chek_area_state=0; //指定角点检测范围的时候用的 (画拖动时的矩形框的)
//---------------------本程序用到的函数---------------------------------------------
//-----滑动条响应函数(检测角点就在该函数里实现)---
void re_find_corners(int ) ;
//----鼠标响应函数(主要用于确定寻找角点的矩形区域范围)----
void on_mouse( int event, int x, int y, int flags, void* param ) ;
//----角点排序函数(对寻找到的角点进行重新排序 )----------
void corners_sort() ;
//----------以下为main主函数-----------------
void main( )
{
//载入原始图像
//srcImage = cvLoadImage("黑白格.jpg",-1);
srcImage = cvLoadImage("Image044_00.jpg",-1);
grayImage = cvCreateImage(cvGetSize(srcImage), IPL_DEPTH_8U, 1);
cout<<"srcImage的信道数目:"<<srcImage->nChannels<<endl;
//当原始图像是RGB彩色图时转为为灰度图 不然直接拷贝.
if ( srcImage->nChannels > 1)
{
cvCvtColor(srcImage, grayImage, CV_BGR2GRAY);
}
else
{
grayImage=cvCloneImage(srcImage);
}
//---------设置角点检测的矩形区域范围----------------------------
ROI_rect.x=0;
ROI_rect.y=0;
ROI_rect.width = grayImage->width;
ROI_rect.height = grayImage->height;
//----一开始默认是整幅图像--------
cvSetImageROI(grayImage, ROI_rect);
//----临时图像创建角点检测函数cvGoodFeaturesToTrack中需要----
corners1= cvCreateImage(cvGetSize(grayImage), IPL_DEPTH_32F, 1);
corners2= cvCreateImage(cvGetSize(grayImage),IPL_DEPTH_32F, 1);
//---------显示图像窗口"image"------------
cvNamedWindow( "image", 0 ); //改成1的话 下面那句resize就没用啦
cvResizeWindow("image",950,768);
//-----滑动条qualityLevel和minDistance改变角点检测的最小质量因子和最小距离-----
cvCreateTrackbar("qualityLevel", "image", &qualityLevel, 100, re_find_corners);
cvCreateTrackbar("minDistance", "image", &minDistance, 200, re_find_corners);
//------调用以显示检测出的角点---------
re_find_corners(0);
//----------鼠标效应函数cvSetMouseCallback------------------
cvSetMouseCallback( "image", on_mouse, 0 );
//-------------确定角点检测范围的提示----------------------
cout<<endl<<endl
<<"提示:按下shift建的同时单击鼠标确定角点检测范围的左上角,"<<endl
<<" 最后鼠标右键确定角点检测范围的右下角"
<<endl<<endl;
cvWaitKey(0); // wait for key. The function has
//------------释放图像------------------
cvReleaseImage(&srcImage);
cvReleaseImage(&ImageShow);
cvReleaseImage(&grayImage);
cvReleaseImage(&corners1);
cvReleaseImage(&corners2);
}
//----------------滑动条改变时的响应函数(目的是为了找对应的角点)--------------------
void re_find_corners(int )
{
int i=0;
int radius=2;
int thickness=2;
//根据滑动条的改变更新quality_level
double quality_level=(double)qualityLevel /100 + 0.02;
//根据滑动条的改变更新min_distance
double min_distance=(double)minDistance;
//-------- cvGoodFeaturesToTrack检测角点函数----------------
cvGoodFeaturesToTrack( grayImage,
corners1,
corners2,
corners,
&cornerCount,
quality_level,
min_distance,
NULL
);
//-------------重新设置角点的位置(因为在这之前的角点位置是原图像的在ROI区域的)并
//-------------输出角点在图像中的坐标--------------------
if(cornerCount>0)
{
for (i=0; i<cornerCount; i++)
{
corners[i].x=corners[i].x + ROI_rect.x;
corners[i].y=corners[i].y + ROI_rect.y;
}
}
//只有当rank_num*col_num等于找到的角点数(即满足宏定义条件)时才对它进行排序
if( (rank_num*col_num)== cornerCount )
{
corners_sort(); //对角点进行排序
cout<<endl<<endl
<<"找到的角点数等于rank_num*col_num"
<<endl<<endl;
//-------------输出排序后角点在图像中的坐标--------------------
cout<<endl<<endl
<<"输出排序后角点在图像中的坐标"
<<endl<<endl;
for (i=0; i<cornerCount; i++)
{
cout<<corners[i].x<<" "<<corners[i].y<<endl;
}
//------------存储检测出的角点坐标到文件器----------------------------
CvFileStorage* fs = cvOpenFileStorage( "points_coordinates.xml", 0, CV_STORAGE_WRITE );
cvWriteComment(fs, "存储角点的坐标", 0);
cvWriteRawData( fs, corners, rank_num*col_num*2, "f" );
cout<<endl<<endl<<"已经存储角点坐标到文件points_coordinates.xml"<<endl<<endl;
cvReleaseFileStorage (&fs);
}
//-------在原图上绘出角点---------
ImageShow=cvCloneImage(srcImage);
if(cornerCount>0)
{
//-------------输出角点在图像中的坐标--------------------
for (i=0; i<cornerCount; i++)
{
//cout<<corners[i].x<<" "<<corners[i].y<<endl;
}
for (i=0; i<cornerCount; i++)
{
cvCircle(ImageShow,
cvPoint((int)(corners[i].x), (int)(corners[i].y)), //圆心坐标
radius, //半径
color, //颜色
thickness, //线条粗细
CV_AA,
0);
}
}
printf("num corners found: %d\n", cornerCount);
cornerCount=max_corners;
//------显示检出角点的图像-----
cvShowImage( "image", ImageShow );
cvReleaseImage(&ImageShow);
}
//----------------------鼠标效应函数用于设定角点检测的范围-----------------
void on_mouse( int event, int x, int y, int flags, void* param )
{
int thickness=1; //画检测边缘的线条粗细
CvPoint point1;
CvPoint point2;
//--------shift和左键按下时确定角点检测范围的左上角--------
if( (event==CV_EVENT_LBUTTONUP) && (flags==CV_EVENT_FLAG_SHIFTKEY) )
{
ROI_rect.x=x; //设置ROI区域的位置点
ROI_rect.y=y;
chek_area_state=1; //表征此时鼠标点击的点作为矩形框的左上角
}
//--------------动态的画出角点检测范围-------------------
if( chek_area_state && event==CV_EVENT_MOUSEMOVE)
{
ImageShow=cvCloneImage(srcImage);
point1=cvPoint(ROI_rect.x, ROI_rect.y);
point2=cvPoint(x,y);
cvRectangle( ImageShow,
point1,
point2,
color,
thickness,
CV_AA,
0
);
cvShowImage( "image", ImageShow );
cvReleaseImage(&ImageShow);
}
//--------直接右键按下时确定角点检测范围的右下角
if( chek_area_state && event==CV_EVENT_RBUTTONUP ) //直接写flags=17也可
{
ROI_rect.width = abs(x - ROI_rect.x); //设置ROI区域的大小
ROI_rect.height = abs(y - ROI_rect.y);
cvSetImageROI(grayImage, ROI_rect); //设置角点检测的ROI区域
corners1= cvCreateImage(cvGetSize(grayImage), IPL_DEPTH_32F, 1);
corners2= cvCreateImage(cvGetSize(grayImage),IPL_DEPTH_32F, 1);
cvWaitKey(10);
//在新设置的范围内重新找角点
re_find_corners(0);
//表征此时鼠标点击的点作为矩形框的右下角,且矩形框已画完了
chek_area_state=0;
//-------------确定角点检测范围的提示----------------------
cout<<endl<<endl
<<"提示:按下shift建的同时单击鼠标确定角点检测范围的左上角,"<<endl
<<" 最后鼠标右键确定角点检测范围的右下角"
<<endl<<endl;
}
}
void corners_sort()
{
CvPoint2D32f temp_point=cvPoint2D32f(0.0,0.0); //排序时用于交换的临时point
int i=0;
int j=0;
int k=0;
//-------------先根据point的x值排序---------------
for( i=1; i<cornerCount-1; i++ ) //i<cornerCount-1 因为 后面j=i 再j+1了
{
for( j=i; j>=0; j-- )
{
if( (corners[j].x) > (corners[j+1].x) )
{
//-----交换CvPoint--------
temp_point=corners[j];
corners[j]=corners[j+1];
corners[j+1]=temp_point;
}
else;
}
}
//-------------(rank*colom的点阵)再根据point的y值排序---------------
for( i=0; i<col_num; i++ ) // i代表第几列,
{
for( j=0; j<rank_num-1; j++ ) //j代表行数 rank_num-1 因为下面加1啦
{
for( k=j; k>=0; k-- )
{
if( (corners[i*rank_num+k].y) > (corners[i*rank_num+k+1].y) )
{
//-----交换点之间的坐标以排序-------
temp_point=corners[i*rank_num+k];
corners[i*rank_num+k]=corners[i*rank_num+k+1];
corners[i*rank_num+k+1]=temp_point;
}
else;
}
}
}
}
//*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -