我从这张图片开始:
然后我应用了Canny Edge Detector,如:
Mat originalMatGreyScale = new Mat();
Imgproc.cvtColor(originalPhotoMat, originalMatGreyScale, Imgproc.COLOR_BGR2GRAY);
Mat edgesMat = new Mat();
Imgproc.Canny(originalMatGreyScale, edgesMat , 50, 70);
我得到了:
然后我找到contours
的轮廓列表(Imgproc.findContours()
)。然后我做了一些编码,以便(1)找到最大轮廓区域(maximumContourArea
)(2)删除来自contours
任何面积小于 maximumContourArea
的轮廓。问题底部给出的代码。
我打电话给Imgproc.drawContours()
以在原始图像上绘制绿色(剩余)轮廓
for (int contourIndex = 0; contourIndex < contours.size(); contourIndex++) {
Imgproc.drawContours(originalPhotoMat, contours, contourIndex, new Scalar(0, 255, 0));
}
我期待的是所有那些小污迹和噪音的轮廓应该从轮廓列表contours
中移除,但我仍然得到这个垫子(在那些小污迹周围绘制绿色轮廓)同样):
此外,以下代码中的Log.i()
条消息打印出来:
最初的轮廓数量:27
处理后的轮廓数量:27
List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
Imgproc.findContours(edgesMap, contours, new Mat(), Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);
Log.i(TAG, "Number of contours initially: " + contours.size());//check
double maximumContourArea = 0;
Iterator<MatOfPoint> contoursIterator = contours.iterator();
while(contoursIterator.hasNext()) {
MatOfPoint nextContour = contoursIterator.next();
double nextContourArea = Imgproc.contourArea(nextContour);
if (nextContourArea > maximumContourArea) {
maximumContourArea = nextContourArea;
}
}
while(contoursIterator.hasNext()) {
MatOfPoint nextContour = contoursIterator.next();
if (Imgproc.contourArea(nextContour) < maximumContourArea*(10 / 100)) {
contours.remove(contours.indexOf(nextContour));
}
}
Log.i(TAG, "Number of contours after processing: " + contours.size());//check
编辑:
我将(10/100)
替换为0.1
,实际上为了清楚起见,我决定在这个例子中使用0.5
。这样,应移除小于最大轮廓面积一半的所有轮廓。
所以在这里和那里发表了几个Log.i
语句之后,我意识到第二个while循环没有被执行。在使用Iterator
进行一些调整然后逐步调整到foreach
循环后,我得到ConcurrentModificationException
,因此我终于发现解决方案是for
循环,如下所示。
问题:(a)我仍然得到相同的Mat
s,而如果您查看以下代码段和maximumContourArea
的值以及{currentContourArea
的值1}}来自本页底部的logcat输出,你会注意到只有一个轮廓,面积为1719.0
应保留,所有其他轮廓应该被删除。 (b)在以下代码之后查看Logcat输出。
代码已更改:
Log.i(TAG, "PNM Number of contours initially: " + contours.size());//check
double maximumContourArea = 0;
for (int currentContour=0; currentContour<contours.size(); currentContour++) {
double currentContourArea = Imgproc.contourArea(contours.get(currentContour));
if (maximumContourArea < currentContourArea) {
maximumContourArea = currentContourArea;
}
}
Log.i(TAG, "PNM maximumContourArea: " + maximumContourArea);//check
Log.i(TAG, "PNM maximumContourArea*.5: " + maximumContourArea*0.5);//check
for (int currentContour=0; currentContour<contours.size(); currentContour++) {
double currentContourArea = Imgproc.contourArea(contours.get(currentContour));
Log.i(TAG, "PNM currentContourArea: " + currentContourArea);//check
if (currentContourArea < maximumContourArea*0.5) {
contours.remove(currentContour);
}
}
Log.i(TAG, "PNM Number of contours after processing: " + contours.size());//check
Logcat输出:
04-21 12:09:59.955: I/MainActivity(9983): PNM Number of contours initially: 27
04-21 12:09:59.957: I/MainActivity(9983): PNM maximumContourArea: 1992.0
04-21 12:09:59.957: I/MainActivity(9983): PNM maximumContourArea*.5: 996.0
04-21 12:09:59.958: I/MainActivity(9983): PNM currentContourArea: 0.0
04-21 12:09:59.958: I/MainActivity(9983): PNM currentContourArea: 0.0
04-21 12:09:59.959: I/MainActivity(9983): PNM currentContourArea: 34.0
04-21 12:09:59.959: I/MainActivity(9983): PNM currentContourArea: 40.0
04-21 12:09:59.959: I/MainActivity(9983): PNM currentContourArea: 2.5
04-21 12:09:59.959: I/MainActivity(9983): PNM currentContourArea: 0.0
04-21 12:09:59.959: I/MainActivity(9983): PNM currentContourArea: 0.0
04-21 12:09:59.960: I/MainActivity(9983): PNM currentContourArea: 0.0
04-21 12:09:59.961: I/MainActivity(9983): PNM currentContourArea: 0.5
04-21 12:09:59.961: I/MainActivity(9983): PNM currentContourArea: 1719.0
04-21 12:09:59.962: I/MainActivity(9983): PNM currentContourArea: 35.5
04-21 12:09:59.962: I/MainActivity(9983): PNM currentContourArea: 105.0
04-21 12:09:59.962: I/MainActivity(9983): PNM currentContourArea: 29.5
04-21 12:09:59.962: I/MainActivity(9983): PNM currentContourArea: 47.0
04-21 12:09:59.962: I/MainActivity(9983): PNM Number of contours after processing: 14
确定我已将contours.remove(currentContour);
替换为Log.i(TAG, "PNM A contour with an area of " + Imgproc.contourArea(contours.remove(currentContour))
+ " is being removed.");
,因为ArrayList
的{{1}}方法会返回要删除的内容(轮廓)。 (source)
在此声明之后我还添加了remove()
。
以下是Logcat消息:
currentContour--;
^似乎正在运作。 现在仍然存在的唯一问题是,当执行最后一次04-21 14:15:19.824: I/MainActivity(11125): PNM Number of contours: 27
04-21 14:15:19.824: I/MainActivity(11125): PNM maximumContourArea: 1992.0
04-21 14:15:19.824: I/MainActivity(11125): PNM maximumContourArea*.5: 996.0
04-21 14:15:19.824: I/MainActivity(11125): PNM currentContourArea: 0.0
04-21 14:15:19.824: I/MainActivity(11125): PNM A contour with an area of 0.0 is being removed.
04-21 14:15:19.825: I/MainActivity(11125): PNM currentContourArea: 18.0
04-21 14:15:19.825: I/MainActivity(11125): PNM A contour with an area of 18.0 is being removed.
04-21 14:15:19.825: I/MainActivity(11125): PNM currentContourArea: 0.0
04-21 14:15:19.825: I/MainActivity(11125): PNM A contour with an area of 0.0 is being removed.
04-21 14:15:19.825: I/MainActivity(11125): PNM currentContourArea: 0.0
04-21 14:15:19.825: I/MainActivity(11125): PNM A contour with an area of 0.0 is being removed.
04-21 14:15:19.825: I/MainActivity(11125): PNM currentContourArea: 34.0
04-21 14:15:19.825: I/MainActivity(11125): PNM A contour with an area of 34.0 is being removed.
04-21 14:15:19.825: I/MainActivity(11125): PNM currentContourArea: 0.0
04-21 14:15:19.825: I/MainActivity(11125): PNM A contour with an area of 0.0 is being removed.
04-21 14:15:19.825: I/MainActivity(11125): PNM currentContourArea: 40.0
04-21 14:15:19.825: I/MainActivity(11125): PNM A contour with an area of 40.0 is being removed.
04-21 14:15:19.825: I/MainActivity(11125): PNM currentContourArea: 0.0
04-21 14:15:19.825: I/MainActivity(11125): PNM A contour with an area of 0.0 is being removed.
04-21 14:15:19.825: I/MainActivity(11125): PNM currentContourArea: 2.5
04-21 14:15:19.825: I/MainActivity(11125): PNM A contour with an area of 2.5 is being removed.
04-21 14:15:19.826: I/MainActivity(11125): PNM currentContourArea: 4.0
04-21 14:15:19.826: I/MainActivity(11125): PNM A contour with an area of 4.0 is being removed.
04-21 14:15:19.826: I/MainActivity(11125): PNM currentContourArea: 0.0
04-21 14:15:19.826: I/MainActivity(11125): PNM A contour with an area of 0.0 is being removed.
04-21 14:15:19.826: I/MainActivity(11125): PNM currentContourArea: 0.5
04-21 14:15:19.826: I/MainActivity(11125): PNM A contour with an area of 0.5 is being removed.
04-21 14:15:19.826: I/MainActivity(11125): PNM currentContourArea: 0.0
04-21 14:15:19.826: I/MainActivity(11125): PNM A contour with an area of 0.0 is being removed.
04-21 14:15:19.826: I/MainActivity(11125): PNM currentContourArea: 32.5
04-21 14:15:19.826: I/MainActivity(11125): PNM A contour with an area of 32.5 is being removed.
04-21 14:15:19.826: I/MainActivity(11125): PNM currentContourArea: 0.0
04-21 14:15:19.826: I/MainActivity(11125): PNM A contour with an area of 0.0 is being removed.
04-21 14:15:19.826: I/MainActivity(11125): PNM currentContourArea: 0.0
04-21 14:15:19.826: I/MainActivity(11125): PNM A contour with an area of 0.0 is being removed.
04-21 14:15:19.826: I/MainActivity(11125): PNM currentContourArea: 0.5
04-21 14:15:19.826: I/MainActivity(11125): PNM A contour with an area of 0.5 is being removed.
04-21 14:15:19.826: I/MainActivity(11125): PNM currentContourArea: 11.5
04-21 14:15:19.826: I/MainActivity(11125): PNM A contour with an area of 11.5 is being removed.
04-21 14:15:19.826: I/MainActivity(11125): PNM currentContourArea: 1719.0
04-21 14:15:19.826: I/MainActivity(11125): PNM currentContourArea: 35.5
04-21 14:15:19.826: I/MainActivity(11125): PNM A contour with an area of 35.5 is being removed.
04-21 14:15:19.827: I/MainActivity(11125): PNM currentContourArea: 59.0
04-21 14:15:19.827: I/MainActivity(11125): PNM A contour with an area of 59.0 is being removed.
04-21 14:15:19.827: I/MainActivity(11125): PNM currentContourArea: 105.0
04-21 14:15:19.827: I/MainActivity(11125): PNM A contour with an area of 105.0 is being removed.
04-21 14:15:19.827: I/MainActivity(11125): PNM currentContourArea: 1992.0
04-21 14:15:19.827: I/MainActivity(11125): PNM currentContourArea: 29.5
04-21 14:15:19.827: I/MainActivity(11125): PNM A contour with an area of 29.5 is being removed.
04-21 14:15:19.827: I/MainActivity(11125): PNM currentContourArea: 259.5
04-21 14:15:19.827: I/MainActivity(11125): PNM A contour with an area of 259.5 is being removed.
04-21 14:15:19.827: I/MainActivity(11125): PNM currentContourArea: 47.0
04-21 14:15:19.827: I/MainActivity(11125): PNM A contour with an area of 47.0 is being removed.
04-21 14:15:19.827: I/MainActivity(11125): PNM currentContourArea: 38.0
04-21 14:15:19.827: I/MainActivity(11125): PNM A contour with an area of 38.0 is being removed.
04-21 14:15:19.827: I/MainActivity(11125): PNM Number of contours after processing: 2
以在原始图像上绘制绿色轮廓时,为什么我会绘制所有绘制的轮廓(甚至是那些肮脏的污迹)。
答案 0 :(得分:2)
循环中的逻辑存在缺陷......
假设您有一个包含10个元素的数组,并且您发现第二个元素将被删除,此时您的currentContour
变量为1并删除此元素。然后你将有9个元素,你的迭代结束了,你的currentContour
变量将在2中。到目前为止,当你用索引1删除你的元素时,问题2的元素的索引被改变了是什么问题因此,永远不会检查此元素,因为您的currentContour
变量已经在2中。
解决此问题的一种方法是创建一个新数组并添加您想要的轮廓......或者在删除元素后将索引更改为前一个数字currentContour--;