转自http://hapkui.blog.sohu.com/74264444.html
选取矩形区域
保存矩形区域
哈哈,忍不住感叹opencv功能的强大,这要裸编出来得多不容易啊,呵呵。
下面把代码大概贴一下
用控制台函数和MFC均可,这里是MFC的情况
//view.cpp里面
将鼠标函数声明为全局函数,不然编译时cvSetMouseCallback("image",on_mouse,0)函数会报错:
'cvSetMouseCallback' : cannot convert parameter 2 from 'void (int,int,int,int,void *)' to 'void (__cdecl *)(int,int,int,int,void *)'
void on_mouse(int event,int x,int y,int flags,void *zhang);
IplImage* inpaint_mask=0;
IplImage* img0=0 ,*img=0, *inpainted=0,*selimg=0;;
CvPoint prev_pt={-1,-1} ;
CvPoint pt_beg={-1,-1},pt_end = {-1,-1};
CvPoint pt1={-1,-1},pt2={-1,-1};
CvRect rect;
鼠标事件函数
void on_mouse(int event,int x,int y,int flags,void *)
{
if (!img)
return;
if (event==CV_EVENT_LBUTTONUP || !(flags & CV_EVENT_FLAG_LBUTTON) )
{
prev_pt=cvPoint(-1,-1);
}
else if (event==CV_EVENT_LBUTTONDOWN )
{
prev_pt=cvPoint(x,y);
pt_beg = cvPoint(x,y);//点下鼠标左键时得到起始位置
}
else if (event == CV_EVENT_MOUSEMOVE && (flags & CV_EVENT_FLAG_LBUTTON) )
{
cvZero( inpaint_mask );
cvCopy( img0, img );//拖动时随时更新恢复至原图像,然后只重绘当前拖动位置
CvPoint pt = cvPoint(x,y);
pt1.x=pt.x;
pt1.y=prev_pt.y;
pt2.x=prev_pt.x;
pt2.y=pt.y;//得到其他两个定点的位置,然后绘制矩形
cvLine( inpaint_mask, prev_pt, pt1, cvScalarAll(255),2, 8, 0 );
cvLine( inpaint_mask, prev_pt, pt2, cvScalarAll(255), 2, 8, 0 );
cvLine( inpaint_mask, pt1, pt, cvScalarAll(255), 2, 8, 0 );
cvLine( inpaint_mask, pt2, pt, cvScalarAll(255), 2,8, 0 );
cvLine( img, prev_pt, pt1, cvScalarAll(255), 2, 8, 0 );
cvLine( img, prev_pt, pt2, cvScalarAll(255), 2, 8, 0 );
cvLine( img, pt1, pt, cvScalarAll(255), 2, 8, 0 );
cvLine( img, pt2, pt, cvScalarAll(255), 2, 8, 0 );
pt_end = pt;//得到当前矩形结束位置
cvShowImage( "image", img );
}
}
主函数
void COpcv1View::On
{
// TODO: Add your command handler co
CString str;
CFileDialog filedlg(TRUE);
if(filedlg.DoModal()!=IDOK)
return;
str=filedlg.GetPathName();
if( (img0 = cvLoadImage(str,-1)) == 0 ) //打开文件
return ;
cvNamedWindow( "image", 1 );
img = cvCloneImage( img0 );
inpainted = cvCloneImage( img0 );
inpaint_mask = cvCreateImage( cvGetSize(img), 8, 1 );
cvZero( inpaint_mask );
cvZero( inpainted );
cvShowImage( "image", img );
cvShowImage( "watershed transform", inpainted );
cvSetMouseCallback("image",on_mouse,0);
for(;;)
{
int c = cvWaitKey(0);
if( (char)c == 27 )
break;
if( (char)c == 'r' )
{
cvZero( inpaint_mask );
cvCopy( img0, img );
cvShowImage( "image", img );
}
if( (char)c == 'i' || (char)c == '\n' )
{
cvNamedWindow( "inpainted image", 1 );
cvInpaint( img, inpaint_mask, inpainted, 3, CV_INPAINT_TELEA );
cvShowImage( "inpainted image", inpainted );
}
if ((char)c == 'c')
{
rect.x = min(pt_beg.x,pt_end.x);//这样得到的才准确,不能直接pt_beg.x,因为可以从右下角拉动
rect.y = min(pt_beg.y,pt_end.y);
rect.height = abs(pt_end.y - pt_beg.y);
rect.width = abs(pt_end.x - pt_beg.x);
cvSetImageROI( img0, rect );//选取目标区域,这个函数好,同学帮助告知的
CvSize size;
size.width=rect.width;
size.height=rect.height;
selimg=cvCreateImage(size,IPL_DEPTH_8U,3);//新建一个图像,这里的3个通道实际上应该判断一下是灰度图还是彩图。
cvCopy(img0,selimg,NULL);//复制感兴趣区域
cvNamedWindow( "select image", 1 );
cvShowImage("select image",selimg);
cvSaveImage("selimg.bmp",selimg);//保存
break;
}
}
}