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;
}
时间: 2024-10-29 00:30:53

OpenCV常用图像操作和鼠标操作(双11版本)的相关文章

OpenCV常用图像操作和鼠标操作

最近的工作经常需要对图像进行操作,也需要用鼠标对图像进行各种操作,于是自己整理和编写了这个类,总结了常用的基于OpenCV对图像进行的操作. 这个类我也将继续完善和丰富下去,需要的朋友可以直接使用. 如果有什么疏漏的地方还请多多指教. 首先是头文件: /* ******* ccv.h ********** ********* opencv常用操作函数声明 ********** */ /* author: autumoon */ #ifndef _CCV_H_ #define _CCV_H_ #i

selenium_对浏览器操作、鼠标操作等总结

1 控制浏览器 Selenium 主要提供的是操作页面上各种元素的方法,但它也提供了操作浏览器本身的方法,比如浏览器的大小以及浏览器后退.前进按钮等. 1.1 控制浏览器窗口大小 在不同的浏览器大小下访问测试站点,对测试页面截图并保存,然后观察或使用图像比对工具对被测页面的前端样式进行评测.比如可以将浏览器设置成移动端大小(480x800),然后访问移动站点,对其样式进行评估:WebDriver 提供了set_window_size() 方法来设置浏览器的大小. 例子: #coding=utf-

MFC常用的字符串、文件、目录操作(双11版本)

修改日志: 1.增加了list容器存储: 2.修改了IsFile 和 IsDir的实现,使区别于IfExistFile和IfExistDir; 3.修改了部分函数的名称: 4.其他细节修改: 首先是头文件: /* ******* StrDirFile.h ********** ********* 字符串.文件.目录操作函数声明 ********** */ /* author: autumoon */ #ifndef _STR_DIR_FILE_ #define _STR_DIR_FILE_ #p

如何用OpenCV跟踪鼠标操作

转载:如何用OpenCV跟踪鼠标操作 http://blog.skyoung.org/2014/05/01/how-to-track-mouse/ 在视频第一帧手动标记出目标的位置是在线视觉跟踪中最基本的一个操作,实现这个操作需要检测鼠标的移动和点击事件.OpenCV提供了setMouseCallback这个函数来响应鼠标的动作,并返回鼠标在绑定窗口上的坐标位置.下面就这个函数的使用做一个简单的介绍. 首先,setMouseCallback的C++函数声明如下: 1 void onMouse(i

实验2014062701:opencv对图像的点操作

#include<Windows.h>#include<cv.h>#include<highgui.h>#include <cxcore.h>int main(){    IplImage* img = cvLoadImage("1.jpg");    IplImage* dst = cvCreateImage(cvGetSize(img),img->depth,1);    cvNamedWindow("GRAY&quo

八.使用OpenCv对图像进行平滑操作

1.cvSmooth函数 函数 cvSmooth 可使用简单模糊.简单无缩放变换的模糊.中值模糊.高斯模糊.双边滤波的任何一种方法平滑图像.每一种方法都有自己的特点以及局限. 没有缩放的图像平滑仅支持单通道图像,并且支持8位到16位的转换(与cvSoble和cvaplace相似)和32位浮点数到32位浮点数的变换格式. 简单模糊和高斯模糊支持 1- 或 3-通道, 8-比特 和 32-比特 浮点图像.这两种方法可以(in-place)方式处理图像. 中值和双向滤波工作于 1- 或 3-通道, 8

opencv学习笔记(01)——操作图像的像素

1 #include <opencv2\core\core.hpp> 2 #include <opencv2\highgui\highgui.hpp> 3 #include <opencv2\imgproc\imgproc.hpp> 4 #include <iostream> 5 6 7 void salt(cv::Mat& image, int n) 8 { 9 10 for(int k=0; k<n; k++) 11 { 12 13 int

Opencv中图像的遍历与像素操作

Opencv中图像的遍历与像素操作 OpenCV中表示图像的数据结构是cv::Mat,Mat对象本质上是一个由数值组成的矩阵.矩阵的每一个元素代表一个像素,对于灰度图像,像素是由8位无符号数来表示(0代表黑,255代表白):对于彩色图像,每个像素是一个三元向量,即由三个8位无符号数来表示三个颜色通道(Opencv中顺次为蓝.绿.红). 我们先来介绍下cv::Mat类的获取像素的成员函数at(),其函数原型如下: template<typename _Tp> _Tp& at(int i0

UiPath鼠标操作图像的介绍和使用

一.鼠标(mouse)操作的介绍 模拟用户使用鼠标操作的一种行为,例如单击,双击,悬浮.根据作用对象的不同我们可以分为对元素的操作.对文本的操作和对图像的操作 二.鼠标对图像的操作在UiPath中的使用 1.打开设计器,在设计库中新建一个Sequence,为序列命名及设置Sequence存放的路径 2.在Activities中搜索open browser,并将其拖至设计区,且设置打开网站,运行该流程“https://www.baidu.com/” 3.  在Activities中搜索mouse,