从 Objective C++ 调用 OpenCv inRange 函数时的行为不同

Posted

技术标签:

【中文标题】从 Objective C++ 调用 OpenCv inRange 函数时的行为不同【英文标题】:OpenCv inRange function behaves differently when called from Objective C++ 【发布时间】:2018-02-18 21:50:18 【问题描述】:

我在这里使用了这个问题的优秀答案:

How to detect bullet holes on the target using python

我已经验证它在 Python 2 和 3.6 中都可以工作,但我想在一个用 Objective C(++) 编写的 ios 应用程序中使用这个概念。这是我翻译它的尝试。最终,我需要它来处理相机拍摄的图像,所以我不想使用 imread,但我已经检查过这没有什么区别。

UIImage *nsi = [UIImage imageNamed:@"CANDX.jpg"];
cv::Mat original;
UIImageToMat(nsi, original);

cv::Mat thresholded;
cv::inRange(original, cv::Scalar(40,40,40), cv::Scalar(160,160,160), thresholded);

cv::Mat kernel = cv::Mat::ones(10, 10, CV_64FC1);
cv::Mat opening;
cv::morphologyEx(thresholded, opening, cv::MORPH_OPEN, kernel);

vector<vector<cv::Point>> contours;
cv::findContours(opening, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);

使用与 Python 版本相同的值对 inRange 的调用会给出一个完全黑色的图像。实际上,不可能为不会导致此结果的下限和上限选择值。我尝试将图像转换为 HSV 并使用 HSV 值作为下限和上限。这有点不同,因为我可以获得一些模糊可识别的结果,但与我应该得到的有用结果完全不同。

如果我从答案中替换“阈值”图像并注释掉 inRange 调用,morphologyfindContours 调用工作正常。

我在设置 inRange 调用时做错了吗?

【问题讨论】:

您所指的原始问题不存在——您是否获得了正确的链接? 感谢@DanMašek,不知道我是如何错误地粘贴它的!现已编辑。 original cv::Mat 的元素(和通道数)的数据类型是什么? 感谢@DanMašek,我认为元素的数据类型是CV_8UC4,查看github.com/opencv/opencv/blob/master/modules/imgcodecs/src/… 中的UIImageToMat 的来源。通道数在我的代码中报告为 4。 完美!非常感谢。如果你想把它写成答案,我所要做的就是在 inRange 调用之前输入cvtColor(original, original, cv::COLOR_BGRA2BGR); 【参考方案1】:

正如您在 cmets 中提到的,original 的数据类型是 CV_8UC4——即它是一个 4 通道图像。但是,在您致电 cv::inRange 时,您只提供了 3 个频道的范围。

cv::Scalar 表示一个 4 元素向量。当您仅使用 3 个值调用 constructor 时,第 4 个元素使用默认值 0。

因此,您对inRange 的调用实际上等同于:

cv::inRange(original, cv::Scalar(40,40,40,0), cv::Scalar(160,160,160,0), thresholded);

您只寻找 Alpha 通道设置为 0(完全透明)的像素。由于图像来自相机,因此不太可能有任何透明像素 - Alpha 通道可能只有全部 255。

有两种方法可以解决这个问题:

删除不需要的 Alpha 通道。一种方法是使用cv::cvtColor,例如

cv::cvtColor(original, original, cv::COLOR_BGRA2BGR);

为所有通道指定所需的范围,例如

cv::inRange(original, cv::Scalar(40,40,40,0), cv::Scalar(160,160,160,255), thresholded);

【讨论】:

以上是关于从 Objective C++ 调用 OpenCv inRange 函数时的行为不同的主要内容,如果未能解决你的问题,请参考以下文章

带有objective-c的opencv和c++ [关闭]

使用另一个 C++ 类作为参数从 Objective-C(++) 调用 C++ 方法

如何在c++中,调用objective-c

从 Android 中的本机 c++ 文件调用本机 opencv

如何从 c# web 服务调用 c++ Opencv 项目?

objective-c和c++的区别