Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 无法使用排序控制器生成七段OCR_Python_Opencv_Image Processing_Ocr - Fatal编程技术网

Python 无法使用排序控制器生成七段OCR

Python 无法使用排序控制器生成七段OCR,python,opencv,image-processing,ocr,Python,Opencv,Image Processing,Ocr,我正试图建立一个OCR来识别七段显示,如下所述 使用OpenCV的预处理工具,我在这里得到了它 现在我试着学习本教程- 但在这方面 digitCnts = contours.sort_contours(digitCnts, method="left-to-right")[0] digits = [] 我得到的错误是- 使用THRESH\u BINARY\u INV解决了该错误,但OCR仍然无法工作。任何修复都很好 文件“/Users/ms/anaconda3/lib/python3

我正试图建立一个OCR来识别七段显示,如下所述

使用OpenCV的预处理工具,我在这里得到了它

现在我试着学习本教程-

但在这方面

digitCnts = contours.sort_contours(digitCnts,
    method="left-to-right")[0]
digits = []
我得到的错误是-

使用THRESH\u BINARY\u INV解决了该错误,但OCR仍然无法工作。任何修复都很好

文件“/Users/ms/anaconda3/lib/python3.6/site packages/imutils/courtous.py”,第25行,在sort\u等高线中 键=λb:b[i],反向=反向)

ValueError:没有足够的值来解包(应为2,得到0)

你知道如何解决这个问题并使我的OCR成为一个工作模型吗

我的全部代码是:

import numpy as np 
import cv2
import imutils
# import the necessary packages
from imutils.perspective import four_point_transform
from imutils import contours
import imutils
import cv2

# define the dictionary of digit segments so we can identify
# each digit on the thermostat
DIGITS_LOOKUP = {
    (1, 1, 1, 0, 1, 1, 1): 0,
    (0, 0, 1, 0, 0, 1, 0): 1,
    (1, 0, 1, 1, 1, 1, 0): 2,
    (1, 0, 1, 1, 0, 1, 1): 3,
    (0, 1, 1, 1, 0, 1, 0): 4,
    (1, 1, 0, 1, 0, 1, 1): 5,
    (1, 1, 0, 1, 1, 1, 1): 6,
    (1, 0, 1, 0, 0, 1, 0): 7,
    (1, 1, 1, 1, 1, 1, 1): 8,
    (1, 1, 1, 1, 0, 1, 1): 9
}

# load image
image = cv2.imread('d4.jpg')
# create hsv
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)

 # set lower and upper color limits
low_val = (60,180,160)
high_val = (179,255,255)
# Threshold the HSV image 
mask = cv2.inRange(hsv, low_val,high_val)
# find contours in mask
ret, cont, hierarchy = cv2.findContours(mask,cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# select the largest contour
largest_area = 0
for cnt in cont:
    if cv2.contourArea(cnt) > largest_area:
        cont = cnt
        largest_area = cv2.contourArea(cnt)

# get the parameters of the boundingbox
x,y,w,h = cv2.boundingRect(cont)

# create and show subimage
roi = image[y:y+h, x:x+w]
cv2.imshow("Result", roi)


#  draw box on original image and show image
cv2.rectangle(image, (x,y),(x+w,y+h), (0,0,255),2)
cv2.imshow("Image", image)

grayscaled = cv2.cvtColor(roi,cv2.COLOR_BGR2GRAY)
retval, threshold = cv2.threshold(grayscaled, 10, 255, cv2.THRESH_BINARY)
retval2,threshold2 = cv2.threshold(grayscaled,125,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
cv2.imshow('threshold',threshold2)
cv2.waitKey(0)
cv2.destroyAllWindows()
# find contours in the thresholded image, then initialize the
# digit contours lists
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 >= 15 and (h >= 30 and h <= 40):
        digitCnts.append(c)
# sort the contours from left-to-right, then initialize the
# actual digits themselves
digitCnts = contours.sort_contours(digitCnts,
    method="left-to-right")[0]
digits = []


# loop over each of the digits
for c in digitCnts:
    # extract the digit ROI
    (x, y, w, h) = cv2.boundingRect(c)
    roi = thresh[y:y + h, x:x + w]

    # 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 total / float(area) > 0.5:
            on[i]= 1

    # lookup the digit and draw it on the image
    digit = DIGITS_LOOKUP[tuple(on)]
    digits.append(digit)
    cv2.rectangle(output, (x, y), (x + w, y + h), (0, 255, 0), 1)
    cv2.putText(output, str(digit), (x - 10, y - 10),
        cv2.FONT_HERSHEY_SIMPLEX, 0.65, (0, 255, 0), 2)
# display the digits
print(u"{}{}.{}{}.{}{} \u00b0C".format(*digits))
cv2.imshow("Input", image)
cv2.imshow("Output", output)
cv2.waitKey(0)
将numpy导入为np
进口cv2
导入imutils
#导入必要的包
从imutils.perspective导入四点变换
从imutils导入等高线
导入imutils
进口cv2
#定义数字段字典,以便我们能够识别
#恒温器上的每个数字
数字\u查找={
(1, 1, 1, 0, 1, 1, 1): 0,
(0, 0, 1, 0, 0, 1, 0): 1,
(1, 0, 1, 1, 1, 1, 0): 2,
(1, 0, 1, 1, 0, 1, 1): 3,
(0, 1, 1, 1, 0, 1, 0): 4,
(1, 1, 0, 1, 0, 1, 1): 5,
(1, 1, 0, 1, 1, 1, 1): 6,
(1, 0, 1, 0, 0, 1, 0): 7,
(1, 1, 1, 1, 1, 1, 1): 8,
(1, 1, 1, 1, 0, 1, 1): 9
}
#加载图像
image=cv2.imread('d4.jpg')
#创建hsv
hsv=cv2.cvt颜色(图像,cv2.COLOR\u BGR2HSV)
#设置颜色下限和上限
低值=(60180160)
高值=(179255255)
#对HSV图像进行阈值设置
掩码=cv2.inRange(hsv、低值、高值)
#在蒙版中查找轮廓
ret,cont,hierarchy=cv2.findContours(掩码,cv2.RETR\u外部,cv2.CHAIN\u近似值\u简单)
#选择最大的轮廓
最大面积=0
对于cont中的cnt:
如果cv2.轮廓面积(cnt)>最大面积:
cont=cnt
最大面积=cv2。轮廓面积(cnt)
#获取边界框的参数
x、 y,w,h=cv2.boundingRect(续)
#创建并显示子图像
roi=图像[y:y+h,x:x+w]
cv2.imshow(“结果”,投资回报率)
#在原始图像上绘制框并显示图像
cv2.矩形(图像,(x,y),(x+w,y+h),(0,0255),2)
cv2.imshow(“图像”,图像)
灰度=cv2.CVT颜色(roi,cv2.COLOR\u BGR2GRAY)
retval,threshold=cv2.threshold(灰度,10255,cv2.THRESH_二进制)
retval2,threshold2=cv2.threshold(灰度,125255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
cv2.imshow(“阈值”,阈值2)
cv2.等待键(0)
cv2.destroyAllWindows()
#在阈值图像中查找轮廓,然后初始化
#数字轮廓列表
cnts=cv2.findContentours(threshold2.copy(),cv2.RETR_EXTERNAL,
cv2.链条(近似简单)
cnts=imutils.GRAP_轮廓(cnts)
digitCnts=[]
#在候选数字区域上循环
对于碳纳米管中的碳:
#计算轮廓的边界框
(x,y,w,h)=cv2.boundingRect(c)
#如果轮廓足够大,它必须是一个数字
如果w>=15和(h>=30和h 0.5:
关于[i]=1
#查找数字并将其绘制在图像上
数字=数字\u查找[元组(打开)]
数字。追加(数字)
cv2.矩形(输出,(x,y),(x+w,y+h),(0,255,0),1)
cv2.putText(输出,str(数字),(x-10,y-10),
cv2.FONT_HERSHEY_SIMPLEX,0.65,(0,255,0),2)
#显示数字
打印(u{}{}.{}{}.{}{}{}\u00b0C.format(*位))
cv2.imshow(“输入”,图像)
cv2.imshow(“输出”,输出)
cv2.等待键(0)

在修复我的OCR方面会有很大的帮助

我认为您创建的查找表是用于
七位数显示
,而不是
七位数OCR
。至于显示的大小是固定的,我想您可以尝试将其分割为单独的区域,并使用
模板匹配
k-means
进行识别

这是我的预处理步骤:

(1) 在
HSV

mask = cv2.inRange(hsv, (50, 100, 180), (70, 255, 255))

(2) 通过使用LUT投影和识别标准七位数字来尝试分离:

(3) 在检测到的绿色显示屏上尝试


因此,正如我在评论中所说,有两个问题:

  • 您试图在白色背景上找到黑色轮廓,这与。这是使用THRESH_BINARY_INV flag而不是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)
    
    我通读了这些评论,似乎LUT中的一些条目可能是错误的。所以我要让你们自己去弄清楚。以下是找到的单个数字(但未识别):

    或者,您可以使用tesseract来识别这些检测到的数字


    希望有帮助

    如果您查看上的OpenCV文档,它会提到要查找的对象应该是白色的,背景应该是黑色的。尝试使用,
    THRESH\u BINARY\u INV
    而不是
    THRESH\u BINARY
    。错误表明它没有找到任何轮廓。但它仍然没有打印任何我要求修复OCR的内容。你能在你的系统上运行它并验证错误是什么吗?请@RickM。Rick提到的问题肯定是相关的。从这里开始,您这边的一些调试工作不会有什么坏处(即使只是简单地将变量打印到控制台)如果您对实现此排序功能感兴趣,请选择过滤条件
    w>=15和(h>=30和h)
    
    # 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