OpenCV常用图像操作和鼠标操作(双11版本)
更新日志:
1.添加了自适应窗口大小的功能;
2.添加了在图像上画矩形的功能;
3.添加了在大图上画矩形的功能;
4.部分函数名称更改;
5其他修改。
首先是头文件:
/* ******* ccv.h ********** ********* opencv常用操作函数声明 ********** */ /* author: autumoon */ #ifndef _CCV_H_ #define _CCV_H_ #include <afxdlgs.h> //打开文件 #include "cv.h" #include "cxcore.h" #include "highgui.h" using namespace cv; #define SCREEN_WIDTH 1920 #define SCREEN_HEIGHT 1080 class CCvImage { public: Mat m_Minput; //使用Mat类型 //鼠标控制相关变量 Mat m_Mmask; Mat m_Mmid; Mat m_Msrc; //外部矩阵输入 char* m_szTitle; CvPoint m_curr_pt; CvPoint m_prev_pt; CvRect m_rect; CvRect m_CRroi; float m_fProportion; int m_nThick; public: CCvImage(); CCvImage(Mat mat); CCvImage(IplImage* pImage); CCvImage(char szImgPath[], int flags = 1); CCvImage(CString strImgPath, int flags = 1); public: //图像操作 int AdaptiveFindThreshold(CvMat *dx, CvMat *dy, double *low, double *high); int AutoSizeMat(Mat& Msrc, Mat& Mdst, float& fProportion, int nScreenWidth = SCREEN_WIDTH, int nScreenHeight = SCREEN_HEIGHT); int CannyAutoThreshold(Mat Msrc, Mat& Mdst); int EasyCanny(Mat Msrc, Mat& Mdst, double threshold1 = 100, double threshold2 = 200); int ErodeDilate(Mat Msrc, Mat& Mdst, int nPos); //nPos < 10 腐蚀,nPos > 10 膨胀 int OpenClose(Mat Msrc, Mat& Mdst, int nPos); //nPos < 10 开运算,nPos > 10 闭运算 int ShowImg(char szTitle[] = "显示图像", bool bAutoClose = true); int ShowImg(Mat Msrc, char szTitle[] = "显示图像", bool bAutoClose = true); //显示某个矩阵 int ShowImgAutoSize(char szTitle[] = "显示图像", int nScreenWidth = SCREEN_WIDTH, int nScreenHeight = SCREEN_HEIGHT, bool bAutoClose = true); int ShowImgAutoSize(Mat Msrc, char szTitle[] = "显示图像", int nScreenWidth = SCREEN_WIDTH, int nScreenHeight = SCREEN_HEIGHT, bool bAutoClose = true); int SobelCalc(Mat Msrc, Mat& pMdst, bool bGray = false); //鼠标图像操作 int DrawCurveOnImg(Mat Msrc, char* szTitle = "画曲线", int nThick = 2); int DrawCurveOnBigImg(Mat Msrc, int nScreenWidth = SCREEN_WIDTH, int nScreenHeight = SCREEN_HEIGHT, char* szTitle = "画曲线", int nThick = 2); int DrawLineOnImg(Mat Msrc, CvPoint& pStart, CvPoint& pEnd, char* szTitle = "画直线", int nThick = 2); int DrawLineOnBigImg(Mat Msrc, CvPoint& pStart, CvPoint& pEnd, int nScreenWidth = SCREEN_WIDTH, int nScreenHeight = SCREEN_HEIGHT, char* szTitle = "画直线", int nThick = 2); int DrawRectOnImg(Mat Msrc, CvRect& rect, char* szTitle = "画矩形", int nThick = 2); int DrawRectOnBigImg(Mat Msrc, CvRect& rect, int nScreenWidth = SCREEN_WIDTH, int nScreenHeight = SCREEN_HEIGHT, char* szTitle = "画矩形", int nThick = 2); int GetMaskByCurve(Mat Msrc, Mat& pDst, char* szTitle = "获取遮罩"); //通过曲线获取遮罩 int GetMaskByDaub(Mat Msrc, Mat& pDst, int nRadius = 20, char* szTitle = "获取遮罩"); //通过涂抹获取遮罩 //其他操作 int ResetRect(CvRect& rect, int nValue = -1); int ResizePoint(CvPoint& Csrc, float fProportion); int ResizeRect(CvRect& Csrc, float fProportion); int ResizeRect(CvRect& rect, int nExpandWidthPixs = 0, int nExpandHeightPixs = 0); int ResizeRect(CvRect& rect, int nLeft, int nRight, int nUp, int nDown); int ValidExpandValue(const CvRect& CRroi, int& nLeft, int& nRight, int& nUp, int& nDown, int nWidth, int nHeight); int ValidRect(CvRect& rect, const int nWidth, const int nHeight); int ValidRect(CvRect& rectSmall, const int nRectWidth, const int nRectHeight, const int nPicWidth, const int nPicHeight); private: IplImage* IInput; //内部使用的IplImage指针 }; //回调函数 void on_mouse_curve(int event, int x, int y, int flags, void* pParameters); void on_mouse_big_curve(int event, int x, int y, int flags, void* pParameters); void on_mouse_curve_mask(int event, int x, int y, int flags, void* pParameters); void on_mouse_daub(int event, int x, int y, int flags, void* pParameters); void on_mouse_line(int event, int x, int y, int flags, void* pParameters); void on_mouse_rect(int event, int x, int y, int flags, void* pParameters); #endif
然后是cpp文件:
/* ******* ccv.cpp ********** ********* opencv常用操作函数实现 ********** */ /* author: autumoon */ #include "ccv.h" CCvImage::CCvImage() { ResetRect(m_rect); ResetRect(m_CRroi); IInput = NULL; } CCvImage::CCvImage(char szImgPath[], int flags/* = 1*/) { ResetRect(m_rect); ResetRect(m_CRroi); IInput = NULL; m_Minput = imread(szImgPath, flags); } CCvImage::CCvImage(CString strImgPath, int flags/* = 1*/) { ResetRect(m_rect); ResetRect(m_CRroi); IInput = NULL; char* szImgPath; #ifdef _UNICODE USES_CONVERSION; szImgPath = W2A(strCstring); #else szImgPath = (LPSTR)(LPCTSTR)strImgPath; #endif m_Minput = imread(szImgPath, flags); } int CCvImage::AdaptiveFindThreshold(CvMat *dx, CvMat *dy, double *low, double *high) { CvSize size; IplImage *imge=0; int i,j; CvHistogram *hist; int hist_size = 255; float range_0[]={0,256}; float* ranges[] = { range_0 }; double PercentOfPixelsNotEdges = 0.7; size = cvGetSize(dx); imge = cvCreateImage(size, IPL_DEPTH_32F, 1); // 计算边缘的强度, 并存于图像中 float maxv = 0; for(i = 0; i < size.height; i++ ) { const short* _dx = (short*)(dx->data.ptr + dx->step*i); const short* _dy = (short*)(dy->data.ptr + dy->step*i); float* _image = (float *)(imge->imageData + imge->widthStep*i); for(j = 0; j < size.width; j++) { _image[j] = (float)(abs(_dx[j]) + abs(_dy[j])); maxv = maxv < _image[j] ? _image[j]: maxv; } } if(maxv == 0){ *high = 0; *low = 0; cvReleaseImage( &imge ); return -1; } // 计算直方图 range_0[1] = maxv; hist_size = (int)(hist_size > maxv ? maxv:hist_size); hist = cvCreateHist(1, &hist_size, CV_HIST_ARRAY, ranges, 1); cvCalcHist( &imge, hist, 0, NULL ); int total = (int)(size.height * size.width * PercentOfPixelsNotEdges); float sum=0; int icount = hist->mat.dim[0].size; float *h = (float*)cvPtr1D( hist->bins, 0 ); for(i = 0; i < icount; i++) { sum += h[i]; if( sum > total ) break; } // 计算高低门限 *high = (i+1) * maxv / hist_size ; *low = *high * 0.4; cvReleaseImage( &imge ); cvReleaseHist(&hist); return 0; } int CCvImage::AutoSizeMat(Mat& Msrc, Mat& Mdst, float& fProportion, int nScreenWidth/* = SCREEN_WIDTH*/, int nScreenHeight/* = SCREEN_HEIGHT*/) { if (Msrc.cols <= nScreenWidth && Msrc.rows <= nScreenHeight) { Msrc.copyTo(Mdst); fProportion = 1.0; return 0; } if ((float)Msrc.cols / Msrc.rows >= (float)nScreenWidth / nScreenWidth) { fProportion = (float)Msrc.cols / nScreenWidth; } else { fProportion = (float)Msrc.rows / nScreenHeight; } resize(Msrc, Mdst, cv::Size(Msrc.cols / fProportion, Msrc.rows / fProportion)); return 0; } int CCvImage::CannyAutoThreshold(Mat Msrc, Mat& Mdst) { double low, high; IplImage Isrc = Msrc; Mat src; if (Msrc.channels() == 3) { cvtColor(Msrc, src, CV_RGB2GRAY); } else { src = Msrc; } const int cn = src.channels(); Mat dx(src.rows, src.cols, CV_16SC(cn), BORDER_REPLICATE); Mat dy(src.rows, src.cols, CV_16SC(cn), BORDER_REPLICATE); Sobel(src, dx, CV_16S, 1, 0, 3, 1, 0); Sobel(src, dy, CV_16S, 0, 1, 3, 1, 0); CvMat _dx = dx, _dy = dy; AdaptiveFindThreshold(&_dx, &_dy, &low, &high); Canny(Msrc, Mdst, low, high); return 0; } int CCvImage::EasyCanny(Mat Msrc, Mat& Mdst, double threshold1/* = 100*/, double threshold2/* = 200*/) { Mat Mgray; if (Msrc.channels() == 3) { cvtColor(Msrc, Mgray, CV_RGB2GRAY); } else { Mgray = Msrc; } Canny(Mgray, Mdst, threshold1, threshold2); return 0; } int CCvImage::ErodeDilate(Mat Msrc, Mat& Mdst, int nPos) { int n = nPos - 10; int an = n > 0 ? n : -n; Mat element = getStructuringElement(MORPH_RECT, Size(an*2+1, an*2+1), Point(an, an) ); if( n < 0 ) erode(Msrc, Mdst, element); else dilate(Msrc, Mdst, element); return 0; } int CCvImage::OpenClose(Mat Msrc, Mat& Mdst, int nPos) { int n = nPos - 10; int an = n > 0 ? n : -n; Mat element = getStructuringElement(MORPH_RECT, Size(an*2+1, an*2+1), Point(an, an) ); if( n < 0 ) morphologyEx(Msrc, Mdst, CV_MOP_OPEN, element); else morphologyEx(Msrc, Mdst, CV_MOP_CLOSE, element); return 0; } int CCvImage::ShowImg(char szTitle[]/* = "显示图像"*/, bool bAutoClose/* = true*/) { imshow(szTitle, m_Minput); waitKey(); if (bAutoClose) { destroyWindow(szTitle); } return 0; } int CCvImage::ShowImg(Mat Msrc, char szTitle[]/* = "显示图像"*/, bool bAutoClose/* = true*/) { imshow(szTitle, Msrc); waitKey(); if (bAutoClose) { destroyWindow(szTitle); } return 0; } int CCvImage::ShowImgAutoSize(char szTitle[]/* = "显示图像"*/, int nScreenWidth/* = 1920*/, int nScreenHeight/* = 1080*/, bool bAutoClose/* = true*/) { return ShowImgAutoSize(m_Minput, szTitle, nScreenWidth, nScreenHeight, bAutoClose); } int CCvImage::ShowImgAutoSize(Mat Msrc, char szTitle[]/* = "显示图像"*/, int nScreenWidth/* = 1920*/, int nScreenHeight/* = 1080*/, bool bAutoClose/* = true*/) { Mat Mresize; float fProportion; AutoSizeMat(Msrc, Mresize, fProportion, nScreenWidth, nScreenHeight); imshow(szTitle, Mresize); waitKey(); if (bAutoClose) { destroyWindow(szTitle); } return 0; } int CCvImage::SobelCalc(Mat Msrc, Mat& pMdst, bool bGray/* = false*/) { Mat src, dst_x, dst_y, dst; if (bGray && Msrc.channels() == 3) { cvtColor(Msrc, src, CV_RGB2GRAY); } else { src = Msrc; } Sobel(src, dst_x, src.depth(), 1, 0); Sobel(src, dst_y, src.depth(), 0, 1); convertScaleAbs(dst_x, dst_x); convertScaleAbs(dst_y, dst_y); addWeighted( dst_x, 0.5, dst_y, 0.5, 0, dst); dst.copyTo(pMdst); return 0; } int CCvImage::DrawCurveOnImg(Mat Msrc, char* szTitle/* = "画曲线"*/, int nThick/* = 2*/) { m_Mmid.release(); m_Mmid = Msrc; //显示原图 imshow(szTitle,m_Mmid); //鼠标回调函数 this->m_szTitle = szTitle; this->m_nThick = nThick; cvSetMouseCallback(szTitle, on_mouse_curve, this); waitKey(0); destroyWindow(szTitle); return 0; } void on_mouse_curve(int event, int x, int y, int flags, void* pParameters) { CCvImage* pthis = (CCvImage*)pParameters; //获取相关的参数 char* szTitle = pthis->m_szTitle; CvPoint& prev_pt = pthis->m_prev_pt; int nThick = pthis->m_nThick; Mat& Mmid = pthis->m_Mmid; if(!Mmid.data) 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); } else if ( event == CV_EVENT_MOUSEMOVE && (flags & CV_EVENT_FLAG_LBUTTON)) //判断移动鼠标并且左拖拽 { CvPoint pt = cvPoint(x, y); if ( prev_pt.x < 0) { prev_pt = pt; } line(Mmid, prev_pt, pt, Scalar::all(255), nThick ,8,0); //原图上划线 prev_pt = pt; imshow(szTitle, Mmid); } if (event == CV_EVENT_RBUTTONUP) { destroyWindow(szTitle); } } int CCvImage::DrawCurveOnBigImg(Mat Msrc, int nScreenWidth/* = SCREEN_WIDTH*/, int nScreenHeight/* = SCREEN_HEIGHT*/, char* szTitle/* = "画曲线"*/, int nThick/* = 2*/) { m_Mmid.release(); m_Msrc.release(); float fProportion; AutoSizeMat(Msrc, m_Mmid, fProportion, nScreenWidth, nScreenHeight); m_Msrc = Msrc; //显示原图 imshow(szTitle, m_Mmid); //鼠标回调函数 this->m_szTitle = szTitle; this->m_nThick = nThick; this->m_fProportion = fProportion; cvSetMouseCallback(szTitle, on_mouse_big_curve, this); waitKey(0); destroyWindow(szTitle); return 0; } void on_mouse_big_curve(int event, int x, int y, int flags, void* pParameters) { CCvImage* pthis = (CCvImage*)pParameters; //获取相关的参数 char* szTitle = pthis->m_szTitle; CvPoint& prev_pt = pthis->m_prev_pt; int nThick = pthis->m_nThick; Mat& Mmid = pthis->m_Mmid; if(!Mmid.data) 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); } else if ( event == CV_EVENT_MOUSEMOVE && (flags & CV_EVENT_FLAG_LBUTTON)) //判断移动鼠标并且左拖拽 { CvPoint pt = cvPoint(x, y); if ( prev_pt.x < 0) { prev_pt = pt; } line(Mmid, prev_pt, pt, Scalar::all(255), nThick ,8,0); //缩小图上划线 CvPoint t_prev_pt = prev_pt, t_pt = pt; pthis->ResizePoint(t_prev_pt, pthis->m_fProportion); pthis->ResizePoint(t_pt, pthis->m_fProportion); line(pthis->m_Msrc, t_prev_pt, t_pt, Scalar::all(255), nThick ,8,0); //原图上划线 prev_pt = pt; imshow(szTitle, Mmid); } if (event == CV_EVENT_RBUTTONUP) { destroyWindow(szTitle); } } int CCvImage::DrawLineOnImg(Mat Msrc, CvPoint& pStart, CvPoint& pEnd, char* szTitle/* = "画直线"*/, int nThick/* = 2*/) { m_Mmid.release(); Msrc.copyTo(m_Mmid); //显示原图 imshow(szTitle, m_Mmid); //鼠标回调函数 this->m_szTitle = szTitle; this->m_nThick = nThick; cvSetMouseCallback(szTitle, on_mouse_line, this); waitKey(0); pStart = m_prev_pt; pEnd = m_curr_pt; destroyWindow(szTitle); return 0; } int CCvImage::DrawLineOnBigImg(Mat Msrc, CvPoint& pStart, CvPoint& pEnd, int nScreenWidth/* = SCREEN_WIDTH*/, int nScreenHeight/* = SCREEN_HEIGHT*/, char* szTitle/* = "画直线"*/, int nThick/* = 2*/) { m_Mmid.release(); float fProportion; AutoSizeMat(Msrc, m_Mmid, fProportion, nScreenWidth, nScreenHeight); //显示原图 imshow(szTitle, m_Mmid); //鼠标回调函数 this->m_szTitle = szTitle; this->m_nThick = nThick; cvSetMouseCallback(szTitle, on_mouse_line, this); waitKey(0); pStart = m_prev_pt; pEnd = m_curr_pt; ResizePoint(pStart, fProportion); ResizePoint(pEnd, fProportion); destroyWindow(szTitle); return 0; } void on_mouse_line(int event, int x, int y, int flags, void* pParameters) { CCvImage* pthis = (CCvImage*)pParameters; //获取相关的参数 char* szTitle = pthis->m_szTitle; CvPoint curr_pt; CvPoint prev_pt = pthis->m_prev_pt; //注意这里不是引用 int nThick = pthis->m_nThick; Mat& Mmid = pthis->m_Mmid; if(!Mmid.data) return; Mat Mori; 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); } else if ( event == CV_EVENT_MOUSEMOVE && (flags & CV_EVENT_FLAG_LBUTTON)) //判断移动鼠标并且左拖拽 { CvPoint pt = cvPoint(x, y); if ( prev_pt.x < 0) { prev_pt = pt; } Mori.release(); Mmid.copyTo(Mori); line(Mori, prev_pt, pt, Scalar::all(255), nThick ,8,0); //原图上划线 curr_pt = pt; pthis->m_prev_pt = prev_pt; pthis->m_curr_pt = pt; imshow(szTitle, Mori); } if (event == CV_EVENT_RBUTTONUP) { destroyWindow(szTitle); } } int CCvImage::DrawRectOnImg(Mat Msrc, CvRect& rect, char* szTitle/* = "画矩形"*/, int nThick/* = 2*/) { m_Mmid.release(); Msrc.copyTo(m_Mmid); //显示原图 imshow(szTitle,m_Mmid); //鼠标回调函数 this->m_szTitle = szTitle; this->m_nThick = nThick; cvSetMouseCallback(szTitle, on_mouse_rect, this); waitKey(0); destroyWindow(szTitle); rect = this->m_rect; return 0; } int CCvImage::DrawRectOnBigImg(Mat Msrc, CvRect& rect, int nScreenWidth/* = SCREEN_WIDTH*/, int nScreenHeight/* = SCREEN_HEIGHT*/, char* szTitle/* = "画矩形"*/, int nThick/* = 2*/) { m_Msrc.release(); m_Mmid.release(); m_Msrc = Msrc; AutoSizeMat(Msrc, m_Mmid, m_fProportion, nScreenWidth, nScreenHeight); //显示原图 imshow(szTitle,m_Mmid); //鼠标回调函数 this->m_szTitle = szTitle; this->m_nThick = nThick; cvSetMouseCallback(szTitle, on_mouse_rect, this); waitKey(0); destroyWindow(szTitle); rect = this->m_rect; ResizeRect(rect, m_fProportion); return 0; } void on_mouse_rect(int event, int x, int y, int flags, void* pParameters) { CCvImage* pthis = (CCvImage*)pParameters; //获取相关的参数 char* szTitle = pthis->m_szTitle; CvPoint& prev_pt = pthis->m_prev_pt; CvRect& rect = pthis->m_rect; CvRect& RoiRect = pthis->m_CRroi; int nThick = pthis->m_nThick; Mat& Mmid = pthis->m_Mmid; Mat& Msrc = pthis->m_Msrc; if(!Mmid.data) return; Mat Mori; 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); } else if ( event == CV_EVENT_MOUSEMOVE && (flags & CV_EVENT_FLAG_LBUTTON)) //判断移动鼠标并且左拖拽 { if (RoiRect.width == -1 || RoiRect.height == -1) { CvPoint pt = cvPoint(x, y); if ( prev_pt.x < 0) { prev_pt = pt; } Mori.release(); Mmid.copyTo(Mori); rectangle(Mori, prev_pt, pt, Scalar::all(255), nThick); rect = cvRect(prev_pt.x, prev_pt.y, pt.x - prev_pt.x, pt.y - prev_pt.y); imshow(szTitle, Mori); } else { if (pthis->m_Msrc.cols != pthis->m_Mmid.cols || pthis->m_Msrc.rows != pthis->m_Mmid.rows) { IplImage Isrc = pthis->m_Msrc; CvPoint pt = cvPoint(x, y); Mat Mr(pthis->m_Msrc, RoiRect); Mr.copyTo(Mori); rectangle(Mori, prev_pt, pt, Scalar::all(255), nThick); rect = cvRect(RoiRect.x + prev_pt.x, RoiRect.y + prev_pt.y, pt.x - prev_pt.x, pt.y - prev_pt.y); pthis->ResizeRect(rect, 1 / pthis->m_fProportion); imshow(szTitle, Mori); } } } if (event == CV_EVENT_LBUTTONDBLCLK) { if (RoiRect.width == -1 || RoiRect.height == -1) { if (pthis->m_Msrc.cols != pthis->m_Mmid.cols || pthis->m_Msrc.rows != pthis->m_Mmid.rows) { IplImage Isrc = pthis->m_Msrc; CvPoint pt = cvPoint(x, y); RoiRect = cvRect(x * pthis->m_fProportion - pthis->m_Mmid.cols / 2, y * pthis->m_fProportion - pthis->m_Mmid.rows / 2, pthis->m_Mmid.cols, pthis->m_Mmid.rows); pthis->ValidRect(RoiRect, pthis->m_Mmid.cols, pthis->m_Mmid.rows, pthis->m_Msrc.cols, pthis->m_Msrc.rows); cvSetImageROI(&Isrc, RoiRect); cvShowImage(szTitle, &Isrc); cvResetImageROI(&Isrc); } } else { Mori.release(); Mmid.copyTo(Mori); imshow(szTitle, Mori); pthis->ResetRect(RoiRect); } } if (event == CV_EVENT_RBUTTONUP) { destroyWindow(szTitle); } } int CCvImage::GetMaskByCurve(Mat Msrc, Mat& Mdst, char* szTitle/* = "获取遮罩"*/) { m_Mmid.release(); Msrc.copyTo(m_Mmid); Mat mask(Msrc.rows, Msrc.cols, CV_8U, Scalar(255)); m_Mmask.release(); m_Mmask = mask; //显示原图 imshow(szTitle,m_Mmid); //鼠标回调函数 this->m_szTitle = szTitle; cvSetMouseCallback(szTitle, on_mouse_curve_mask, this); waitKey(0); m_Mmask.copyTo(Mdst); destroyWindow(szTitle); return 0; } void on_mouse_curve_mask(int event, int x, int y, int flags, void* pParameters) { CCvImage* pthis = (CCvImage*)pParameters; //获取相关的参数 char* szTitle = pthis->m_szTitle; CvPoint& prev_pt = pthis->m_prev_pt; CvRect& rect = pthis->m_rect; Mat& Mmid = pthis->m_Mmid; Mat& Mmask = pthis->m_Mmask; if(!Mmid.data) 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); } else if ( event == CV_EVENT_MOUSEMOVE && (flags & CV_EVENT_FLAG_LBUTTON)) //判断移动鼠标并且左拖拽 { CvPoint pt = cvPoint(x, y); if ( prev_pt.x < 0) { prev_pt = pt; } line(Mmask, prev_pt, pt, Scalar(0),2,8,0); //模板上划线 line(Mmid, prev_pt, pt, Scalar::all(255),2,8,0); //原图上划线 prev_pt = pt; imshow(szTitle, Mmid); } if (event == CV_EVENT_RBUTTONUP) { floodFill(Mmask, Point(x,y), Scalar(0));//填充抠图模板 } } int CCvImage::GetMaskByDaub(Mat Msrc, Mat& Mdst, int nRadius/* = 20*/, char* szTitle/* = "获取遮罩"*/) { m_Mmid.release(); Msrc.copyTo(m_Mmid); Mat mask(Msrc.rows, Msrc.cols, CV_8U, Scalar(0)); m_Mmask.release(); m_Mmask = mask; //显示原图 imshow(szTitle,m_Mmid); //鼠标回调函数 this->m_szTitle = szTitle; this->m_nThick = nRadius; cvSetMouseCallback(szTitle, on_mouse_daub, this); waitKey(0); m_Mmask.copyTo(Mdst); destroyWindow(szTitle); return 0; } void on_mouse_daub(int event, int x, int y, int flags, void* pParameters) { CCvImage* pthis = (CCvImage*)pParameters; //获取相关的参数 char* szTitle = pthis->m_szTitle; CvPoint& prev_pt = pthis->m_prev_pt; int nThick = pthis->m_nThick; Mat& Mmid = pthis->m_Mmid; if(!Mmid.data) 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); } else if ( event == CV_EVENT_MOUSEMOVE && (flags & CV_EVENT_FLAG_LBUTTON)) //判断移动鼠标并且左拖拽 { CvPoint pt = cvPoint(x, y); if ( prev_pt.x < 0) { prev_pt = pt; } line(pthis->m_Mmask, prev_pt, pt, Scalar(255), nThick, 8, 0); //模板上划线 line(Mmid, prev_pt, pt, Scalar::all(255), nThick, 8, 0); //原图上划线 prev_pt = pt; imshow(szTitle, Mmid); } if (event == CV_EVENT_RBUTTONUP) { destroyWindow(szTitle); } } int CCvImage::ResetRect(CvRect& rect, int nValue/* = -1*/) { rect.x = nValue; rect.y = nValue; rect.width = nValue; rect.height = nValue; return 0; } int CCvImage::ResizePoint(CvPoint& Csrc, float fProportion) { Csrc.x *= fProportion; Csrc.y *= fProportion; return 0; } int CCvImage::ResizeRect(CvRect& Csrc, float fProportion) { Csrc.x *= fProportion; Csrc.y *= fProportion; Csrc.width *= fProportion; Csrc.height *= fProportion; return 0; } int CCvImage::ResizeRect(CvRect& rect, int nExpandWidthPixs/* = 0*/, int nExpandHeightPixs/* = 0*/) { rect.x -= nExpandWidthPixs; rect.y -= nExpandHeightPixs; rect.width += nExpandWidthPixs * 2; rect.height += nExpandHeightPixs * 2; return 0; } int CCvImage::ResizeRect(CvRect& rect, int nLeft, int nRight, int nUp, int nDown) { rect.x -= nLeft; rect.y -= nUp; rect.width += nLeft + nRight; rect.height += nUp + nDown; return 0; } int CCvImage::ValidExpandValue(const CvRect& CRroi, int& nLeft, int& nRight, int& nUp, int& nDown, int nWidth, int nHeight) { if (CRroi.x < nLeft) { nLeft = CRroi.x; } if (CRroi.x + CRroi.width + nRight > nWidth) { nRight = nWidth - CRroi.x - CRroi.width; } if (CRroi.y < nUp) { nUp = CRroi.y; } if (CRroi.y + CRroi.height + nDown > nHeight) { nDown = nHeight - CRroi.y - CRroi.height; } return 0; } int CCvImage::ValidRect(CvRect& rect, int nWidth, int nHeight) { if (rect.width < 0 && rect.height < 0 && rect.x >= 0 && rect.x <= nWidth && rect.y >= 0 && rect.y <= nWidth) { //反向操作 rect.x += rect.width; rect.y += rect.height; rect.width = -rect.width; rect.height = -rect.height; } if (rect.x < 0) { rect.x = 0; } if (rect.x > nWidth) { rect.x = nWidth; } if (rect.y > nHeight) { rect.y = nHeight; } if (rect.y < 0) { rect.y = 0; } if (rect.x + rect.width > nWidth) { rect.width = nWidth - rect.x; } if (rect.y + rect.height > nHeight) { rect.height = nHeight - rect.y; } return 0; } int CCvImage::ValidRect(CvRect& rectSmall, const int nRectWidth, const int nRectHeight, const int nPicWidth, const int nPicHeight) { ValidRect(rectSmall, nPicWidth, nPicHeight); if (rectSmall.x + nRectWidth > nPicWidth) { rectSmall.x = nPicWidth - nRectWidth; rectSmall.width = nRectWidth; } if (rectSmall.y + nRectHeight > nPicHeight) { rectSmall.y = nPicHeight - nRectHeight; rectSmall.height = nRectHeight; } return 0; }