Задача состоит в следующем. Есть сертификат на экспорт автомобиля из Японии. Из него необходимо достать определенные значения(выделил зеленым на изображении):
Это обычные сканы документов или просто картинки объединённые в .pdf формат, текст в которых - не определен(если открыть в каком-нибудь pdf редакторе).
Чтобы не мучаться с чтением всего документа, а потом выделением из него необходимых значений - я решил поступить наоборот - сначала выделить в документе +- необходимую область для распознавания. Наложив, 10 документов друг на друга в фотошопе, я нашел примерные координаты необходимых блоков для обрезки оригинального изображения и с помощью функции crop - обрезал изображения по примерным точкам.
image.crop(cpor_cords)
После чего, добавив яркости и контрастности, а так же - применив черно-белый фильтр - я обработал изображения. Далее подключил EasyOCR для распознавания текста на картинке. Результат, мягко сказать - был не очень. Из 20 документов - верно определялось 2-3 штуки. Попробовал ручками - убрать все на изображении кроме текста(границы ячеек, вводные знаки и т.д.) - тогда результат был куда лучше. Тогда уже решил провести следующую процедуру: обрезать обрезанные изображения:
width, height = final_image.size
pixel_data = []
for y in range(height):
for x in range(width):
color = pixels[x, y]
pixel_data.append((x, y, color))
x1 = None
x2 = None
y1 = None
y2 = None
for pixel in pixel_data:
x, y = pixel[0], pixel[1]
r, g, b = pixel[2][:3]
if y == 2 and r < 200 and g < 200 and b < 200:
print(x)
if x1 is None:
#print(x,y,r,g,b)
x1 = x
x2 = x
if type != 'serial':
if x == 9:
if r != 255 and g != 255 and b != 255:
if y1 is None:
y1 = y
y2 = y
if type == 'serial':
if x == 100:
if r != 255 and g != 255 and b != 255:
if y1 is None:
y1 = y
if x == 900:
if r != 255 and g != 255 and b != 255:
y2 = y
if type != 'serial':
x2 -= 23
x1 += 20
crop_final = x1, y1, x2, y2
print('Croped: ',crop_final)
image2 = Image.open('final_output_' + str(type) + '.png')
cropped_image = image2.crop(crop_final)
То есть, логика была следующая: открываем изображение и разбираем его по пикселям и цветам в нем.
Проходимся по ширине в 9 пикселей. Если у нас не задана y1, а цвет в данной точки не белый - то y1 равно данным координатам. Последняя точка y2 - последняя точка на данной ширине, которая не равна цвету 255,255,255. Для серийного номера брал 2 точки x - это на 100 пикселе и на 900-м
Тут я уже столкнулся с другой проблемой: Либо неопределенна координаты y2 или вообще некорректно. Зачастую, в необходимых областях - по мимо границы ячейки - находился либо текст с других ячеек - либо не было ничего и y2 = ширине изображения. Менял точки прохода: х = 12,15,20 и т.д. - так как это сканы, где то документ положили к верхнему правому углу сканера, где то к нижнему левому, а где то вовсе наклон 5*. Тогда решил поменять алгоритм - так как серийники +- обрезались ровно и документы имели четко один и тот же размер - я решил использовать точку G. Я искал точку отсчета - верхний левый угол ячейки серийного номера. И если мы знаем данную точку - мы рассчитываем от нее уже расстояния до других ячеек по пикселям. Но кривые обрезки все равно достаточно часто проскакивали - либо точка G находилась чуть выше границы ячейки таблицы, или чуть ниже границы.
В общем. Неделю ковырял - не знаю что уже можно придумать? Есть ли какие-нибудь альтернативы, чтобы необходимые области обрезались как надо? В идеале - если на изображение применен фильтр, яркость и контрастность - в 95% текст читается корректно - а этого более чем достаточно.