Как удалить границы с изображений, взятых из документа (например, рукописные символы MNIST)?

Я хочу извлечь рукописные символы, написанные в таких полях. Поле формы

Я извлекаю квадраты шириной 29 пикселей, что дает мне такие изображения.

Извлеченные изображения 1 Извлеченные изображения 2 Извлеченные изображения 3

Чтобы правильно распознавать символы, изображения отдельных символов должны быть очень чистыми. Нравится,

Очистить символы 1 Очистить символы 2

Что я делаю,

  1. Вычислите горизонтальную и вертикальную проекцию каждого изображения.
  2. Перебрать каждый элемент обоих массивов. Если значение проекции больше определенного порога, это означает, что она не достигла границы. Он удаляет пробелы вокруг границы.

  3. Затем найдите контуры на изображении.

  4. Если площадь контура больше некоторого порога. Получите ограничивающий прямоугольник и обрежьте его.

Но проблема в том, что метод не точен. В некоторых случаях это работает нормально, но в большинстве случаев, если терпит неудачу с треском. Он создает такие изображения, как

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

Также значения проекции очень специфичны для этого изображения (или изображений, близких к этому изображению). Это плохо обобщает.

Есть ли другой метод, который может хорошо работать в этой ситуации?

Код,

char = cv2.imread(image)
char_gray = cv2.cvtColor(char, cv2.COLOR_BGR2GRAY)
char_bw = cv2.adaptiveThreshold(char_gray, 255, 
cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 9)

(rows, cols) = char_gray.shape

bit_not = cv2.bitwise_not(char_bw)
proj_h = cv2.reduce(bit_nv2.REDUCE_AVG)

proj_v = cv2.reduce(bit_not, 0, cv2.REDUCE_AVG)

thresh_h = 200
thresh_v = 100

start_x, start_y, end_x, end_y = 0, 0, cols - 1, rows - 1
#proj_h = proj_h[0]
proj_v = proj_v[0]

num_iter_h = cols // 8
num_iter_v = rows // 8

for _ in range(num_iter_h):
    if proj_h[start_y][0] > 35:
        start_y += 1

for _ in range(num_iter_h):
    if proj_h[end_y][0] > 160:
        end_y -= 1

for _ in range(num_iter_v):
    if proj_v[start_x] > 15: #25:
        start_x += 1

for _ in range(num_iter_v):
    if proj_v[end_x] > 125:
        end_x -= 1

print('processing.. %s.png' % idx)
output_char = char[start_y:end_y, start_x:end_x]
output_char = get_cropped_char(output_char)
return output_char


def get_cropped_char(img):
    """
    Returns Grayscale cropped image
    """

img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

blur = cv2.GaussianBlur(img, (3,3), 0)

thresh = cv2.adaptiveThreshold(blur, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 75, 10)
im2, cnts, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

contour = None
for c in cnts:
    area = cv2.contourArea(c)
    if area > 100:
        contour = c
if contour is None: return None
(x, y, w, h) = cv2.boundingRect(contour)
img = img[y:y+h, x:x+w]
return img

person Arka    schedule 04.10.2017    source источник


Ответы (2)


Я не думаю, что это хороший способ напрямую обрезать символ после порога изображения. Я считаю, что morphy-op может устроить сцену.

Элементы блока расположены аккуратно, поэтому попробуйте morphy-erode-op, чтобы разделить блоки (или удалить границы блоков). Как только вы получите изображение символов clean, вы можете легко обрезать изображения символов.

...

Плохой английский, 哈哈哈


Это результат, который я получаю.

Обрезанные изображения.

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

Шаги:

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

person Kinght 金    schedule 04.10.2017
comment
Вы про эрозионную операцию? - person Arka; 04.10.2017
comment
Ух ты. Это именно то, что я хочу сделать. Но, после эрозии. Как разделить коробки? - person Arka; 04.10.2017
comment
Вторая строка — эрозия-операция, третья строка — порог-операция. Затем выполните findContours и отфильтруйте их по ширине/высоте/площади и т. д., вы можете получить отдельную ограничительную рамку (как показано во второй строке). Используйте cv2.rectangle для рисования заполненного прямоугольника, как четвертая строка на черном холсте, вы можете получить маску. Затем используйте этот make для работы с серым, вы можете получить чистые изображения char. - person Kinght 金; 04.10.2017

Я новичок в OpenCV (и работаю над подобным проектом...), но вот что я могу сказать по своему опыту. Извлечение чистых символов возможно, по крайней мере, для последних двух. Первый немного сложнее из-за линии, которая пересекает число.

Вы должны сделать серую версию изображения, порог и попробовать некоторые операции открытия/закрытия. После этого вам нужно выполнить морфологическое преобразование чтобы удалить горизонтальные/вертикальные линии каждого квадрата. Я попробовал свою версию программы, и она работает на 40%. Мне нужно его улучшить...

После этого с результатом вы должны извлечь ограничивающую рамку каждого числа. Это не сложно. Некоторые номера не удастся, но большинство из них будут извлечены. «Чрезвычайно чистый» довольно сложно получить на этом уровне.

Проведите больше исследований. Существует множество примеров того, как выполнять большинство операций.

РЕДАКТИРОВАТЬ: у вас должно быть изображение, похожее на мое. Работать над чем-то таким проще..

пример

Вот чего я добился от своего: посмотрите на внутренние квадраты, каждый вокруг одного числа. Их можно легко извлечь и сохранить для последующей обработки.

пример2

person lucians    schedule 04.10.2017
comment
Я также новичок в OpenCV. Я борюсь с этими проблемами в течение последних нескольких недель. Так как результаты непостоянны, у меня минимум 5 подходов к каждому шагу. В вашем случае вы сначала удаляете горизонтальные/вертикальные линии, используя открытие/закрытие, затем обнаруживаете контуры, а затем ограничиваете область обнаруженных контуров? - person Arka; 04.10.2017
comment
Ну, я использую OpenCV и Python в течение последних 3 месяцев... Процесс, который я использую, близок к описанному вами, операция более или менее. - person lucians; 04.10.2017
comment
Насколько точно вам удалось убрать границы на вашем изображении? - person Arka; 04.10.2017
comment
На изображениях, которые я разместил, программа только выделяет их, а не удаляет. Я попытался с изображением, которое вы разместили выше, и тот же скрипт выдает ошибку. Пожалуйста, предоставьте лучшее изображение, и я прогоню его через программу. Если получится, выложу код, если нет, то ничего. Поймите меня, он уже не такой открытый, как раньше.. - person lucians; 04.10.2017
comment
Как вы фильтруете ограничивающие рамки символов? Как вы можете отличить персонажей от ящиков? Мне интересно знать. - person Arka; 27.10.2017
comment
Я не говорю коробки отдельно от символов. Я извлекаю их. Найдите ROI извлечения. - person lucians; 27.10.2017
comment
Но когда вы извлекаете, вы можете получить часть окружающих ящиков, кроме персонажа. Как вы справляетесь с этой ситуацией? - person Arka; 27.10.2017