2 qq 29898263 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));

        }

    }



}

是不是因为每次把image更新了,所以一直重复第一次按左键时的动作,请问怎么改,或者有没有其他方法

1个回答

wangyaninglm
wangyaninglm   Ds   Rxr 2016.04.10 17:51
已采纳

你这个用视频的话,你VideoCapture的这个对象,每次读一帧到mat中去,你画图也是针对这样一帧进行画,没等你画完,下一帧就过去了,这个你只能是
对背景上进行绘制,完后用背景和前景进行合成,最后才是和你在图片上画画一个效果

Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!