视频ROI多边形区域生成

操作步骤:1、按下任意键盘键,视频暂停播放

2、点击鼠标左键选取感兴趣区域

3、按任意键盘键,获取roi区域

代码亲测有效

//鼠标事件生成roi多边形区域
#include 
#include 
#include "stdlib.h"
#include "stdio.h"

//鼠标事件入参,可用头文件包含
typedef struct {
	IplImage* src1;
	IplImage* dst;

	int nPort;
	CvPoint pre_pt;
	CvPoint cur_pt;
	CvPoint first_pt;
	CvPoint finally_pt;

	int pointnum;
	CvPoint *point;
}MouseArgs;

//鼠标事件
void on_mouse(int event, int x, int y, int flags, void* ustc)
{
	MouseArgs *m_arg = (MouseArgs*)ustc;
	CvFont font;
	cvInitFont(&font, CV_FONT_HERSHEY_SIMPLEX, 0.5, 0.5, 0, 1, CV_AA);
	char temp[16];

	if (event == CV_EVENT_LBUTTONDOWN)
	{
		cvCopy(m_arg->dst, m_arg->src1, NULL);
		sprintf(temp, "(%d,%d)", x, y);
		m_arg->pre_pt = cvPoint(x, y);
		m_arg->point[m_arg->pointnum] = m_arg->pre_pt;

		if (m_arg->nPort == 0)
		{
			m_arg->first_pt = m_arg->pre_pt;
		}

		//画点和直线
		cvPutText(m_arg->src1, temp, m_arg->pre_pt, &font, cvScalar(0, 0, 0, 255));
		cvCircle(m_arg->src1, m_arg->pre_pt, 3, cvScalar(255, 0, 0, 0), CV_FILLED, CV_AA, 0);
		if (m_arg->nPort != 0)
		{
			cvLine(m_arg->src1, m_arg->cur_pt, m_arg->pre_pt, cvScalar(0, 255, 0, 0), 1, CV_AA, 0);
		}

		(m_arg->pointnum)++;
		(m_arg->nPort)++;
		cvShowImage("ON_MOUSE", m_arg->src1);
		cvCopy(m_arg->src1, m_arg->dst, NULL);
	}
	else if (event == CV_EVENT_MOUSEMOVE && (flags & CV_EVENT_FLAG_LBUTTON))
	{
		cvCopy(m_arg->dst, m_arg->src1, NULL);
		sprintf(temp, "(%d,%d)", x, y);
		m_arg->cur_pt = cvPoint(x, y);

		//画点和直线
		cvPutText(m_arg->src1, temp, m_arg->cur_pt, &font, cvScalar(0, 0, 0, 255));
		cvLine(m_arg->src1, m_arg->pre_pt, m_arg->cur_pt, cvScalar(0, 255, 0, 0), 1, CV_AA, 0);
		cvShowImage("ON_MOUSE", m_arg->src1);
	}
	else if (event == CV_EVENT_LBUTTONUP)
	{
		sprintf(temp, "(%d,%d)", x, y);
		m_arg->cur_pt = cvPoint(x, y);
		m_arg->finally_pt = m_arg->cur_pt;

		//画点和直线
		cvPutText(m_arg->src1, temp, m_arg->cur_pt, &font, cvScalar(0, 0, 0, 255));
		cvCircle(m_arg->src1, m_arg->cur_pt, 3, cvScalar(255, 0, 0, 0), CV_FILLED, CV_AA, 0);
		cvLine(m_arg->src1, m_arg->pre_pt, m_arg->cur_pt, cvScalar(0, 255, 0, 0), 1, CV_AA, 0);
		cvShowImage("ON_MOUSE", m_arg->src1);
		cvCopy(m_arg->src1, m_arg->dst, NULL);
	}
	else if (event == CV_EVENT_RBUTTONDOWN)
	{
		//画直线
		cvLine(m_arg->src1, m_arg->cur_pt, m_arg->first_pt, cvScalar(0, 255, 0, 0), 1, CV_AA, 0);
		cvShowImage("ON_MOUSE", m_arg->src1);
		cvCopy(m_arg->src1, m_arg->dst, NULL);
	}
}

//做roi区域
void CreateMask(IplImage* frame, IplImage* mask)
{
	uchar maskpixel;

	for (int h = 0; h < mask->height; h++)
	{
		for (int w = 0; w < mask->width; w++)
		{
			maskpixel = ((uchar*)(mask->imageData + h*mask->widthStep))[w];

			//屏蔽
			if (maskpixel == 0)
			{
				((uchar*)(frame->imageData + h*frame->widthStep))[w * 3 + 0] = 0;
				((uchar*)(frame->imageData + h*frame->widthStep))[w * 3 + 1] = 0;
				((uchar*)(frame->imageData + h*frame->widthStep))[w * 3 + 2] = 0;
			}
		}
	}
}

int main()
{
	CvCapture *cap = cvCaptureFromAVI("H:/SourceCodeV1.1/roi/Debug/15.avi");
	if (!cap) return 0;
	IplImage *frame;

	int pointnum = 0;
	CvPoint *point = (CvPoint *)malloc(sizeof(CvPoint)* 10);;
	IplImage *mask = NULL;

	int flag = 0;
	while (1)
	{
		frame = cvQueryFrame(cap);
		if (!frame) break;

		if (flag > 0)
		{
			//生成roi区域
			CreateMask(frame, mask);

			/* 可以去做,可以不去做
			int p;
			for (p = 0; p < pointnum; p++)
			{
			if (p != pointnum - 1)
			{
			cvLine(frame, point[p], point[p + 1], cvScalar(0, 255, 0, 0), 1, CV_AA, 0);
			}
			else
			{
			cvLine(frame, point[p], point[0], cvScalar(0, 255, 0, 0), 1, CV_AA, 0);
			}
			}
			*/
		}

		cvShowImage("ON_MOUSE", frame);
		if (cvWaitKey(1) > 0 && flag == 0)
		{
			//入参初始化
			MouseArgs *m_arg = (MouseArgs *)malloc(sizeof(MouseArgs));
			m_arg->nPort = 0;
			m_arg->pre_pt.x = -1;
			m_arg->pre_pt.y = -1;
			m_arg->cur_pt.x = -1;
			m_arg->cur_pt.y = -1;
			m_arg->first_pt.x = -1;
			m_arg->first_pt.y = -1;
			m_arg->finally_pt.x = -1;
			m_arg->finally_pt.y = -1;
			m_arg->src1 = cvCloneImage(frame);
			m_arg->dst = cvCloneImage(frame);
			m_arg->pointnum = 0;
			m_arg->point = (CvPoint *)malloc(sizeof(CvPoint)* 10);

			cvSetMouseCallback("ON_MOUSE", on_mouse, (void*)m_arg);
			cvShowImage("ON_MOUSE", frame);
			cvWaitKey(0);

			pointnum = m_arg->pointnum;
			memcpy(point, m_arg->point, sizeof(CvPoint)* 10);

			//生成mask图
			mask = cvCreateImage(cvSize(frame->width, frame->height), 8, 1);
			for (int h = 0; h < mask->height; h++)
			{
				for (int w = 0; w < mask->width; w++)
				{
					cvSet2D(mask, h, w, cvScalar(0, 0, 0, 0));
				}
			}
			cvFillConvexPoly(mask, m_arg->point, m_arg->pointnum, CV_RGB(255, 255, 255), CV_AA, 0);

			flag++;
			//释放内存
			cvReleaseImage(&(m_arg->src1));
			cvReleaseImage(&(m_arg->dst));
			free(m_arg->point);
			free(m_arg);
		}
		else if (cvWaitKey(1) > 0 && flag > 0)
		{
			break;
		}
	}

	//释放内存
	free(point);
	cvReleaseCapture(&cap);
	cvReleaseImage(&mask);
	return 0;
}

效果图

视频ROI多边形区域生成_第1张图片视频ROI多边形区域生成_第2张图片

你可能感兴趣的:(opencv)