Я начал с этого изображения:
Затем я применил 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
, как показано ниже.
ПРОБЛЕМА: (а) я по-прежнему получаю те же Mat
s, тогда как если вы посмотрите на следующий фрагмент кода и значения maximumContourArea
и currentContourArea
s из выходных данных 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.");
, потому что метод remove()
ArrayList
возвращает удаляемую вещь (контур). (источник)
Я также добавил currentContour--;
после этого утверждения.
Ниже приведены сообщения Logcat:
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
^ вроде работает. ЕДИНСТВЕННАЯ ПРОБЛЕМА, КОТОРАЯ ОСТАЛАСЬ НА СЕЙЧАС, ЗАКЛЮЧАЕТСЯ В ТОМ, ЧТО почему я рисую все контуры (даже те, что покрыты небольшими пятнами), когда выполняется последнее drawContours()
для рисования контуров зеленого цвета на исходном изображении.
10 / 100
равно нулю? Я не уверен, как Java справляется с этим, поэтому попробуйте вместо этогоmaximumContourArea*0.1
. И, пожалуйста, попробуйте разные пороги, такие какmaximumContourArea*0.9
. - person Micka   schedule 21.04.201610/100
равно нулю. Я исправил это, но результат все еще не правильный. Я только что опубликовал редактирование в вопросе об этом. - person Solace   schedule 21.04.2016contours.remove(currentContour);
? Вы уверены, что.remove
работает так, как вам нужно? Может быть, вам нужно вставить позицию индекса вместо элемента? (извините, я понятия не имею о структурах Java) - person Micka   schedule 21.04.2016maximumContourArea
. @Micka Хорошо, просто сделаю это - person Solace   schedule 21.04.2016currentContour
- это индекс, а не контур как таковой - person api55   schedule 21.04.2016contours.size()
дал вам 2 (судя по логам), он не может рисовать больше вещей... Возможно, вы используете устаревший список (один без удаления вещей) или вы используете изображение, которое вы нарисовали на нем раньше.. , чтобы знать, является ли это одним из этих двух, вы должны сделать. 1) напечатать размер массива перед частью рисования и 2) показать изображение перед рисованием на нем. Если 1) дал вам число, отличное от двух, проблема заключается в массиве. Если 2) дает вам изображение с нарисованными контурами, то это использованное изображение, которое вы нарисовали на нем раньше. - person api55   schedule 21.04.2016Mat
решило проблему =) Но просто для пояснения, даже словоoriginalPhotoMat
не встречалось где-либо междуImgproc.cvtColor(originalPhotoMat, originalMatGreyScale, Imgproc.COLOR_BGR2GRAY);
иImgproc.drawContours(originalPhotoMat, contours, contourIndex, new Scalar(0, 255, 0));
(оба утверждения даны под вопросом) в моем коде. - person Solace   schedule 21.04.2016