我正尝试构建一个OCR来识别如下所述的七段显示
使用开放式简历的预处理工具
现在,我正在尝试遵循本教程-https://www.pyimagesearch.com/2017/02/13/recognizing-digits-with-opencv-and-python/
但在部分
ip
我收到错误消息-
使用THRESH_BINARY_INV解决了错误,但OCR仍无法正常工作,任何修复都很好
文件“ /Users/ms/anaconda3/lib/python3.6/site-packages/imutils/contours.py”,第25行,在sort_contours中 key = lambda b:b 1 [i],reverse = reverse))
ValueError:没有足够的值可解包(预期2,得到0)
任何想法如何解决这个问题并使我的OCR成为可行的模型
我的整个代码是:
digitCnts = contours.sort_contours(digitCnts,
method="left-to-right")[0]
digits = []
修复我的OCR很有帮助
答案 0 :(得分:2)
我认为您创建的查找表适用于seven-digit OCR
,而不适用于template-matching
。至于显示的大小是固定的,我认为您可以尝试将其分成多个单独的区域并使用k-means
或HSV
进行识别。
这是我的预处理步骤:
(1)在mask = cv2.inRange(hsv, (50, 100, 180), (70, 255, 255))
{{1}}
(3)尝试检测到的绿色显示
答案 1 :(得分:1)
所以,正如我在评论中说的那样,存在两个问题:
您正在尝试在 white 背景上找到 black 轮廓,该轮廓与OpenCV documentation相反。这是使用 THRESH_BINARY_INV 标志而不是 THRESH_BINARY 解决的。
由于未连接数字,因此找不到该数字的完整轮廓。所以我尝试了一些形态学操作。步骤如下:
2a)使用以下代码在上图中打开:
threshold2 = cv2.morphologyEx(threshold, cv2.MORPH_OPEN, np.ones((3,3), np.uint8))
2b)放大上一张图片:
threshold2 = cv2.dilate(threshold2, np.ones((5,1), np.uint8), iterations=1)
2c)由于会扩大到顶部边框,因此将图像的顶部裁剪为单独的数字:
height, width = threshold2.shape[:2]
threshold2 = threshold2[5:height,5:width]
注意不知何故,此处显示的图像没有我正在谈论的白色边框。尝试在新窗口中打开图像,您会明白我的意思。
因此,在解决了这些问题之后,轮廓非常好,并且看起来是应该是,如下所示:
cnts = cv2.findContours(threshold2.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
digitCnts = []
# loop over the digit area candidates
for c in cnts:
# compute the bounding box of the contour
(x, y, w, h) = cv2.boundingRect(c)
# if the contour is sufficiently large, it must be a digit
if w <= width * 0.5 and (h >= height * 0.2):
digitCnts.append(c)
# sort the contours from left-to-right, then initialize the
# actual digits themselves
cv2.drawContours(image2, digitCnts, -1, (0, 0, 255))
cv2.imwrite("cnts-sort.jpg", image2)
如下所示,轮廓以红色绘制。
现在,为了估计数字是否为代码,该部分某种程度上不起作用,我为此归咎于查找表。从下图可以看到,所有数字的边界矩形均已正确裁剪,但是查找表无法识别它们。
# loop over each of the digits
j = 0
for c in digitCnts:
# extract the digit ROI
(x, y, w, h) = cv2.boundingRect(c)
roi = threshold2[y:y + h, x:x + w]
cv2.imwrite("roi" + str(j) + ".jpg", roi)
j += 1
# compute the width and height of each of the 7 segments
# we are going to examine
(roiH, roiW) = roi.shape
(dW, dH) = (int(roiW * 0.25), int(roiH * 0.15))
dHC = int(roiH * 0.05)
# define the set of 7 segments
segments = [
((0, 0), (w, dH)), # top
((0, 0), (dW, h // 2)), # top-left
((w - dW, 0), (w, h // 2)), # top-right
((0, (h // 2) - dHC) , (w, (h // 2) + dHC)), # center
((0, h // 2), (dW, h)), # bottom-left
((w - dW, h // 2), (w, h)), # bottom-right
((0, h - dH), (w, h)) # bottom
]
on = [0] * len(segments)
# loop over the segments
for (i, ((xA, yA), (xB, yB))) in enumerate(segments):
# extract the segment ROI, count the total number of
# thresholded pixels in the segment, and then compute
# the area of the segment
segROI = roi[yA:yB, xA:xB]
total = cv2.countNonZero(segROI)
area = (xB - xA) * (yB - yA)
# if the total number of non-zero pixels is greater than
# 50% of the area, mark the segment as "on"
if area != 0:
if total / float(area) > 0.5:
on[i] = 1
# lookup the digit and draw it on the image
try:
digit = DIGITS_LOOKUP[tuple(on)]
digits.append(digit)
cv2.rectangle(roi, (x, y), (x + w, y + h), (0, 255, 0), 1)
cv2.putText(roi, str(digit), (x - 10, y - 10),
cv2.FONT_HERSHEY_SIMPLEX, 0.65, (0, 255, 0), 2)
except KeyError:
continue
我通读了website you mentioned in the question,从注释中看来,LUT中的某些条目可能是错误的。因此,我将由您自己解决。以下是找到的个人数字(但未被识别):
或者,您可以使用tesseract来识别这些检测到的数字。
希望有帮助!