Почему мой код не сегментирует символы входного изображения?

#python #image-processing #deep-learning #ocr #image-segmentation

Вопрос:

Я пытаюсь выполнить сегментацию символов по изображению, но вывод не сегментируется.

Это мое новое входное изображение:

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

Это мой код для сегментации символов:

 word = cv2.imread('../input/word-image/word.PNG',0)

fig, ax1 = plt.subplots(1)
ax1.imshow(word, cmap="gray")
# the next two lines is based on the assumptions that the width of
# a license plate should be between 5% and 15% of the license plate,
# and height should be between 35% and 60%
# this will eliminate some
character_dimensions = (0.35*word.shape[0], 0.60*word.shape[0], 0.05*word.shape[1], 0.15*word.shape[1])
min_height, max_height, min_width, max_width = character_dimensions

characters = []
counter=0
column_list = []
for regions in regionprops(word):
    y0, x0, y1, x1 = regions.bbox
    region_height = y1 - y0
    region_width = x1 - x0

    if region_height > min_height and region_height < max_height and region_width > min_width and region_width < max_width:
        roi = word[y0:y1, x0:x1]

        # draw a red bordered rectangle over the character.
        rect_border = patches.Rectangle((x0, y0), x1 - x0, y1 - y0, edgecolor="red",
                                       linewidth=2, fill=False)
        ax1.add_patch(rect_border)

        # resize the characters to 20X20 and then append each character into the characters list
        resized_char = resize(roi, (20, 20))
        characters.append(resized_char)

        # this is just to keep track of the arrangement of the characters
        column_list.append(x0)
# print(characters)
plt.show()
 

Это текущий выходной сигнал:

Выход

В чем здесь может быть проблема?

Ответ №1:

Из документации по skimage.measure.regionprops :

Измерьте свойства помеченных областей изображения.

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

Итак, первым шагом будет создание правильного помеченного изображения, например, с помощью cv2.connectedComponents . Поэтому вам нужно будет (инвертировать) бинаризировать входное изображение заранее. Получив labels изображение, вы можете непосредственно приступить к своему циклу. Тем не менее, я бы отверг все предположения о ширине и высоте здесь.

Это был бы измененный код:

 import cv2
import matplotlib.pyplot as plt
from matplotlib import patches
from skimage.measure import regionprops
from skimage.transform import resize

# Read image as grayscale
word = cv2.imread('pFLpN.png', cv2.IMREAD_GRAYSCALE)

# Inverse binarize image, and find connected components
thr = cv2.threshold(word, 254, 255, cv2.THRESH_BINARY_INV)[1]
labels = cv2.connectedComponents(thr)[1]

# Maybe leave out any assumptions on the width and height...

# Prepare outputs
plt.figure(figsize=(18, 9))
plt.subplot(2, 2, 1), plt.imshow(word, cmap='gray'), plt.title('Original image')
plt.subplot(2, 2, 2), plt.imshow(thr, cmap='gray'), plt.title('Binarized image')
plt.subplot(2, 2, 3), plt.imshow(labels), plt.title('Connected components')
ax = plt.subplot(2, 2, 4), plt.imshow(word, cmap='gray')

# Iterate found connected components as before
# (Without checking width and height...)
characters = []
counter = 0
column_list = []
for regions in regionprops(labels):
    y0, x0, y1, x1 = regions.bbox
    region_height = y1 - y0
    region_width = x1 - x0
    roi = word[y0:y1, x0:x1]
    rect_border = patches.Rectangle((x0, y0), x1 - x0, y1 - y0, edgecolor='red',
                                    linewidth=2, fill=False)
    ax[0].add_patch(rect_border)

    resized_char = resize(roi, (20, 20))
    characters.append(resized_char)

    column_list.append(x0)

plt.title('Segmented characters')
plt.tight_layout(), plt.show()
 

И это было бы результатом:

Выход

 ----------------------------------------
System information
----------------------------------------
Platform:      Windows-10-10.0.19041-SP0
Python:        3.9.1
PyCharm:       2021.1.2
Matplotlib:    3.4.2
OpenCV:        4.5.2
scikit-image:  0.18.1
----------------------------------------
 

Комментарии:

1. Это было полезно!! Как я могу распечатать изображения отдельных символов out it?

2. Что вы подразумеваете под «печатью»? У вас уже есть roi = word[y0:y1, x0:x1] , из которого вырезан персонаж word . Сохраните roi , например, на каком-нибудь изображении. Или сделайте что-то дополнительное plt.imshow(roi) , если вы хотите отобразить отдельные символы.

3. Эй! Когда я пытаюсь ввести другое изображение , оно не сегментируется. Пожалуйста, взгляните на новое изображение, которое я ввел. Я отредактировал свой опубликованный вопрос. В чем может быть причина того же самого?!

4. Потому что на вашем первоначальном изображении был идеальный белый фон, в то время как на вашем новом изображении был какой-то белый/серый фон. Как и для каждой задачи обработки изображений, вам необходимо адаптировать предварительную обработку при изменении входных данных. Если вам нужно более общее решение, предоставьте больше примеров ввода в начале! Для этого нового изображения вы можете попробовать thr = cv2.threshold(word, 0, 255, cv2.THRESH_OTSU cv2.THRESH_BINARY_INV)[1] , что также будет работать для исходного изображения. Но это не гарантирует работу с вашими следующими 6 или 7 изображениями…

5. Этот код рисует ограничительные рамки на связанных символах. Но в моем языке есть даже символы, где не все символы имеют связанные компоненты! Что мне делать в этом случае???