【问题标题】:Count 'white' pixels in opencv binary image (efficiently)计算opencv二进制图像中的“白色”像素(有效)
【发布时间】:2012-01-15 05:46:07
【问题描述】:

我正在尝试计算 OpenCV 二进制图像中的所有白色像素。我目前的代码如下:

  whitePixels = 0;
  for (int i = 0; i < height; ++i)
    for (int j = 0; j < width; ++j)
      if (binary.at<int>(i, j) != 0)
        ++whitePixels;

但是,在使用 gprof 进行分析后,我发现这是一段非常慢的代码,并且是程序中的一大瓶颈。

有没有一种方法可以更快地计算相同的值?

【问题讨论】:

  • 您是否尝试更改高度和宽度?我的意思是循环宽度然后高度?这可能会改善循环,这取决于图像在内存中的布局方式。
  • 你可以通过这个at()函数直接访问图像数据吗?
  • 按照 jrok 的建议做可能会更快。我想知道this faq entry 是否相关。
  • 谢谢大家,我认为直接数据访问一定是要走的路。有些事情告诉我,改变循环的顺序也会更快。我试试看。
  • at() 函数在 Debug 模式下非常慢,尽管(几乎)与 Release 中的直接指针访问一样快。它包含一个 CV_DbgAssert() 来检查边界,这是惰性的。

标签: c++ optimization image-processing opencv


【解决方案1】:

cv::CountNonZero。通常,任务的 OpenCV 实现会进行大量优化。

【讨论】:

  • @karlphillip 你的意思是cv::countNonZero?
  • 完美,优化的内置功能。正是我想要的。
  • 添加了当前文档链接以回答(与此评论不同,将来可以更新)。
【解决方案2】:

您可以使用并行计算。您将图像分成 N 部分并在不同的线程中运行您的代码,然后您会得到每个线程的结果,然后您可以将此结果相加以获得最终数量。

【讨论】:

  • Bill 的算法如果实施得当,应该可能是内存限制而不是 CPU 限制。在普通台式计算机上,并行化通常对内存受限的任务没有帮助。
【解决方案3】:

一行中的最后一个像素通常后面跟着下一行的第一个像素(C代码):

limit=width*height;
i=0;
while (i<limit)
{
  if (binary.at<int>(0,i) != 0) ++whitePixels;
  ++i;
}

【讨论】:

  • 或者将它实现为一个滑动指针,它将取消索引。
  • 和/或在 [i] 和 [i+1] 一次测试两个,并将 2 添加到索引/指针。这将使所需的循环减半。
  • 在使用 isContinuous() 之前应该对矩阵进行连续性测试。如果矩阵不连续,此方法将失败。
【解决方案4】:

其实binary.at&lt;int&gt;(i, j)访问很慢!

这是访问速度比您的更快的简单代码。

for (int i = 0; i < height; ++i)
{
uchar * pixel = image.ptr<uchar>(i);
    for (int j = 0; j < width; ++j)
{
  if(pixel[j]!=0)
   {
      //do your job
   }
}
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-19
    • 2014-05-22
    • 1970-01-01
    • 2023-03-26
    • 2014-09-30
    相关资源
    最近更新 更多