OpenCV函数cvtColor能否用于原地转换矩阵?

14

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中有没有惯例可以确定何时可以以这种方式使用函数?

1
当源和目标具有相同数量的通道时,可以完成此操作。例如,RGB到YUV,RGB到YCbCr或反之亦然等等... - sgarizvi
3个回答

14
也许已经太晚回答了,但我想说我不同意这里写的一些事情。
即使目标矩阵没有“相同数量的通道”,甚至如果目标矩阵还没有被创建,您也可以将完全相同的Mat用作源和目标,没有任何问题。
OpenCV程序员经过深思熟虑地设计了它。
所有使用此功能的用户只需要注意源Mat的正确性,包括通道数和数据类型,并记住在函数调用之后可以进行更改。
证明来自查看源代码,在cv :: cvtColor(...)函数内部的第2406行,即第一行。
Mat src = _src.getMat();

如果调用了 in-place 的 cv::cvtColor(…),那么将创建 Mat dst(即 dst=_dst=_scr)。
因此,在 cv::cvtColor(…) 内部进行 in-place 调用时的情况是:src 指向旧矩阵,_src、_dst 和 dst 都指向同一个新分配的矩阵,该矩阵将成为目标矩阵。
这意味着现在可以将新变量 src 和 dst(不是函数调用中的 _src 和 _dst)传递给真正的转换函数。
当函数 void cv::cvtColor(…) 完成后,src 将被处理,_src、_dst 和 dst 都会指向相同的 Mat,_dst 的引用计数将变为 1。


是的,我同意这个观点,尽管我目前没有时间实际测试它。但是根据我的理解,通过InputArray进行传递等同于使用cv :: Mat按值传递,这意味着两个矩阵指向相同的数据集。如果需要重新分配内存,则不会影响指向原始数据的原始矩阵头部。 - Tim MB
是的,在重新分配后,新矩阵是目标Mat,而源Mat是临时的,并且在函数结束时将被丢失。我刚刚测试了一下,这种原地方案似乎在OpenCv框架中很常见(几乎是标准)。 - Giuseppe Dini

3
如果你查看这里的代码,你会发现在2420行上,矩阵dst上调用了create。这意味着该矩阵的数据部分以及头文件都被重写了。因此,可能不建议使用相同的矩阵在srcdst中调用此函数。
至于OpenCV的惯例,请查看InputArray和OutputArray,这些似乎表明,每当存在这些作为输入和输出数据类型的函数调用时,您应该使用不同的Mat变量。

嗯,我明白你的意思。但是当矩阵转换为InputArray时,可能会出现它接收到一个新的头文件的情况吗?只要创建了一个带有指针的新头文件即可。此外,查看_InputArray的头文件https://github.com/Itseez/opencv/blob/9b7dfd677db5818b8dd699e2059c886a1e7ce24f/modules/core/include/opencv2/core/core.hpp表明getMat()函数也返回具有自己头文件的Mat,而不是对相同头文件数据的引用。 - Tim MB
是的...没错...所以你应该使用不同的Mat变量...如果你不清楚头文件在哪里改变以及数据在哪里,调试这些应用程序可能会有点棘手。 - ssb

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

如果您有一个示例,在原地调用cvtColordst没有正确转换图像,请将其提交为错误报告http://code.opencv.org

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

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


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