[转]Opencv鼠标交互等

  • [转]OpenCV鼠标交互(原文链接已失效)
    绘制任意形状并获得区域图像:原理同上,使用CvSeq记录轨迹点,然后用cvFillConvexPoly填充多边形区域形成掩模,最后用cvCopy拷贝区域图像。支持两种绘图模式,描点式(如PS之钢笔)和拖动式:
#include <opencv2\opencv.hpp>
//#include <opencv\cvaux.h>
#include <opencv\cxcore.h>
#include <opencv\highgui.h>
#include <opencv\cv.h>

#include <iostream>

using namespace std;
using namespace cv;

struct MouseArgs{
    IplImage* img;
    CvPoint p_start;
    CvPoint p_end;
    CvSeq* seq;
    CvMemStorage* storage;
    int points;
    // init
    MouseArgs() :img(0), points(0){
        p_start = cvPoint(-1, -1);
        p_end = cvPoint(-1, -1);
        storage = cvCreateMemStorage(0);
        seq = cvCreateSeq(CV_32SC2, sizeof(CvSeq), sizeof(CvPoint), storage);
    }
    // destroy
    void Destroy(){
        if (!img)
            cvReleaseImage(&img);
        cvReleaseMemStorage(&storage);
        seq = NULL;
        img = NULL;
    }
};

void MouseDraw(int event, int x, int y, int flags, void*param);

int main(int argc, char** argv)
{
    // loading image
    char* imf = argc >= 2 ? argv[1] : "test.png";

    IplImage* pImg_org = cvLoadImage(imf, 1);
    if (!pImg_org){
        cout << "cann't load image!" << endl;
        return-1;
    }

    // 回调参数
    MouseArgs* m_arg = new MouseArgs();
    m_arg->img = cvCloneImage(pImg_org);

    // 画图窗口
    cvNamedWindow("Draw ROI", CV_WINDOW_AUTOSIZE);

    // 设置鼠标事件的回调函数
    cvSetMouseCallback("Draw ROI",
        MouseDraw,
        (void*)m_arg);

    // 拖动鼠标作画
    while (1)
    {
        cvShowImage("Draw ROI", m_arg->img);
        // 按 esc 键退出绘图模式,获得矩形
        if (cvWaitKey(100) == 27)
            break;

    }

    // 输出
    if (m_arg->points < 1)
        return 0;
    cout << m_arg->points << endl;
    for (int i = 0; i < m_arg->points; i++){
        CvPoint line = *CV_GET_SEQ_ELEM(CvPoint, m_arg->seq, i);
        cout << line.x << "," << line.y << "; ";
    }

    // 获得掩模
    IplImage* mask = cvCreateImage(cvGetSize(pImg_org), 8, 1);
    cvZero(mask);

    CvPoint* PointArr = new CvPoint[m_arg->points];
    cvCvtSeqToArray(m_arg->seq, PointArr);
    cvFillConvexPoly(mask, PointArr, m_arg->points, cvScalarAll(255), CV_AA, 0);
    delete[] PointArr;
    cvNamedWindow("Mask", CV_WINDOW_AUTOSIZE);
    cvShowImage("Mask", mask);

    // 获得区域
    IplImage* roi = cvCreateImage(cvGetSize(pImg_org), 8, 3);
    cvCopy(pImg_org, roi, mask);
    cvNamedWindow("ROI", CV_WINDOW_AUTOSIZE);
    cvShowImage("ROI", roi);

    //
    cvWaitKey(0);
    cvDestroyWindow("Draw ROI");
    cvDestroyWindow("Mask");
    cvDestroyWindow("ROI");

    //
    m_arg->Destroy();
    delete m_arg;
    cvReleaseImage(&pImg_org);
    cvReleaseImage(&mask);
    cvReleaseImage(&roi);
    //
    getchar();
    return 0;
}

// 描点式
/* void MouseDraw(int event,int x,int y,int flags,void*param) { MouseArgs* m_arg = (MouseArgs*) param; if( !m_arg->img ) return; if( event == CV_EVENT_LBUTTONUP || !(flags & CV_EVENT_FLAG_LBUTTON) ) { m_arg->p_end = m_arg->p_start; } else if( event == CV_EVENT_LBUTTONDOWN ) { m_arg->p_start = cvPoint(x,y); cvSeqPush( m_arg->seq, &m_arg->p_start); // 描点记录 m_arg->points += 1; if(m_arg->p_start.x>0 && m_arg->p_end.x>0){ cvLine( m_arg->img, m_arg->p_start, m_arg->p_end, cvScalar(0,0,255) ); cvLine( m_arg->img, m_arg->p_start, m_arg->p_start, cvScalar(128,0,255) ); } } } */
// 拖动式
void MouseDraw(int event, int x, int y, int flags, void*param)
{
    MouseArgs* m_arg = (MouseArgs*)param;
    if (!m_arg->img)
        return;

    if (event == CV_EVENT_LBUTTONUP || !(flags & CV_EVENT_FLAG_LBUTTON))
    {
        m_arg->p_start = cvPoint(x, y);
    }
    else if(event == CV_EVENT_LBUTTONDOWN)
    {
        m_arg->p_start = cvPoint(x, y);
        cvSeqPush(m_arg->seq, &m_arg->p_start);
        m_arg->points += 1;
        if (m_arg->p_start.x>0 && m_arg->p_end.x>0){
            cvLine(m_arg->img, m_arg->p_start, m_arg->p_start, cvScalar(128, 0, 255));
        }
    }
        else if(event == CV_EVENT_MOUSEMOVE && (flags & CV_EVENT_FLAG_LBUTTON))
        {
            CvPoint pt = cvPoint(x, y);
            if (m_arg->p_start.x > 0){
                cvLine(m_arg->img, m_arg->p_start, pt, cvScalar(128, 0, 255));
                m_arg->p_start = pt;
                cvSeqPush(m_arg->seq, &m_arg->p_start);
                m_arg->points += 1;
            }

        }

}
  • 如何把 CvSeq 转去CvPoint和如何从CvPoint写入CvSeq
CvPoint* point = new CvPoint[length]; //分配轮廓点
 int i;
 for (i = 0; i < length; i++) //length = contours->total
        point[i]=*CV_GET_SEQ_ELEM(CvPoint,contours,i);//在当前contour下一个一个的读取数据

CvMemStorage* storage1 = cvCreateMemStorage(0);//开辟16K的存储空间
CvSeq* seq = cvCreateSeq( CV_32SC2,  
               sizeof(CvSeq),
              sizeof(CvPoint),
              storage1 );//创建序列,定义格式
 for( i = 0; i       
     cvSeqPush( seq,&point[i]);//压栈,把数组指针指向的point点放入序列

你可能感兴趣的:(鼠标,opencv)