【问题标题】:Can the OpenCV function cvtColor be used to convert a matrix in place?可以使用 OpenCV 函数 cvtColor 就地转换矩阵吗?
【发布时间】:2017-04-16 08:08:11
【问题描述】:

OpenCV 函数cvtColor 转换矩阵的颜色空间(例如,从 RGB 到灰度)。该函数的 C++ 签名是

void cvtColor(InputArray src, OutputArray dst, int code, int dstCn=0 )

可以使用此函数就地转换矩阵,即srcdst 具有相同的对象吗?

cv::Mat mat = getColorImage();
cvtColor(mat, mat, CV_RGB2GRAY);

(我知道无论哪种方式,由于目标的通道数与源的通道数不同,它仍然需要为目标分配一个新的内存块。)

更一般地说,OpenCV API 中是否有一个约定来确定何时可以以这种方式使用函数?

【问题讨论】:

  • 源端和目的端通道数相同时可以这样做。例如 RGB 到 YUV,RGB 到 YCbCr,反之亦然等...

标签: c++ opencv


【解决方案1】:

也许回答太晚了,但我想说我不同意这里写的一些东西。
即使目标矩阵没有“相同数量的通道”,或者即使目标矩阵尚未创建,您也可以毫无问题地放置与源和目标相同的 Mat。
OpenCV 程序员对其进行了彻底的设计。
此函数的所有用户都必须注意源 Mat 的正确性,包括通道数和数据类型,并记住在函数调用之后它们可能会发生变化。

证明来自查看source code,在第2406行,只是cv::cvtColor(…)函数内的第一行,

Mat src = _src.getMat();

被调用,然后 Mat dst 被创建(并且 dst=_dst=_scr)。
所以cv::cvtColor(…)内部的情况在就地调用时如下:src指向旧矩阵,_src、_dst、dst都指向同一个新分配的矩阵,这将是目标矩阵。
这意味着比现在新的变量 src 和 dst(不是来自函数调用 _src 和 _dst 的变量)已准备好传递给真正的转换函数。
当函数void cv::cvtColor(…) 完成后,src 被释放,_src、_dst 和 dst 都指向同一个 Mat,_dst 的 refcount 将变为 1。

【讨论】:

  • 是的,我同意这一点,尽管我目前没有时间实际测试它。但正如我所见,通过 InputArray 传递等效于使用 cv::Mat 传递值,这意味着两个矩阵指向同一组数据。如果需要重新分配那么这不会影响指向原始数据的原始矩阵头。
  • 是的,重新分配后新矩阵是目标 Mat,而源 Mat 是临时的,函数结束时会丢失。我刚刚对其进行了测试,这种就地方案在 OpenCv 框架中似乎很常见(几乎是标准)。
【解决方案2】:

如果您查看代码 here,您将看到在第 2420 行,在矩阵 dst 上调用了 create。这意味着该矩阵的数据部分以及标题被重写。因此,可能不建议在srcdst 中使用相同的矩阵调用此函数。

至于 OpenCV 中的约定,请查看 InputArray and OutputArray,这些似乎表明只要函数调用以这些作为输入和输出的数据类型存在,您可能应该使用不同的 Mat 变量。

【讨论】:

  • 嗯,我明白你的意思了。但是,当矩阵转换为 InputArray 时,它可能会收到一个新的标头?提供一个新的头是用一个指针创建的。此外,查看 _InputArray github.com/Itseez/opencv/blob/… 的标头表明 getMat() 函数还返回带有自己标头的 Mat,而不是对相同标头数据的引用。
  • 是的...完全正确...所以您可能应该使用不同的 Mat 变量...如果您不清楚标头在哪里更改,调试这些应用程序可能会有点棘手以及数据在哪里。
【解决方案3】:

它必须就地工作,因为dst 将在调用cv::cvtColor 后包含正确转换的矩阵。但是如果输入的通道数与输出的通道数不同,则矩阵的数据将被重新分配。

如果您有一个示例,其中dst 在就地调用cvtColor 后没有正确转换图像,请在http://code.opencv.org 上将其作为错误提交

更一般地说,OpenCV API 中是否有一个约定来确定何时可以以这种方式使用函数?

没有这样的约定。但是您可以期望大多数基本图像处理功能都可以就地工作。因此,已知所有的转换、过滤器、阈值、仿射/透视转换都支持就地调用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-02
    • 2017-05-08
    • 1970-01-01
    • 2012-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多