pytesseract image_to_string 不够准确
pytesseract image_to_string not accurate enough
我想使用 python 从裁剪后的数独图片中循环读取数字(这个语言中的新手......)并使用谷歌搜索推荐使用 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
,并且按照其他答案中的建议,我将图片移动为白色 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 }
点(评估为空白点)裁剪的 img 是
完整的数独图像
提前致谢!
为此,我对图像使用了 OpenCV,然后将电路板保存到一个 numpy 数组中。我做的主要事情是为 image_to_string()
调用添加一个配置参数,以将输出限制为仅数字。不过这确实需要一段时间,因为它会像我认为你原来的那样单独预测每个数字。
import cv2
import numpy as np
import pytesseract
im = cv2.resize(cv2.imread('./test.png'), (900, 900))
out = np.zeros((9, 9), dtype=np.uint8)
for x in range(9):
for y in range(9):
num = pytesseract.image_to_string(im[10 + x*100:(x+1)*100 - 10, 10 + y*100:(y+1)*100 - 10, :], config='--psm 6 --oem 1 -c tessedit_char_whitelist=0123456789')
if num:
out[x, y] = num
这给了我你在你的 post 图像上的这个输出,其中 0 作为空格。
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)
它不是最干净的,但似乎工作得很好。
我想使用 python 从裁剪后的数独图片中循环读取数字(这个语言中的新手......)并使用谷歌搜索推荐使用 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
,并且按照其他答案中的建议,我将图片移动为白色 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 }
点(评估为空白点)裁剪的 img 是
完整的数独图像
提前致谢!
为此,我对图像使用了 OpenCV,然后将电路板保存到一个 numpy 数组中。我做的主要事情是为 image_to_string()
调用添加一个配置参数,以将输出限制为仅数字。不过这确实需要一段时间,因为它会像我认为你原来的那样单独预测每个数字。
import cv2
import numpy as np
import pytesseract
im = cv2.resize(cv2.imread('./test.png'), (900, 900))
out = np.zeros((9, 9), dtype=np.uint8)
for x in range(9):
for y in range(9):
num = pytesseract.image_to_string(im[10 + x*100:(x+1)*100 - 10, 10 + y*100:(y+1)*100 - 10, :], config='--psm 6 --oem 1 -c tessedit_char_whitelist=0123456789')
if num:
out[x, y] = num
这给了我你在你的 post 图像上的这个输出,其中 0 作为空格。
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)
它不是最干净的,但似乎工作得很好。