这个程序主要是用OpenCV实现的,主要流程是:菜单响应函数(初始化一些变量等)->鼠标响应函数(mousecallback)->画框选中感兴趣的部分并显示出来.脑海一定要有清晰的流程概念,其实这个小程序就是实现了美图秀秀或者photoshop里面的一个按钮的功能.
代码如下:
BOOL rectFlag2=false;
CvRect rect1;
IplImage *frame4_1;
void draw_rect1(IplImage* frame4_1,CvRect rect)//画框
{
IplImage *frame4_2=cvCreateImage(cvGetSize(frame4_1),8,3);
cvCopy(frame4_1,frame4_2); //这个copy的位置很关键,要不然会有画了很多框的情况出现。
cvRectangle(
frame4_2,
cvPoint(rect.x,rect.y),
cvPoint(rect.x+rect.width,rect.y+rect.height),
CV_RGB(0,255,255),2/*CV_FILLED*/
);
cvShowImage("Example1",frame4_2);
cvWaitKey(0);
if(rect.width<0)//考虑到画框的起点不一定是左上角,所以要预防出错.
{rect.x+=rect.width;rect.width*=(-1);}
if(rect.height<0)
{rect.y+=rect.height;rect.height*=(-1);}
cvSetImageROI(frame4_2,rect);//这里ROI区域的rect如果不是正的话,下面frame4_3就会出错.
IplImage *frame4_3=cvCreateImage(cvGetSize(frame4_2),8,3);
cvCopy(frame4_2,frame4_3);
cvNamedWindow("ROI");
cvShowImage("ROI",frame4_3);
}
void my_mouse_callback1(int event,int x,int y,int flags,void* param)
{
switch(event)
{
case CV_EVENT_LBUTTONDOWN:{rect1.x=x;rect1.y=y;rectFlag2=TRUE;}break;
case CV_EVENT_MOUSEMOVE:
{
if(rectFlag2)
{
rect1.width=x-rect1.x;
rect1.height=y-rect1.y;
draw_rect1(frame4_1,rect1);
}
}break;
case CV_EVENT_LBUTTONUP://这个case放在一定要callback函数里面,要不然放左键是响应不了的。
{
if(rectFlag2)
rectFlag2=false;
}break;//如果没有break的话,程序运行下去就会退出的了。
case CV_EVENT_RBUTTONDOWN://为了调试方便,按下右键就可以退出了。
{
exit(0);
}
}
}
void CMy9161View::On04()
{
cvNamedWindow("Example1",400*4);
IplImage *frame=cvLoadImage("E:\\lena02.jpg");//装载图像
frame4_1=cvCreateImage(cvGetSize(frame),8,3);
cvCopy(frame,frame4_1);//我比较喜欢不在原图上操作,所以通常会新建一幅一样的图像再操作
cvShowImage("Example1",frame4_1);
rect1.x=0;
rect1.y=0;
cvSetMouseCallback("Example1",my_mouse_callback1);//关于cv开头的函数,有不懂的请自行百度,或者查阅相关openCV的书籍,说得很详细的。
}
同样,附上程序结果图: