OpenCV inRange 更改 Mat 类型

Posted

技术标签:

【中文标题】OpenCV inRange 更改 Mat 类型【英文标题】:OpenCV inRange changes Mat type 【发布时间】:2015-01-26 13:10:19 【问题描述】:

我无法摆脱 OpenCV 中的这个错误:

OpenCV 错误:输入参数的大小不匹配(操作是 既不是“数组操作数组”(其中数组具有相同的大小和类型), 也不是'array op scalar',也不是'scalar op array')

我通过Mat.type(); 发现我所有的Mat(img) 都有类型16,但是在函数inRange 之后我的img3 将类型更改为0。然后我不能使用函数bitwise_and,因为它没有同类型。

如何将其转换为相同类型?

Mat img1 = imread(argv[1], 1);
Mat img2, img3, img4;

cvtColor(img1, img2, CV_BGR2HSV);
GaussianBlur(img2, img2, Size(15,15), 0); 
inRange(img2, Scalar(h_min_min,s_min_min,v_min_min), Scalar(h_max_min,s_max_min,v_max_min), img3); // now img3 changed type to 0
bitwise_and(img1, img3, img4); // img1.type()=16, img3.type()=0 ERROR

【问题讨论】:

出于所有意图和目的,OpenCV 中的inRange 为您提供阈值二值图像。 CV_8U 类型,如果我没记错的话。尝试使用 img3.convertTo(img3, CV_16U) 或您需要的任何内容将其转换回所需的类型。 感谢您的快速响应,但在 img3.convertTo(img3, CV_16U) 之后类型为 2,在 img3.convertTo(img3, 16) 之后类型仍为 0 你想达到什么目的?将所有不在范围内的元素设置为零?而不是 bitwise_ 并尝试img1.copyTo(img4,img3); 并尝试imshow("img3", img3); cv::waitKey(0); 来测试inRange 是否给出了您想要的结果。 关于你之前的评论:img3.convertTo(img3, CV_16U) 只转换类型,不转换通道数。你需要的是 CV_16UC3 但你不能用.convertTo 得到它,它不会做你所期望的。所以如果你真的想在所有 3 个通道上使用 bitwise_and,你必须 cv::merge 一个向量,它是你的 img3 的 3 倍 16U 版本... 【参考方案1】:

这是正常的,因为inRange 返回一个 1 通道掩码(每个像素的值),所以要执行按位运算,只需将掩码转换回 3 通道图像:

cvtColor(img3,img3,CV_GRAY2BGR);
bitwise_and(img1, img3, img4);// now both images are CV_8UC3 (=16)

编辑:正如 Berak 所说,要更改频道数量,您必须使用 cvtColor,而不是 Mat::convertTo。对此感到抱歉。

【讨论】:

感谢您的快速回复,但没有帮助。类型仍为 0。 inRange(img2, Scalar(h_min_min,s_min_min,v_min_min), Scalar(h_max_min,s_max_min,v_max_min), img3); cout convertTo 不改变通道数,只改变深度。它在这里需要 cvtColor。 太好了,谢谢。我使用了 cvtColor(img3,img3,CV_GRAY2BGR,3);它有效:)

以上是关于OpenCV inRange 更改 Mat 类型的主要内容,如果未能解决你的问题,请参考以下文章

openCV Mat问题“输入参数的大小不匹配”

OpenCV:改变像素的颜色

opencv编程中cvMat到Mat如何进行数据转换?

无法更改图像 Mat opencv 中的所有像素

opencv mat的数据类型CV_32FC1变成CV_8UC1

OpenCV:Mat,IplImage,CvMat类型转换