我在这里使用了这个问题的优秀答案:
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值进行下限和上限。这略微不同,我可以得到一些模糊的可识别结果,但没有什么比我应该得到的有用结果。
如果我用'thresholdolded&#39;来自答案的图片并注释掉了inRange电话,morphology
和findContours
电话工作正常。
我在设置inRange调用时遇到了什么问题吗?
答案 0 :(得分:2)
正如您在评论中提到的,original
的数据类型是CV_8UC4
- 即它是4通道图像。但是,在致电cv::inRange
时,您只提供3个频道的范围。
cv::Scalar
表示4元素向量。当您仅使用3个值调用constructor时,默认值0将用于第4个元素。
因此,您对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);