pytesseract image_to_string недостаточно точен - PullRequest
1 голос
/ 25 мая 2020

Я хочу читать цифры в al oop из обрезанного изображения судоку, используя python (newby на этом языке ...), и в поиске в Google рекомендуется использовать pytesseract,

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


from PIL import Image
import pytesseract

image = Image.open('./test.png')

width, height = image.size
left = 0
top = 0
i = 0
j = 0
while (top < height):
    while (left < width):
        crop_img = image.crop((left, top, left + width / 9,  top + height / 9))
        print(i, j, pytesseract.image_to_string(crop_img, config='--psm 6'))
        left += width / 9
        j += 1
    top += height / 9
    i += 1
    left = 0
    j = 0

результат print был таким


0 0 5
0 1 3
0 2 a
0 3 po
0 4 7
0 5 |
0 6 So
0 7 7
0 8 _
1 0 6
1 1 
1 2 7
1 3 
1 4 9
1 5 
1 6 So
1 7 7
1 8 a
2 0 -
2 1 9
2 2 
2 3 P|
2 4 i
2 5 |
2 6 -
2 7 6
2 8 a
3 0 8
3 1 a
3 2 a
3 3 po
3 4 6
3 5 |
3 6 So
3 7 7
3 8 
4 0 4
4 1 -
4 2 -
4 3 
4 4 i
4 5 
4 6 -
4 7 _
4 8 
5 0 7
5 1 _
5 2 _
5 3 S|
5 4 
5 5 |
5 6 |
5 7 _
5 8 6.
6 0 |
6 1 6
6 2 7
6 3 P|
6 4 7
6 5 |
6 6 
6 7 
6 8 _
7 0 _
7 1 _
7 2 |
7 3 
7 4 
7 5 9
7 6 So
7 7 _
7 8 
8 0 |
8 1 |
8 2 
8 3 po
8 4 
8 5 |
8 6 So
8 7 
8 8 9

недостаточно точно, но не так уж плохо.

Итак, моя вторая попытка использовала cv2 вместо PIL, и, как было предложено в других ответах, я сместил pi c, чтобы он был черным текстом на белом bg (может быть, это немного беспорядочно и не лучшая практика, советы приветствуются :))


import pytesseract
import cv2

image = cv2.imread('./test.png', 0)
height, width = image.shape
left = 0
top = 0
i = 0
j = 0
while (top < height):
    while (left < width):
        crop_img = image[int(top):int(top + height/9),
                         int(left):int(left + width/9)]
        thresh = cv2.threshold(
            crop_img, 155, 255, cv2.THRESH_BINARY_INV)[1]
        result = cv2.GaussianBlur(thresh, (5, 5), 0)
        result = 255 - result
        print(i, j, pytesseract.image_to_string(result, config='--psm 6'))
        left += width / 9
        j += 1
    top += height / 9
    i += 1
    left = 0
    j = 0

что дает мне


  0 0 5
  0 1 3
  0 2 S|
  0 3 pS
  0 4 7
  0 5 |
  0 6 pS
  0 7 7
  0 8 7
  1 0 6
  1 1 po
  1 2 S|
  1 3 1
  1 4 9
  1 5 5 |
  1 6 pS
  1 7 7
  1 8 7
  2 0 pp
  2 1 Oo
  2 2 
  2 3 po
  2 4 
  2 5 |
  2 6 pS
  2 7 6
  2 8 |
  3 0 3
  3 1 po
  3 2 S|
  3 3 po
  3 4 6
  3 5 |
  3 6 pp
  3 7 7
  3 8 3)
  4 0 4
  4 1 |
  4 2 S|
  4 3 8
  4 4 |
  4 5 3]
  4 6 |
  4 7 7
  4 8 1
  5 0 7
  5 1 SS
  5 2 S|
  5 3 S|
  5 4 2
  5 5 |
  5 6 p
  5 7 |
  5 8 6.
  6 0 po
  6 1 6
  6 2 S|
  6 3 pS
  6 4 
  6 5 |
  6 6 
  6 7 
  6 8 7
  7 0 -
  7 1 -
  7 2 -
  7 3 4
  7 4 1
  7 5 9 |
  7 6 |
  7 7 i
  7 8 
  8 0 -
  8 1 -
  8 2 S|
  8 3 pS
  8 4 8
  8 5 |
  8 6 P|
  8 7 
  8 8 9)

в обоих случаях я сохранено (.save(} для PIL и imwrite для cv2) изображение кадрирования для отладки, и на самом деле изображения довольно четкие, например в cv2 кадрированном { 2, 2 } месте (которое оценивается как пустое место) обрезанное изображение

2,2

полное изображение судоку

sudoku

спасибо в dvance!

1 Ответ

2 голосов
/ 25 мая 2020

Для этого я использовал OpenCV для изображения, а затем сохранил плату в массиве numpy. Главное, что я сделал, - это добавил аргумент конфигурации для вызова image_to_string(), чтобы ограничить вывод только цифрами. Однако это займет некоторое время, поскольку он прогнозирует индивидуально для каждого di git, как я думаю, вы были в исходном. пробелы.

array([[5, 3, 0, 0, 7, 0, 0, 0, 0],
       [6, 0, 0, 1, 9, 5, 0, 0, 0],
       [0, 9, 8, 0, 0, 0, 0, 6, 0],
       [8, 0, 0, 0, 6, 0, 0, 0, 3],
       [4, 0, 0, 8, 0, 3, 0, 0, 1],
       [7, 0, 0, 0, 2, 0, 0, 0, 6],
       [0, 6, 0, 0, 0, 0, 2, 8, 0],
       [0, 0, 0, 4, 1, 9, 0, 0, 5],
       [0, 0, 0, 0, 8, 0, 0, 7, 9]], dtype=uint8)

Не самый чистый, но вроде неплохо работает.

...