【问题标题】:OpenCV cvtColor() performance issue on iPhone 4(S)iPhone 4(S) 上的 OpenCV cvtColor() 性能问题
【发布时间】:2014-07-23 11:38:38
【问题描述】:

我目前正在用 C++ 开发一个跨平台应用程序,主要针对 Android 和 iOS。总体而言,它运行良好且性能令人难以置信,但在 iPhone 4 (S) 上运行非常缓慢(见下图)。

目标是使用特定算法处理约 5-10 fps 的视频流。

除其他外,该代码已成功测试(每秒处理 5 帧或更多帧)并在以下设备上进行了分析:

  • 谷歌 Nexus 4
  • 谷歌 Nexus 5
  • 银河 S 迷你
  • 银河 S3
  • 索尼 XPeria Z
  • Google Nexus one(是的,也可以在那里使用)
  • 华为P1和P2
  • 银河笔记

  • iPad2 迷你版

  • iPhone 5
  • iPhone 5s

但是,如上所述,它在 iPhone 4 和 iPhone 4s 上运行。他们都每两秒处理 1 帧 => 0.5fps

当然,这似乎有点奇怪,因为它适用于像华为甚至 Nexus One (2fps) 这样的“较弱”设备,所以我开始使用 Instruments 进行性能和内存消耗分析。

内存消耗还可以,最多使用16MB(从图片可以看出)。但是,运行时的分析让我有点震惊。

和逆调用树:

现在,您可以看到 CPU 正忙于 cvtColor() 函数 (cv::RGB2RGB),占总运行时间的很大一部分。在内部使用了 parallel_for 实现 - 它可能与不适合运行该代码的 CPU 相关联。还是只是在 OpenCV 中实现的 cv::RGB2RGB 函数有点奇怪,因为 BGR2Gray 转换似乎运行得更快?

我使用OpenCV v2.4.9 for iOS 的最新预编译版本。有问题的代码基本上只做从 BGRA 到灰度的颜色转换。它看起来像:

Mat colorMat;
Mat gray;    

colorMat = Mat(vHeight,vWidth,CV_8UC4, rImageData); // no data is copied
cvtColor(colorMat,colorMat,CV_BGRA2BGR);
cvtColor(colorMat,gray,CV_BGR2GRAY);

注意它分为两个转换,因为进一步的处理需要 RGB 和灰度信息 - 这就是为什么不在一个转换步骤中。

另外附注: 我还测试了OpenCV for iOS samples(第 12 章:处理视频),它已交付(以 30fps 捕获率开始时):

  • iPhone 4:5.6 帧/秒
  • iPad mini:30.4 fps

我的问题 由于它在各种设备以及 iOS 设备上运行良好,因此我认为它必须与 iPhone 4(s) 的硬件或软件相关。

有人知道这里可能出了什么问题吗?有没有人遇到过类似的问题?我在互联网上找到了关于遇到相同性能问题的人的非常少的信息(即herehere)。

我知道有不同的视频尺寸,但是对 1280x720 像素的图像进行两次“简单”颜色转换不应该消耗大约 2 秒,尤其是在 iPhone 4 等最近的设备上(S) 是!

非常感谢以这种方式提供的任何帮助、提示或经验!

进展和进一步发现

根据 remi 的评论,我尝试了其他解决方案。不幸的是,我不得不说以下(非常微不足道的)事情也不起作用:

Mat colorMat, gray;
vector<Mat> channels;
AVDEBUG("starting", TAG,1);
colorMat = Mat(vHeight,vWidth,CV_8UC4, rImageData); // no data is copied
AVDEBUG("first", TAG, 1);
split(colorMat, channels);
AVDEBUG("intermediate " << colorMat.size(), TAG, 1);
// no BGRA2BGR conversion at all!!
gray = channels[0]; // take blue channel for gray
AVDEBUG("end", TAG, 1);

产生以下输出:

2014-07-24 09:07:41.763 CheckIfReal[604:3d03] AvCore-Debug: (Debug, Tag=CoreManager) Frame accepted (/Users/tbergmueller/Documents/dev/AvCore/avcore/CoreManager.cpp, line 591)

2014-07-24 09:07:41.765 CheckIfReal[604:3d03] AvCore-Debug: (Debug, Tag=CoreManager) starting (/Users/tbergmueller/Documents/dev/AvCore/avcore/CoreManager.cpp, line 636)

2014-07-24 09:07:41.771 CheckIfReal[604:3d03] AvCore-Debug: (Debug, Tag=CoreManager) first (/Users/tbergmueller/Documents/dev/AvCore/avcore/CoreManager.cpp, line 641)

2014-07-24 09:07:44.599 CheckIfReal[604:3d03] AvCore-Debug: (Debug, Tag=CoreManager) intermediate [720 x 1280] (/Users/tbergmueller/Documents/dev/AvCore/avcore/CoreManager.cpp, line 665)

2014-07-24 09:07:44.605 CheckIfReal[604:3d03] AvCore-Debug: (Debug, Tag=CoreManager) ending (/Users/tbergmueller/Documents/dev/AvCore/avcore/CoreManager.cpp, line 682)

因此 Mat 构造函数 Mat() 很快,因为没有数据被复制(参考docs)。但是,split() 函数在此代码示例中占用了将近 3 秒!然后将蓝色通道作为灰色 Mat 再次快速,因为只创建了一个 Mat-header。

这再次表明循环实现有问题,因为 split() 复制数据,这显然是在循环中完成的。

【问题讨论】:

  • stackoverflow.com/questions/11219240/… 是我调查发现的。不确定是否对您有帮助。是的,每一代 i 设备都比旧设备快得多。我的 iPad3 比 4S 快得多,4S 比 iPad3 快得多,新的 iPad mini 似乎两者都击败了。
  • 不是您的硬件相关问题的答案,但您可能会使用cv::splitcv::marge 函数而不是就地cv::cvtColor 获得一些性能。我不确定它如何就地摆脱通道。或者尝试在与colorMat 不同的矩阵上调用cv::cvtColor 作为输入和输出,然后告诉我们。
  • 感谢 cmets。我将始终编辑第一篇文章以保持一切清洁。我开始玩耍,偶然发现了一些更奇怪的事情,这与分析中的初步观察不符。不幸的是,我今天没有时间详细调查,明天我会打电话给你们,提供有关此问题的更多详细信息。在此感谢!

标签: c++ ios opencv


【解决方案1】:

我要解决这个问题,感谢 cmets,它们将我推向了正确的方向!

正如预期的那样,也从 cmets 中得知,1280x720px 的数据太多,无法在 iPhone 4s 上进行处理,因此我必须找到一种解决方法。

大多数人可能都知道,图像处理主要是使用灰度图像完成的。如果图像是从 iPhone 相机捕获为 BGRA,这意味着首先转换 CV_BGRA2GRAY(这可以使用 cv::cvtColor)。

现在,从分析中可以看出,这种转换花费的时间太长,所以我必须摆脱这种转换。在 iPhone 4(s) 上可能的一种选择是将相机配置为不是在 BGRA 模式下而是在 420YpCbCr 模式下进行捕捉。关于如何正确配置相机有 StackOverflow-Topics。对我来说,尤其是 thisthis as well 很有帮助。

不幸的是,iPhone 4 只支持 3 种像素格式类型,即 420v、420f 和 BGRA。使用此信息和上面的链接,我决定使用 kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange(对应于 420v)。最大的好处是您可以在一个图像平面中获得灰度图像(亮度),在另一个图像平面中获得颜色信息(色度),并且可以分别访问它们。

关键思想是检测灰度图像中的感兴趣区域,然后仅将色彩空间转换应用于那些通常比完整图像少得多的感兴趣像素。通过避免从彩色图像实际转换为灰度,并且仅将颜色空间转换应用于感兴趣的小区域,我在 iPhone 4 上的算法的处理速度提高到每秒约 10 帧,这对于所需的应用程序来说是可以接受的。

【讨论】:

    猜你喜欢
    • 2017-03-02
    • 2019-07-11
    • 2013-01-05
    • 2013-09-03
    • 1970-01-01
    • 1970-01-01
    • 2012-05-15
    • 1970-01-01
    • 2011-12-10
    相关资源
    最近更新 更多