Как убрать фоновые серые рисунки с изображения в OPENCV python - PullRequest
0 голосов
/ 15 апреля 2020

Мне нужно убрать серый рисунок с фона изображения, и на нем нужны только символы, нарисованные поверх него.

Вот мой код для этого с использованием morphologyEx, но он не удаляет весь серый рисунок, который находится в фоновом режиме .

img_path = "images/new_drawing.png"
img = cv2.imread(img_path)

kernel = np.ones((2,2), dtype=np.uint8)
result = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel, iterations=1)
cv2.imshow('Without background',result);

cv2.waitKey(0)
cv2.destroyAllWindows()

Я пробовал также и получил ожидаемые результаты в оттенках серого, но не смог преобразовать его в BGR.

Вот мой код

img = cv2.imread('images/new_drawing.png')
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
med_blur = cv2.medianBlur(gray_img, ksize=3)

_, thresh = cv2.threshold(med_blur, 190, 255, cv2.THRESH_BINARY)
blending = cv2.addWeighted(gray_img, 0.5, thresh, 0.9, gamma=0)
cv2.imshow("blending", blending);

Также я использовал контуры, чтобы идентифицировать символы и нарисовать их на белом изображении, но проблема в том, что он также определяет фоновый рисунок, который мне не нужен.

Входное изображение

enter image description here

Ожидаемое изображение на выходе

enter image description here

Также рисунок всегда будет серого цвета, как на изображении.

Пожалуйста, помогите меня, чтобы получить лучший результат.

Ответы [ 2 ]

1 голос
/ 15 апреля 2020

Вы почти там ...

Вместо использования cv2.inRange для "захвата" не серого пикселя, я предлагаю использовать cv2.inRange для захвата всех пикселей, которые вы хотите изменить на белый цвет:

mask = cv2.inRange(hsv, (0, 0, 100), (255, 5, 255))
  • Диапазон оттенков не имеет значения.
  • Насыщенность близка к нулю (оттенки серого).
  • Яркость исключает черные пиксели (вы хотел бы сохранить).

Чтобы получить более хорошее решение, я также использовал следующие дополнительные этапы:

  • Создание маски из не черных пикселей :

    nzmask = cv2.inRange(hsv, (0, 0, 5), (255, 255, 255))
    
  • Удалите вышеуказанную маску:

    nzmask = cv2.erode(nzmask, np.ones((3,3)))
    
  • Примените операцию and между mask и nzmask:

    mask = mask & nzmask
    

Приведенные выше этапы удерживают серые пиксели вокруг черного текста.
Без указанных этапов черный текст становится тоньше.

  • На последнем этапе выполняется замена mask пикселей на белый:

    new_img = img.copy()
    new_img[np.where(mask)] = 255
    

Вот код:

import numpy as np
import cv2

img_path = "new_drawing.png"
img = cv2.imread(img_path)

hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

mask = cv2.inRange(hsv, (0, 0, 100), (255, 5, 255))
cv2.imshow('mask before and with nzmask', mask);

# Build mask of non black pixels.
nzmask = cv2.inRange(hsv, (0, 0, 5), (255, 255, 255))

# Erode the mask - all pixels around a black pixels should not be masked.
nzmask = cv2.erode(nzmask, np.ones((3,3)))
cv2.imshow('nzmask', nzmask);

mask = mask & nzmask

new_img = img.copy()
new_img[np.where(mask)] = 255

cv2.imshow('mask', mask);
cv2.imshow('new_img', new_img);
cv2.waitKey(0)
cv2.destroyAllWindows()

Результат:
enter image description here

1 голос
/ 15 апреля 2020

Вот один из способов сделать это в Python / OpenCV.

  • Чтение ввода
  • Преобразование в HSV и отдельные каналы
  • Порог канала насыщения
  • Порог значения канала и инвертирование
  • Объединение двух пороговых изображений в качестве маски
  • Применение маски к входу для записи белого цвета, где маска черная
  • Сохранить результат

Ввод:

enter image description here

import cv2
import numpy as np

# read image
img = cv2.imread('symbols.png')

# convert image to hsv colorspace
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
h, s, v = cv2.split(hsv)

# threshold saturation image
thresh1 = cv2.threshold(s, 92, 255, cv2.THRESH_BINARY)[1]

# threshold value image and invert
thresh2 = cv2.threshold(v, 128, 255, cv2.THRESH_BINARY)[1]
thresh2 = 255 - thresh2

# combine the two threshold images as a mask
mask = cv2.add(thresh1,thresh2)

# use mask to remove lines in background of input
result = img.copy()
result[mask==0] = (255,255,255)

# display IN and OUT images
cv2.imshow('IMAGE', img)
cv2.imshow('SAT', s)
cv2.imshow('VAL', v)
cv2.imshow('THRESH1', thresh1)
cv2.imshow('THRESH2', thresh2)
cv2.imshow('MASK', mask)
cv2.imshow('RESULT', result)
cv2.waitKey(0)
cv2.destroyAllWindows()

# save output image
cv2.imwrite('symbols_thresh1.png', thresh1)
cv2.imwrite('symbols_thresh2.png', thresh2)
cv2.imwrite('symbols_mask.png', mask)
cv2.imwrite('symbols_cleaned.png', result)


Предел насыщения канала:

enter image description here

Значение канала с пороговым значением и инвертировано:

enter image description here

Маска:

enter image description here

Результат:

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...