在图片里可以,在视频里就不行了,代码如下:
/******************************************
* 使用说明: *
* 左键单击画点 *
* 右键自动闭合曲线 *
* 右键双击上色 *
******************************************/
#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));
}
}
}
是不是因为每次把image更新了,所以一直重复第一次按左键时的动作,请问怎么改,或者有没有其他方法