qq_29898263 于 2016.04.04 09:49 提问

opencv在视频里画不规则图形

`````` /******************************************
*   使用说明：                            *
*   左键单击画点                          *
*   右键自动闭合曲线                      *
*   右键双击上色                          *
******************************************/
#include <string>
#include <list>
#include <vector>
#include <cmath>
#include<opencv2/opencv.hpp>

using namespace std;
using namespace cv;
void my_mouse_callback(int event, int x, int y, int flags, void *param);
CvPoint point_1, point_2, point_3;
int ymin = 0;
int ymax = 0;
bool drawing_switch = false;
vector<CvPoint> point;
VideoCapture cap("test.mp4");/*0*/
Mat image;
Mat image = imread("test.jpg");//改用视频时将这行注释
Mat temp;

void draw_line(Mat&img)
//画线
{
line(img, point_1, point_2, cvScalar(0x00, 0x00, 0xff)); /*red*/ //函数主体是line函数
}

typedef struct tagEDGE
{
double xi;
double dx;
int ymax;
bool operator <(tagEDGE &e)
{
return xi<e.xi;
}
}EDGE;//边

void GetMinMax(vector<CvPoint> &py, int &ymin, int &ymax);
void InitNewEdgeTable(vector< list<EDGE> > &nTable, vector<CvPoint> &py, int ymin, int ymax);
void CreateTable(vector< list<EDGE> > &nTable, int ymin, int ymax);
void Painting(Mat&img, vector< list<EDGE> > &nTable, int ymin, int ymax);

int main()
{
point_1 = cvPoint(0, 0);
point_2 = cvPoint(0, 0);
point_3 = cvPoint(0, 0);//进行点的初始化

namedWindow("Box Example");
cvSetMouseCallback("Box Example", my_mouse_callback, (void *)&image);
while (1)
{
/*cap >> image;*/
image.copyTo(temp);
if (drawing_switch) draw_line(temp);
imshow("Box Example", temp);
waitKey(30);
}
return 0;
}

void my_mouse_callback(int event, int x, int y, int flags, void *param)

{
Mat& img = *(cv::Mat*)param;
switch (event)
{
case CV_EVENT_MOUSEMOVE:
if (drawing_switch) point_2 = cvPoint(x, y); break;

case CV_EVENT_LBUTTONDOWN:
draw_line(image);
point_2 = point_1;
point_1 = cvPoint(x, y);
point.push_back(point_1);
if (!drawing_switch)point_3 = point_1;
circle(image, point_1, 1, cvScalar(0, 0, 255));
drawing_switch = true; break;
case CV_EVENT_RBUTTONDOWN://右键封闭多边形
point_2 = point_3;
draw_line(image);
drawing_switch = false; break;
case CV_EVENT_RBUTTONDBLCLK://右键双击上色
GetMinMax(point, ymin, ymax);//获取多边形的最小最大y值
vector< list<EDGE> > nTable(ymax - ymin + 1);
InitNewEdgeTable(nTable, point, ymin, ymax); //初始化边表
CreateTable(nTable, ymin, ymax);//创建每一扫描线所对应的边，并排序
Painting(image, nTable, ymin, ymax);//上色
break;
}
}

void GetMinMax(vector<CvPoint> &py, int &ymin, int &ymax)
//获取多边形的最小最大y值
{

for (vector<CvPoint>::iterator iter = py.begin(); iter != py.end(); ++iter)
{

if ((*iter).y<ymin)
ymin = (*iter).y;
if ((*iter).y>ymax)ymax = (*iter).y;

}

}

void InitNewEdgeTable(vector< list<EDGE> > &nTable,
vector<CvPoint> &py, int ymin, int ymax)
//初始化边表
{

EDGE e;
vector<CvPoint>::iterator iter = py.begin();
for (vector<CvPoint>::size_type i = 0; i<py.size(); i++)
{

const CvPoint& ps = *(iter + i);
const CvPoint& pe = *(iter + (i + 1) % py.size());
if (pe.y != ps.y)
{

e.dx = double(pe.x - ps.x) / double(pe.y - ps.y);
if (pe.y>ps.y)
{

e.xi = ps.x;
e.ymax = pe.y;
nTable[ps.y - ymin].push_front(e);

}
else
{

e.xi = pe.x;
e.ymax = ps.y;
nTable[pe.y - ymin].push_front(e);

}

}

}

}

void CreateTable(vector< list<EDGE> > &nTable, int ymin, int ymax)
//创建每一扫描线所对应的边，并排序
{

EDGE e;
for (int y = ymin + 1; y <= ymax; y++)
{

for (list<EDGE>::iterator iter = nTable[y - 1].begin(); iter != nTable[y - 1].end(); iter++)
{

if ((*iter).ymax>y)
{

e.xi = (*iter).xi + (*iter).dx;
e.dx = (*iter).dx;
e.ymax = (*iter).ymax;
nTable[y].push_back(e);

}

}
nTable[y - 1].sort();

}

}

void Painting(Mat&img, vector< list<EDGE> > &nTable, int ymin, int ymax)
//上色
{

for (int y = ymin; y <= ymax; y++)
{

for (list<EDGE>::iterator iter = nTable[y].begin(); iter != nTable[y].end(); ++iter)
{

int x1 = int(ceil((*iter).xi));
++iter;
int x2 = int(floor((*iter).xi));
for (int i = x1; i <= x2; ++i)
circle(img, cvPoint(i, y), 1, cvScalar(0, 0, 255));

}

}

}
``````

1个回答

wangyaninglm      2016.04.10 17:51