zoukankan      html  css  js  c++  java
  • OpenCV常用图像操作和鼠标操作

    最近的工作经常需要对图像进行操作,也需要用鼠标对图像进行各种操作,于是自己整理和编写了这个类,总结了常用的基于OpenCV对图像进行的操作。

    这个类我也将继续完善和丰富下去,需要的朋友可以直接使用。

    如果有什么疏漏的地方还请多多指教。


    首先是头文件:

    /* ******* 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;
        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 AutoSizeMat(Mat& Msrc, Mat& Mdst, float& fProportion, int nScreenWidth = SCREEN_WIDTH, int nScreenHeight = SCREEN_HEIGHT);
        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 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 ResizeCvPoint(CvPoint& Csrc, float fProportion);
        int ResizeCvRect(CvRect& Csrc, float fProportion);
    
    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()
    {
        m_rect = cvRect(-1, -1, -1, -1);
        IInput = NULL;
    }
    
    CCvImage::CCvImage(char szImgPath[], int flags/* = 1*/)
    {
        m_rect = cvRect(-1, -1, -1, -1);
        IInput = NULL;
    
        m_Minput = imread(szImgPath, flags);
    }
    
    CCvImage::CCvImage(CString strImgPath, int flags/* = 1*/)
    {
        m_rect = cvRect(-1, -1, -1, -1);
        IInput = NULL;
    
        char* szImgPath;
    
    #ifdef _UNICODE
        USES_CONVERSION;
        szImgPath = W2A(strCstring);
    #else
        szImgPath = (LPSTR)(LPCTSTR)strImgPath;
    #endif
    
        m_Minput = imread(szImgPath, flags);
    }
    
    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::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*/)
    {
        Mat Mresize;
        float fProportion;
        AutoSizeMat(m_Minput, Mresize, fProportion, nScreenWidth, nScreenHeight);
    
        imshow(szTitle, Mresize);
        waitKey();
    
        if (bAutoClose)
        {
            destroyWindow(szTitle);
        }
    
        return 0;
    }
    
    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::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->ResizeCvPoint(t_prev_pt, pthis->m_fProportion);
            pthis->ResizeCvPoint(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;
        ResizeCvPoint(pStart, fProportion);
        ResizeCvPoint(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_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_rect, this);
        waitKey(0);
    
        destroyWindow(szTitle);
    
        rect = this->m_rect;
        ResizeCvRect(rect, 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;
        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);
            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);
        }
    
        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::ResizeCvPoint(CvPoint& Csrc, float fProportion)
    {
        Csrc.x *= fProportion;
        Csrc.y *= fProportion;
    
        return 0;
    }
    
    int CCvImage::ResizeCvRect(CvRect& Csrc, float fProportion)
    {
        Csrc.x *= fProportion;
        Csrc.y *= fProportion;
        Csrc.width *= fProportion;
        Csrc.height *= fProportion;
    
        return 0;
    }
  • 相关阅读:
    卸载office密钥的命令
    断言的使用
    stm32的NVIC是什么?
    STM32 Cube mx 安装
    不用移位计算获得高位数据
    分组数据
    Vue Router
    存储过程
    js 中 json.stringfy()将对象、数组转换成字符串
    js中 json对象的转化 JSON.parse()
  • 原文地址:https://www.cnblogs.com/autumoonchina/p/3941504.html
Copyright © 2011-2022 走看看