OpenCV удаляет фоновый шум и артефакты

У меня есть следующее изображение:

введите здесь описание изображения

Я могу отобразить это изображение в оттенках серого с помощью следующего кода Java OpenCV:

public static Mat grayscale(Mat mat) throws IOException {
    Mat gray = new Mat(mat.size(), CvType.CV_8UC1);
    if (mat.channels() == 3) {
        Imgproc.cvtColor(mat, gray, Imgproc.COLOR_RGB2GRAY);
    } else if (mat.channels() == 1) {
        mat.copyTo(gray);
    } else {
        throw new IOException("Invalid image type:" + mat.type());
    }
    return gray;
}

Сейчас мне нужно удалить фоновый шум (артефакты сканирования, линии) с этого изображения и оставить там только отсканированную карту. Я думаю, что мне нужно использовать порог, разрушать там, но не могу сделать это с OpenCV.

Я играю с этим, но результат сейчас ужасен и уничтожает все изображение:

public static Mat clean(Mat srcImage) {
    Core.normalize(srcImage, srcImage, 0, 255, Core.NORM_MINMAX);
    Imgproc.threshold(srcImage, srcImage, 0, 255, Imgproc.THRESH_OTSU);
    //Imgproc.erode(srcImage, srcImage, new Mat());
    Imgproc.dilate(srcImage, srcImage, new Mat(), new Point(0, 0), 1);
    return srcImage;
}

Пожалуйста, покажите, как этого можно достичь с помощью OpenCV Java.

ОБНОВЛЕНО

Я пытаюсь перенести пример Python, предоставленный janu777, на Java. Это мой текущий код:

Mat image = Imgcodecs.imread("test.png");

Mat gray = new Mat();
Imgproc.cvtColor(image, gray, Imgproc.COLOR_BGR2GRAY);
Core.absdiff(gray, new Scalar(255), gray);

double thresh = Imgproc.threshold(gray, gray, 5, 255, Imgproc.THRESH_TOZERO);

Mat kernel1 = Imgproc.getStructuringElement(Imgproc.MORPH_ELLIPSE, new Size(11, 11));
Mat kernel2 = Mat.ones(3, 3, CvType.CV_8U);

Mat erosion = new Mat();
Imgproc.erode(gray, erosion, kernel2);
Mat dilation = new Mat();
Imgproc.dilate(erosion, dilation, kernel1);

Прямо сейчас у меня есть другой результат, чем было указано в ответе:

введите здесь описание изображения

Я не могу найти место, где должен применяться параметр thresh, а также я не использую параметр iterations для методов Imgproc.erode и Imgproc.dilate, потому что сигнатура метода в этом случае также требует дополнительного параметра Point anchor, которого у меня сейчас нет.

Что я делаю не так ?


person alexanoid    schedule 05.02.2018    source источник
comment
Imgproc.threshold(), Imgproc.erode(), Imgproc.dilate(), возможно, Imgproc.morphologyEx(), постарайтесь   -  person Jyr    schedule 05.02.2018
comment
На всех отсканированных картах есть эта линия посередине?   -  person janu777    schedule 06.02.2018
comment
@ janu777 у некоторых из них может быть эта строка, но не у всех   -  person alexanoid    schedule 06.02.2018
comment
Вот мой результат с шагами: (1) шаги (2) результат   -  person Kinght 金    schedule 06.02.2018


Ответы (1)


Следуя комментарию @Silencer, я реализовал идею, используя python и Opencv. Пожалуйста, переведите алгоритм для работы с java.

Шаг 1: Морфологические операции с использованием эллиптического элемента структурирования.

img = cv2.imread("test.png")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = cv2.subtract(255,gray)
ret,thresh = cv2.threshold(gray,5,255,cv2.THRESH_TOZERO)
kernel1 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(11,11))
kernel2 = np.ones((3,3),np.uint8)
erosion = cv2.erode(thresh,kernel2,iterations = 1)
dilation = cv2.dilate(erosion,kernel1,iterations = 7)

Результат: Морф-операция

Шаг 2. Поиск контуров

im2,contours, hierarchy = cv2.findContours(dilation,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
c = max(contours, key = cv2.contourArea)
rect = cv2.minAreaRect(c)
box = cv2.boxPoints(rect)
box = np.int0(box)
cv2.drawContours(img,[box],0,(0,0,255),2)

Результат: Ограничивающий прямоугольник

Шаг 3. Поверните изображение и обрежьте

# rotate img
angle = rect[2]
rows,cols = img.shape[0], img.shape[1]
M = cv2.getRotationMatrix2D((cols/2,rows/2),angle,1)
img_rot = cv2.warpAffine(img,M,(cols,rows))

# rotate bounding box
rect0 = (rect[0], rect[1], 0.0)
box = cv2.boxPoints(rect)
pts = np.int0(cv2.transform(np.array([box]), M))[0]    
pts[pts < 0] = 0

# crop
img_crop = img_rot[pts[1][1]:pts[0][1], 
                   pts[1][0]:pts[2][0]]
cv2.imshow("finalresult.jpg",img_crop)

Повернуть и обрезать

person janu777    schedule 06.02.2018
comment
Спасибо! Я пытаюсь перенести ваш пример на Java. Я обновил свой вопрос с текущими результатами. Что я делаю не так? - person alexanoid; 06.02.2018
comment
Можете ли вы проверить строку вычитания. Потому что он должен инвертировать цвета на вашем изображении. Почему значение 0,255? Опубликуйте изображение результата после этого шага - person janu777; 07.02.2018
comment
В случае Core.subtract(gray, new Scalar(255), gray); изображение полностью черное. - person alexanoid; 07.02.2018
comment
Идея этой линии состоит в том, чтобы инвертировать пиксели. Вы должны найти способ сделать это. - person janu777; 07.02.2018
comment
Я думаю, вы можете использовать absdiff для этого - person janu777; 07.02.2018
comment
Спасибо! Теперь после Core.absdiff(gray, new Scalar(255), gray); серая матрица инвертируется. Прямо сейчас что-то не так с Imgproc.erode(), потому что я не знаю, как и где применить параметр thresh в Java-версии этого метода. - person alexanoid; 07.02.2018
comment
Предполагается, что вы разрушаете с помощью ядра2 и расширяете с помощью ядра1. Проверьте правильно - person janu777; 07.02.2018
comment
К сожалению, я сейчас не знаю, как перевести следующую строку erosion = cv2.erode(thresh,kernel1,iterations = 1) в эквивалент Java - Imgproc.erode(..) я не вижу места в cImgproc.erode`, где можно применить параметр thresh - person alexanoid; 07.02.2018
comment
извините, я сделал небольшое изменение в коде. Вы должны разрушить ядро ​​​​2, а не ядро ​​​​1 - person janu777; 07.02.2018
comment
Спасибо, пожалуйста, посмотрите мой обновленный вопрос. Результат довольно близок, но все же не равен. - person alexanoid; 07.02.2018
comment
Как правильно конвертировать? - person alexanoid; 07.02.2018
comment
Вы должны добиться результата методом проб и ошибок. Просто следуйте коду Python для проверки. Я не знаю джаву. Удачи с вашим проектом :) - person janu777; 07.02.2018
comment
Спасибо за вашу помощь! - person alexanoid; 07.02.2018