从Objective C ++

时间:2018-02-18 21:50:19

标签: ios objective-c opencv

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

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电话,morphologyfindContours电话工作正常。

我在设置inRange调用时遇到了什么问题吗?

1 个答案:

答案 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);