OpenCV基础优化之使用drawContours

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;
}

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

你可能感兴趣的:(优化,opencv)