python - easyocr 没有检测到整数值
问题描述
我正在尝试检测在我的 sqares 中找到的数字,并且我认为我可以使用 libary easyocr
,但由于某种原因我读取了错误的值。
这里有我所有的照片(它们是分开的,这只是为了展示它们) ¨ 我怎么找不到任何数字?
from PIL import Image
from operator import itemgetter
import numpy as np
import easyocr
import cv2
import re
import imutils
import pytesseract
pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract'
reader = easyocr.Reader(['ch_sim','en']) # need to run only once to load model into memory
#Define empty array
Cubes = []
def getNumber(ROI):
img = cv2.imread(ROI)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(gray,127,255,0)
#cv2.imshow(thresh)
#cv2.imshow('Thresholded original',thresh)
#cv2.waitKey(0)
## Get contours
contours,h = cv2.findContours(thresh,cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE)
## only draw contour that have big areas
imx = img.shape[0]
imy = img.shape[1]
lp_area = (imx * imy) / 10
tmp_img = img.copy()
for cnt in contours:
approx = cv2.approxPolyDP(cnt,0.01 * cv2.arcLength(cnt, True), True)
if cv2.contourArea(cnt) > lp_area:
# Draw box corners and minimum area rectangle
rect = cv2.minAreaRect(cnt)
box = cv2.boxPoints(rect)
box = np.int0(box)
#cv2.drawContours(tmp_img, [box], 0, (0, 50, 255), 3)
#cv2.circle(tmp_img, tuple(box[0]), 8, (0, 255, 0), -1)
#cv2.circle(tmp_img, tuple(box[1]), 8, (0, 255, 0), -1)
#cv2.circle(tmp_img, tuple(box[2]), 8, (0, 255, 0), -1)
#cv2.circle(tmp_img, tuple(box[3]), 8, (0, 255, 0), -1)
#cv2.imshow(tmp_img)
#cv2.imshow('Minimum Area Rectangle', tmp_img)
#cv2.waitKey(0)
## Correct orientation and crop
# Link, https://jdhao.github.io/2019/02/23/crop_rotated_rectangle_opencv/
width = int(rect[1][0])
height = int(rect[1][1])
src_pts = box.astype("float32")
dst_pts = np.array([[0, height-1],
[0, 0],
[width-1, 0],
[width-1, height-1]], dtype="float32")
M = cv2.getPerspectiveTransform(src_pts, dst_pts)
warped = cv2.warpPerspective(img, M, (width, height))
# Run OCR on cropped image
# If the predicted value is digit print else rotate first
result = reader.readtext(warped)
print(result)
predicted_digit = result[0][1]
if np.char.isdigit(predicted_digit) == True:
cv2.imshow("warped " + ROI,warped)
else:
rot_img = warped.copy()
for i in range(0, 3):
rotated_image = cv2.rotate(rot_img, cv2.cv2.ROTATE_90_CLOCKWISE)
result = reader.readtext(rotated_image)
#if np.array(result).size == 0:
# continue
if not result:
rot_img = rotated_image
continue
#if len(result) == 0:
# continue
predicted_digit = result[0][1]
#print(result)
#print(predicted_digit)
#cv2.imshow(rotated_image)
if np.char.isdigit(predicted_digit) == True:
cv2.imshow("Image " + ROI, rotated_image)
break
rot_img = rotated_image
return predicted_digit
def sortNumbers(Cubes):
Cubes = sorted(Cubes, key=lambda x: int(x[2]))
#Cubes.sort(key=itemgetter(2)) # In-place sorting
#Cubes = sorted(Cubes, key=itemgetter(2)) # Create a new list
return Cubes
#img = cv2.imread('gulRecNum.jpg')
img = cv2.imread('boxes.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# convert to HSV, since red and yellow are the lowest hue colors and come before green
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# create a binary thresholded image on hue between red and yellow
#Change these if cube colours changes?
lower =(20, 100, 100)
upper = (30, 255, 255)
#lower = (0,240,160)
#upper = (30,255,255)
thresh = cv2.inRange(hsv, lower, upper)
# apply morphology
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (9,9))
clean = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (15,15))
clean = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
# get external contours
contours = cv2.findContours(clean, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
result2 = img.copy()
mask = np.zeros(result2.shape, dtype=np.uint8)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
ROI_number = 0
for c in contours:
cv2.drawContours(result2,[c],0,(0,0,0),2)
# get rotated rectangle from contour
rot_rect = cv2.minAreaRect(c)
box = cv2.boxPoints(rot_rect)
box = np.int0(box)
# draw rotated rectangle on copy of img
cv2.drawContours(result2,[box],0,(0,0,0),2)
# Gør noget hvis arealet er større end 1.
# Whats the area of the component?
areal = cv2.contourArea(c)
if(areal > 1):
# get the center of mass
M = cv2.moments(c)
cx = int(M['m10']/M['m00'])
cy = int(M['m01']/M['m00'])
center = (cx, cy)
print("\nx: ",cx,"\ny: ",cy)
color = (0, 0, 255)
cv2.circle(result2, center, 3, color, -1)
cv2.putText(result2, "center", (int(cx) - 10, int(cy) - 20),
cv2.FONT_HERSHEY_SIMPLEX, 1.2, color, 2)
x,y,w,h = cv2.boundingRect(c)
ROI = 255 - thresh[y:y+h, x:x+w]
cv2.drawContours(mask, [c], -1, (255,255,255), -1)
cv2.imwrite('ROI_{}.png'.format(ROI_number), ROI)
#Read saved image (number)
result = getNumber('ROI_{}.png'.format(ROI_number))
print("ROI_number: ", result)
Cubes.append([cx, cy, result])
ROI_number += 1
# save result
cv2.imwrite("4cubes_result2.png",result2)
# display result
imS = cv2.resize(result2, (600, 400))
cv2.imshow("result2", imS)
#cv2.imshow('mask', mask)
#cv2.imshow('thresh', thresh)
SortedCubes = sortNumbers(Cubes)
print("\nFound array [x, y, Cube_num] = ", Cubes)
print("Sorted array [x, y, Cube_num] = ", SortedCubes)
cv2.waitKey(0)
cv2.destroyAllWindows()
编辑
我也得到了这两张照片来尝试
编辑 2
y: 160
shape: rectangle
areal: 723.0
['ta'] : image should have been 4
x: 269
y: 155
shape: rectangle
areal: 637.5
['1'] : image should have been 1
x: 64
y: 149
shape: rectangle
areal: 748.5
['20'] : image should have been 2
x: 125
y: 141
shape: rectangle
areal: 714.5
['5.'] : image should have been 5
x: 222
y: 127
shape: rectangle
areal: 662.5
['3'] : image should have been 3
x: 165
y: 101
shape: rectangle
areal: 666.5
['40'] : image should have been 7
x: 58
y: 96
shape: rectangle
areal: 782.5
['L', 'RJ'] : image should have been 8
x: 279
y: 90
shape: rectangle
areal: 653.5
['EJ'] : image should have been 9
x: 107
y: 84
shape: rectangle
areal: 717.5
['C'] : image should have been 6
所有图像均从此图像中剪切
解决方案
您可能需要不同的处理方法,并且您可能需要设置 page-segmentation-mode ( psm
)tesseract
在这里,当您使用adaptive-thresholding
( at
)bitwise_not
操作时
现在,当您使用psm
模式 6 阅读图像时(假设一个统一的文本块。)
结果将是:
['34', '215', '28', '7', '5']
不幸的是6
并9
没有被检测到,也许如果您更改at
参数可以找到更好的结果。
代码:
import cv2
import pytesseract
img = cv2.imread("u3ZTw.png")
gry = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
thr = cv2.adaptiveThreshold(gry, 255, cv2.ADAPTIVE_THRESH_MEAN_C,
cv2.THRESH_BINARY_INV, 59, 88)
bnt = cv2.bitwise_not(thr)
txt = pytesseract.image_to_string(bnt, config="--psm 6 digits")
txt = txt.strip().split("\n")
print(txt)
cv2.imshow("bnt", bnt)
cv2.waitKey(0)
对于编辑中的照片:
您必须更改adaptive-threshold
每个不同图像的参数。
更具体地说,您必须更改blockSize
和C
参数才能获得预期的结果。
例如,对于 4 号和 5 号,我更改了:
blockSize
: 31 (之前是 59)C
: 30 (之前是 88)-
import cv2 import pytesseract img = cv2.imread("num5.png") gry = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) thr = cv2.adaptiveThreshold(gry, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, 31, 30) bnt = cv2.bitwise_not(thr) txt = pytesseract.image_to_string(bnt, config="--psm 6 digits") txt = txt.strip().split("\n") print(txt) cv2.imshow("bnt", bnt) cv2.waitKey(0)
图片:
结果:
-
['4']
-
['5']
-
推荐阅读
- docker - 连接到独立 chrome 调试容器时如何避免身份验证?
- postgresql - 在 postgresql 中查询多个 Jsonb 列
- point - 将边界框[(x1,y1),(x2,y2),(x3,y3),(x4,y4)] 内的点(x,y) 转换为航向
- ruby-on-rails - 如何在 Rails 中生成序列码字符串
- python - 使用python和mobaxterm将25个随机文件从一个文件夹复制到另一个文件夹
- javascript - React 组件无法加载图像?
- sql - 合并按特定列分组的不同列的结果
- javascript - 如何在另一个文件中插入一个handlebarsjs文件
- python - 如何在抓取之前使用 selenium 从一个 url 选项卡转到另一个?
- r - 在 R 中将多个数据框合并为一个