开发者

How to increase contours precision?

开发者 https://www.devze.com 2023-04-10 05:21 出处:网络
I am working on a project using OpenCV. I need to precisely crop out some objects from HD photos. I\'m using a quad tree to cut my photos in pieces and then I calculate the homogeneity of each quad to

I am working on a project using OpenCV. I need to precisely crop out some objects from HD photos. I'm using a quad tree to cut my photos in pieces and then I calculate the homogeneity of each quad to determine if a piece of the object is in the quad. I apply some filters as Canny with different thresholds depending on the homogeneity of the quad. I hope this description is understandable.

This algorithm works for certain kinds of objects but I'm stuck with some others. Here some example of my problems: I would like a way to flatten my contours. The first screenshot is a after using the canny filter and a floodfill. The second is the final mask result.

http://pastebin.com/91Pgrd2D


To achieve this result, I use cvFindContours() so I have the con开发者_如何学编程tours but I can't find a way to handle them like I want.


Maybe you could use some kind of an average filter to approximate the curve and then use AproxPoly with a small gradient to smooth it. Here is a similar method:

void AverageFilter(CvSeq * contour, int buff_length)
{
    int n = contour->total, i, j;
    if (n > buff_length)
    {
        CvPoint2D32f* pnt;
        float* sampleX = new float[buff_length];
        float* sampleY = new float[buff_length];

        pnt = (CvPoint2D32f*)cvGetSeqElem(contour, 0);
        for (i = 0; i < buff_length; i++)
        {
            if (i >= buff_length / 2)
            {
                pnt = (CvPoint2D32f*)cvGetSeqElem(contour, i + 1 - buff_length / 2 );
            }
            sampleX[i] = pnt->x;
            sampleY[i] = pnt->y;
        }

        float sumX = 0, sumY = 0;

        for (i = 1; i < n; i++)
        {
            pnt = (CvPoint2D32f*)cvGetSeqElem(contour, i);
            for (j = 0; j < buff_length; j++)
            {
                sumX += sampleX[j];
                sumY += sampleY[j];
            }
            pnt->x = sumX / buff_length;
            pnt->y = sumY / buff_length;
            for (j = 0; j < buff_length - 1; j++)
                {
                    sampleX[j] = sampleX[j+1];
                    sampleY[j] = sampleY[j+1];
                }
            if (i <= (n - buff_length / 2))
            {
                pnt = (CvPoint2D32f*)cvGetSeqElem(contour, i + buff_length / 2 + 1);
                sampleX[buff_length - 1] = pnt->x;
                sampleY[buff_length - 1] = pnt->y;
            }
            sumX = 0;
            sumY = 0;
        }
        delete[] sampleX;
        delete[] sampleY;
    }
} 

You give it the contour and the size of the buffer of points that you want to do the average on. If you think the contour is too thick because some of the averaged points are bundled together too close, then that's where Aproxpoly comes in because it reduces the number of points. But choose an appropriate gradient so you don't make it too edgy.

srcSeq = cvApproxPoly(srcSeq,sizeof(CvContour),storage, CV_POLY_APPROX_DP, x, 1);

Play around with 'x' to see how you get better results.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号