处理轮廓中的像素(OpenCV)?

12

我已经从一张图片中提取了轮廓,想要专门处理轮廓中的像素。我需要找到轮廓中像素值的总和(而不是面积)。OpenCV只支持矩形形状的ROI,所以我不知道该怎么做。cvSum也只接受完整的图像,并没有掩膜选项,所以我有点迷失如何继续。是否有人有关于如何找到特定轮廓中像素值总和的建议?


轮廓表示是什么?像素坐标?图像/掩模?为什么不能只循环遍历像素? - Alexey Frunze
很抱歉,我不太明白这个问题。轮廓由一系列点组成,围绕着特定的区域。我不知道如何只是遍历像素。轮廓可以是任何形状 - 从人体轮廓到狗的轮廓 - 没有固定的形状意味着我无法真正地“循环”。 - fdh
如果轮廓的像素以某个数组中的坐标给出,您可以循环该数组,取出其中的坐标,然后查看具有这些坐标的图像像素。如果轮廓在图像中,并且其像素具有特定的颜色(或范围),以将其与其他所有内容区分开来,则只需循环图像像素并查看它们的颜色,以查看它们是否为轮廓像素。如果您没有坐标,并且轮廓像素没有特定的颜色范围,则这是一种不同类型的问题,更难解决。您没有指定表示法。这就是我问的原因。 - Alexey Frunze
好的,下次我会尽量让我的问题更明确。然而,我没有坐标,也没有像素的特定颜色范围。我认为我找到了解决问题的方法,但它会非常慢。我基本上使用cvCopy将每个轮廓的内容传输到一个新图像中,然后找到该图像的总和。这将给我每个轮廓像素值的总和,但逐个遍历每个轮廓会非常慢。你有其他建议吗? - fdh
我忘了提到:我的应用程序是实时工作的,因此解决方案需要高度的速度。 - fdh
这里的“轮廓(contour)”到底是什么意思,你使用这个词好像没有一百万种解释一样。你有任意形状、任意像素颜色、放置在图像上任意位置的图像?你想要找到并计算边缘像素的总和?显然,对于这个问题,不会有可行或正确的算法...但是你说你可以分割轮廓,那么你的输入到底是什么?你有单独的图像吗?以什么形式?你知道边缘在哪里吗?它们是凸形状吗?它们是连续的吗? - fairidox
3个回答

5

首先获取所有轮廓信息。使用这些信息创建二进制图像,其中白色部分是轮廓的轮廓线和面积。对这两个图像执行AND操作。结果将是黑色背景上的轮廓和面积。然后只需将此图像中的所有像素相加即可。


首先,您提出的建议将给我所有轮廓的总和。我想要每个轮廓的总和而不是全部加起来。其次,正如我在问题中所说,我不想计算轮廓的面积,而是轮廓中已经非黑色的像素值。您的方法会使轮廓中的所有像素变为白色,完全违背了应用程序的目的。 - fdh
1
当您对二进制图像和原始图像进行AND运算时,得到的是一个隔离的图像。您不会得到全白的图像。如果您想一个接一个地进行操作,可以创建二进制掩模并逐个对两个图像进行AND运算。 - scord
抱歉如果我没有解释清楚。但是我自己已经成功地做了类似的事情。 - scord

3

如果我理解正确,您想要对灰度图像中位于轮廓内的所有像素强度求和。如果是这样,我想到的方法是在空白图像上绘制该轮廓并填充它,从而创建一个掩模。之后,为了优化该过程,您还可以使用以下方法计算轮廓的边界矩形:

CvRect cvBoundingRect(CvArr* points, int update=0 );

在此之后,您可以使用以下命令创建一个中间图像:

void cvAddS(const CvArr* src, CvScalar value, CvArr* dst, const CvArr* mask=NULL);

使用值0,从轮廓和设置之前作为ROI的边界矩形获取的掩码。

此后,对结果图像进行求和会更快一些。


谢谢。据我所知,您基本上是通过使用掩码来隔离轮廓内容。我知道它的工作原理,但我真的不明白边界矩形的目的。如果轮廓的内容已经被隔离,那么有ROI有什么意义呢? - fdh
重点是在计算总和或涉及遍历图像中的每个像素的任何其他操作时,要在较小的区域上工作。 - Adrian

0

要单独访问轮廓点,请按照以下代码

vector<vector<Point> > contours;
...
printf("\n Contours pixels \n");
for(int a=0; a< contours.size(); a++)
{  
   printf("\nThe contour NO = %d  size = %d \n",a, contours[a].size() );
   for( int b = 0; b < contours[a].size();  b++ )  
   {  
       printf(" [%d, %d] ",contours[a][b].x, contours[a][b].y ); 
   }
}

这将仅导致轮廓边缘上的点,而不是内部的像素。 - David

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接