- [转]OpenCV鼠标交互(原文链接已失效)
绘制任意形状并获得区域图像:原理同上,使用CvSeq记录轨迹点,然后用cvFillConvexPoly填充多边形区域形成掩模,最后用cvCopy拷贝区域图像。支持两种绘图模式,描点式(如PS之钢笔)和拖动式:
#include <opencv2\opencv.hpp>
#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;
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);
}
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)
{
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);
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_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++)
point[i]=*CV_GET_SEQ_ELEM(CvPoint,contours,i);
CvMemStorage* storage1 = cvCreateMemStorage(0);
CvSeq* seq = cvCreateSeq( CV_32SC2,
sizeof(CvSeq),
sizeof(CvPoint),
storage1 );
for( i = 0; i
cvSeqPush( seq,&point[i]);