如何提高轮廓精度?

发布于 2024-12-07 15:52:02 字数 432 浏览 1 评论 0原文

我正在使用 OpenCV 进行一个项目。我需要从高清照片中精确地裁剪出一些物体。 我使用四边形树将照片切成碎片,然后计算每个四边形的同质性以确定物体的一部分是否在四边形中。 我根据四边形的同质性应用了一些具有不同阈值的 Canny 滤波器。 我希望这个描述是可以理解的。

该算法适用于某些类型的对象,但我对其他一些对象感到困惑。 这是我的问题的一些例子:我想要一种方法来压平我的轮廓。 第一个屏幕截图是使用 canny 过滤器和洪水填充后的屏幕截图。第二个是最终的掩模结果。

http://pastebin.com/91Pgrd2D


为了实现此结果,我使用 cvFindContours() 所以我有轮廓,但我找不到像我想要的那样处理它们的方法。

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 contours but I can't find a way to handle them like I want.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

记忆消瘦 2024-12-14 15:52:02

也许您可以使用某种平均滤波器来近似曲线,然后使用具有小梯度的 AproxPoly 来平滑它。
这是一个类似的方法:

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

给它轮廓和要进行平均的点缓冲区的大小。
如果您认为轮廓太粗,因为一些平均点捆绑在一起太近,那么这就是 Aproxpoly 的用武之地,因为它减少了点的数量。
但要选择合适的渐变,这样就不会显得太前卫。

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

尝试使用“x”来看看如何获​​得更好的结果。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文