[轉]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;
            }

        }

}
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點放入序列
發佈了37 篇原創文章 · 獲贊 12 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章