У меня есть черно-белое изображение (только один канал, только 0 и 255), и я хотел бы удалить в нем маленькие капли, которые находятся ниже определенного порогового значения, используя openCV 3.4.2 в Java.
Теперь я уже нашел следующую ветку: Удаление больших двоичных объектов из двоичного изображения , что в значительной степени аналогично - но мне нужна помощь в переводе ответа в код Java. Кроме того, поскольку я хотел бы удалить черные пятна, я инвертирую изображение до и после обработки.
РЕДАКТИРОВАТЬ: благодаря некоторым добрым предложениям мне удалось получить рабочий код и изменить его, так что теперь это MCVE.
Моя попытка до сих пор:
import java.util.ArrayList;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.MatOfPoint;
import org.opencv.core.Scalar;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
public class contourCheck {
public static void main(String[] args) {
// initialises openCV
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
// reads original black&white image
Mat binary_image = Imgcodecs.imread("C:/Users/MyName/Desktop/TestImages/testpic.png", Imgcodecs.CV_LOAD_IMAGE_GRAYSCALE);
// creates temporary Mat
Mat temp_image = binary_image;
// inverts image
Core.bitwise_not(temp_image,temp_image);
// finds all contours in the image
ArrayList<MatOfPoint> contours = new ArrayList<MatOfPoint>();
Imgproc.findContours(temp_image, contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_NONE);
// deletes contours above minArea to keep only the contours that are supposed to be removed from the image
int minArea = 10;
for (int i = 0; i < contours.size(); i++) {
double area = Imgproc.contourArea(contours.get(i));
if (area > minArea) {
contours.remove(i);
}
}
System.out.println("number of contours remaining: " + contours.size());
for (int j = 0; j < contours.size(); j++) {
if (j > 0) { // apparently temp_image gets also inverted, therefore it gets inverted here once again
Core.bitwise_not(temp_image,temp_image);
}
// fills in small (<= minArea) contours with 0's
Imgproc.drawContours(temp_image, contours,j, new Scalar(0),Core.FILLED);
// inverts image once again to get the original state
Core.bitwise_not(temp_image,binary_image);
// writes image with filtered contours
Imgcodecs.imwrite("C:/Users/MyName/Desktop/TestImages/test/testpic_filtered" + j + ".png", binary_image);
}
}
}
Теперь вот пример изображения, где я хотел бы удалить все черные пятна ниже minArea
(= 10):
Что меня теперь удивляет, так это то, что некоторые очень большие компоненты удалены (например, огромный круг с несколькими маленькими кругами внутри или огромный прямоугольник), а меньшие сохранены. Есть ли ошибка в моем коде или я неправильно понимаю некоторые концепции здесь? Кроме того, почему bitwise_not также инвертирует temp_image
, исходный Mat (Core.bitwise_not(temp_image,binary_image)
)?
Примечание: код создает изображение для каждого удаляемого контура, что означает создание 74 изображений.
Пример вывода (последнее изображение после удаления всех контуров):