Python pytesseract 从各种图像中提取数字
Python pytesseract extract number from various images
我有各种类型的图像:
如您所见,它们有点相似,但我无法正确提取它们的编号。
到目前为止,我的代码包含以下内容:
lower = np.array([250,200,90], dtype="uint8")
upper = np.array([255,204,99], dtype="uint8")
mask = cv2.inRange(img, lower, upper)
res = cv2.bitwise_and(img, img, mask=mask)
data = image_to_string(res, lang="eng", config='--psm 13 --oem 3 -c tessedit_char_whitelist=0123456789')
numbers = int(''.join(re.findall(r'\d+', data)))
我尝试调整 psm 参数 6,8 和 13 它们都适用于其中一些示例,但总的来说 none,我不知道如何解决我的问题。
提出的另一种解决方案是:
gry = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
(h, w) = gry.shape[:2]
gry = cv2.resize(gry, (w*2, h*2))
erd = cv2.erode(gry, None, iterations=1)
thr = cv2.threshold(erd, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
bnt = cv2.bitwise_not(thr)
但是,在第一张图片上,bnt 给出:
然后 pytesseract 看到 460..
有什么想法吗?
我的做法:
需要上采样才能准确识别。调整两倍大小将使图像可读。
Erosion操作是一种形态学操作,有助于去除像素的边界。侵蚀去除数字上的笔画,使其更容易检测。
阈值处理(二进制和反二进制)有助于揭示特征。
Bitwise-not 是一种对提取部分图像非常有用的算术运算。
更多方法简单阅读Improving the quality of the output
Erosion
Threshold
Bitwise-not
更新
第一张图片易于阅读,因为它不需要任何预处理技术。请阅读How to Improve Quality of Tesseract
1460
720
3250
3146
2681
1470
代码:
import cv2
import pytesseract
img_lst = ["oqWjd.png", "YZDt1.png", "MUShJ.png", "kbK4m.png", "POIK2.png", "4W3R4.png"]
for i, img_nm in enumerate(img_lst):
img = cv2.imread(img_nm)
gry = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
(h, w) = gry.shape[:2]
if i == 0:
thr = gry
else:
gry = cv2.resize(gry, (w * 2, h * 2))
erd = cv2.erode(gry, None, iterations=1)
if i == len(img_lst)-1:
thr = cv2.threshold(erd, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
else:
thr = cv2.threshold(erd, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
bnt = cv2.bitwise_not(thr)
txt = pytesseract.image_to_string(bnt, config="--psm 6 digits")
print("".join([t for t in txt if t.isalnum()]))
cv2.imshow("bnt", bnt)
cv2.waitKey(0)
如果要在结果中显示逗号,请将 print("".join([t for t in txt if t.isalnum()]))
行更改为 print(txt)
。
并不是说在第四张图片上,阈值方法从二进制变为逆二进制。二进制阈值并不是对所有图像都能准确工作。所以你需要改变。
我有各种类型的图像:
如您所见,它们有点相似,但我无法正确提取它们的编号。
到目前为止,我的代码包含以下内容:
lower = np.array([250,200,90], dtype="uint8")
upper = np.array([255,204,99], dtype="uint8")
mask = cv2.inRange(img, lower, upper)
res = cv2.bitwise_and(img, img, mask=mask)
data = image_to_string(res, lang="eng", config='--psm 13 --oem 3 -c tessedit_char_whitelist=0123456789')
numbers = int(''.join(re.findall(r'\d+', data)))
我尝试调整 psm 参数 6,8 和 13 它们都适用于其中一些示例,但总的来说 none,我不知道如何解决我的问题。
提出的另一种解决方案是:
gry = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
(h, w) = gry.shape[:2]
gry = cv2.resize(gry, (w*2, h*2))
erd = cv2.erode(gry, None, iterations=1)
thr = cv2.threshold(erd, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
bnt = cv2.bitwise_not(thr)
但是,在第一张图片上,bnt 给出:
然后 pytesseract 看到 460..
有什么想法吗?
我的做法:
需要上采样才能准确识别。调整两倍大小将使图像可读。
Erosion操作是一种形态学操作,有助于去除像素的边界。侵蚀去除数字上的笔画,使其更容易检测。
阈值处理(二进制和反二进制)有助于揭示特征。
Bitwise-not 是一种对提取部分图像非常有用的算术运算。
更多方法简单阅读Improving the quality of the output
Erosion | Threshold | Bitwise-not |
---|---|---|
更新
第一张图片易于阅读,因为它不需要任何预处理技术。请阅读How to Improve Quality of Tesseract
1460
720
3250
3146
2681
1470
代码:
import cv2
import pytesseract
img_lst = ["oqWjd.png", "YZDt1.png", "MUShJ.png", "kbK4m.png", "POIK2.png", "4W3R4.png"]
for i, img_nm in enumerate(img_lst):
img = cv2.imread(img_nm)
gry = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
(h, w) = gry.shape[:2]
if i == 0:
thr = gry
else:
gry = cv2.resize(gry, (w * 2, h * 2))
erd = cv2.erode(gry, None, iterations=1)
if i == len(img_lst)-1:
thr = cv2.threshold(erd, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
else:
thr = cv2.threshold(erd, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
bnt = cv2.bitwise_not(thr)
txt = pytesseract.image_to_string(bnt, config="--psm 6 digits")
print("".join([t for t in txt if t.isalnum()]))
cv2.imshow("bnt", bnt)
cv2.waitKey(0)
如果要在结果中显示逗号,请将 print("".join([t for t in txt if t.isalnum()]))
行更改为 print(txt)
。
并不是说在第四张图片上,阈值方法从二进制变为逆二进制。二进制阈值并不是对所有图像都能准确工作。所以你需要改变。