zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    一位测友的真实面试题
    内部cms系统测试
    po模式
    描述器
    monkey命令
    进程管理工具supervisor
    webpack打包绝对路径引用资源和element ui字体图标不显示的解决办法
    pycharm flask debug调试接口
    应对ADT(Eclipse)的No more handles解决办法
    收集整理Android开发所需的Android SDK、开发中用到的工具、Android开发教程、Android设计规范,免费的设计素材等。
  • 原文地址:https://www.cnblogs.com/autumoonchina/p/4088726.html
Copyright © 2011-2022 走看看