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

Nic*_*ick 5 opencv objective-c ios

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

如何使用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);
Run Code Online (Sandbox Code Playgroud)

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

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

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

Dan*_*šek 3

正如您在评论中提到的,数据类型originalCV_8UC4- 即它是 4 通道图像。但是,在您对 的调用中cv::inRange,您仅提供了 3 个通道的范围。

cv::Scalar表示 4 元素向量。当您调用仅包含 3 个值的构造函数时,第 4 个元素将使用默认值 0。

因此,您的调用inRange实际上相当于:

cv::inRange(original, cv::Scalar(40,40,40,0), cv::Scalar(160,160,160,0), thresholded);
Run Code Online (Sandbox Code Playgroud)

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

有 2 个选项可以解决此问题: