OpenCV基础优化之使用drawContours

来源:互联网 发布:巴宝莉格子侵权淘宝 编辑:程序博客网 时间:2024/04/30 07:31

OpenCV基础优化之使用drawContours

本文由 @lonelyrains出品,转载请注明出处。
文章链接: http://blog.csdn.net/lonelyrains/article/details/50215549

最近要使用一个基于点组成的轮廓的过滤效果。即轮廓内的点全部保留,外部的点全部变黑。
一开始想到的做法是按顺时针顺序输入轮廓点,然后将frame内所有的点都按照对所有边的顺时针法则判断是否保留。例如如下代码中,取一点pTemp,如果pTemp->p0->p1是顺时针,则可能保留pTemp,否则“拉黑”;直到每个点对所有的轮廓边都做同样的操作,才决定该点是拉黑还是保留。
虽然加了openmp优化,但是效果并不好。

// 区域外的部分全部置为0 // vector p 顺序为顺时针int filterArea(cv::Mat &frame, vector<cv::Point> &p){    //if(p.size() == 4)    {        /* 四点的顺序是:        p0 ----- p1        |        |        |        |        |        |        p3 ----- p2        */        int nc = frame.channels();#pragma omp parallel for        for (int j = 0; j < frame.rows; j++)        {            uchar* data = frame.ptr<uchar>(j);            for (int i = 0; i < frame.cols*nc; i += nc)            {                // 可能不是一个正矩形,不能简单的判断x/y,而是应该判断是否在直线一侧                //              if(i/nc < p[0].x || j < p[0].y || i/nc > p[3].x || j > p[3].y)                bool bfilterPoint = false;                for (int k = p.size() - 1; k >= 0; k--)                {                    if (k != 0)                    {                        if (isClockwise(cv::Point(i / nc, j), p[k], p[k - 1]) == false)                        {                            bfilterPoint = true;                        }                    }                    else                    {                        if (isClockwise(cv::Point(i / nc, j), p[k], p[p.size() - 1]) == false)                        {                            bfilterPoint = true;                        }                    }                }                if (bfilterPoint == true)                {                    for (int k = 0; k < nc; k++)                    {                        data[i / nc*nc + k] = 0;                    }                }            }        }    }    return 0;}

优化之后的做法非常简单,直接轮廓填充出一个mask,然后按位与原矩阵

// 区域外的部分全部置为0 // vector p 顺序为顺时针int filterArea(cv::Mat &frame, vector<cv::Point> &p){    cv::Mat mask = cv::Mat::zeros(frame.size(), frame.type());    imshow("mask1", mask);    vector< vector<cv::Point> > contours;    vector<cv::Point>contour;    for (int i = 0; i < p.size(); i++)    {        contour.push_back(p[i]);    }    contour.push_back(p[0]);    contours.push_back(contour);    for (int i = 0; i < contours.size(); i++)    {        cv::drawContours(mask, contours, i, cv::Scalar(255, 255, 255), CV_FILLED, 8);    }    imshow("mask", mask);    frame = frame & mask;    mask.release();    return 0;}

代码又少,逻辑又清晰,输入要求又简单,不需要按顺序,而且使用效率很高。

0 2
原创粉丝点击