Python 利用opencv进行数字识别

Python 利用opencv进行数字识别,python,opencv,ocr,Python,Opencv,Ocr,我有4个小图片 有数字6、16、9和9。我将图片和数字与我的模板进行比较,只有30个变体[0-30]。图片-截图是。数字出现在正方形的不同位置(示例中,9在左角,9在右角) 我使用两种方法:计算白色像素的数量 original = cv2.imread('im/16.png') sought = [254,254,254] result = np.count_nonzero(np.all(original==sought,axis=2)) 除6号和9号外,这种方法总是有效的。在这种情

我有4个小图片

有数字6、16、9和9。我将图片和数字与我的模板进行比较,只有30个变体[0-30]。图片-截图是。数字出现在正方形的不同位置(示例中,9在左角,9在右角)

我使用两种方法:计算白色像素的数量

original = cv2.imread('im/16.png')
sought = [254,254,254]
result = np.count_nonzero(np.all(original==sought,axis=2)) 
除6号和9号外,这种方法总是有效的。在这种情况下,白色像素的数量相等

第二种方法:获取图像上所有像素的位置,并将数据与其他图像进行比较:

# tit - title of image
# same list for equal images
difference = cv2.subtract(original,image_to_compare)
b,g,r = cv2.split(difference)
cv2.countNonZero(b) == 0:
    same.append(tit)
if len(same) > 1:
    res = same
    print(res)
这个方法帮助我区分6和9,但是!在两张不同角落有9个的图像中,它也能识别出差异


我希望我的代码能够识别每个数字,并且在图像的右侧或左侧看不到一个数字之间的差异

opencv
中,您可以在
6
9
上训练分类器,例如用于目标检测的基于Haar特征的级联分类器(,)

示例代码位于


我不知道这是否是一项任务,如果你固定使用opencv,如果不是的话,你可以使用神经网络,cf章节Tunnel Vision of或然而空间变压器网络对于这个问题有点过于复杂

你可以找到许多关于OCR的论文和软件,因为它在许多应用中被广泛使用。我想使用numpy和opencv为您的问题提供一个非常简单的解决方案,这将完成这项工作

我们将要做的是:

  • 导入numpy和opencv
  • 加载您提供的图像
  • 特雷斯告诉他们
  • Make函数,该函数将返回给定图像中的数字数组
  • 比较图1和图2的数字
  • 制作我们的“数字库”,让我们知道数字9是什么样子
  • 将图3中的数字与我们的“数字库”进行比较
  • 代码:

    函数,该函数将返回给定图像中的数字数组:

    def get_images_of_digits(image):
        components = cv2.connectedComponentsWithStats(image, 8, cv2.CV_16U) #Separate digits
        #Get position of every components
        #For details how this works take a look at 
        #https://stackoverflow.com/questions/35854197/how-to-use-opencvs-connected-components-with-stats-in-python
        position_of_digits = components[2] 
        number_of_digits = len(position_of_digits) - 1 #number of digits found in image
        digits = [] #Array with every digit in image
        for i in range(number_of_digits):    
            w = position_of_digits[i+1,0] #Left corner of digit
            h = position_of_digits[i+1,1] #Top corner of digit
            digit = image[h:h+height_of_digit,w:w+width_of_digit] #Cut this digit out of image
    
            #Count how many white pixels there are
            px_count = np.count_nonzero(digit)
            #Divide every pixel by square root of count of pixels in digit. 
            #Why? If we make convolution with the same digit it will give us sweet "1", which means these digits are identical
            digit = digit / np.sqrt(px_count)  
        digits.append(digit)
    
    return digits #Return all digits
    
    获取数字

    d_1 = get_images_of_digits(image1)[0] #Digit "9" from first image
    d_2 = get_images_of_digits(image2)[0] #Digit "9" from second image
    d_3 = get_images_of_digits(image4)[0] #Digit "6" from last image
    
    print(cv2.filter2D(d_1,-1,d_2).max()) #Digit "9" on image 1 and 2 match perfectly (result of convolution is 1).
    #Filter2D does convolution (correlation to be precise, but they are the same for our purpose)
    
    将第一张图像中的数字“9”和最后一张图像中的数字“6”放入数字库。然后仔细检查我们在图3中找到的每个数字,并将其与我们的数字库进行比较。如果分数低于0.9,则不匹配

    bank_of_digits = {"9":d_1, "6":d_3} 
    for digit in get_images_of_digits(image3):
        #print(digit)
        best_restult = 0.9 #If score is above 0.9, we say it is match
        #Maybe tweak this higher for separating chars "8" and "9" and "0"
        matching_digit = "?" #Default char, when there is no match
        for number in bank_of_digits:
            score = cv2.filter2D(digit,-1,bank_of_digits[number]).max() #Returns 0-1 . 1 Means perfect match       
            print("Score for number " + number +" is: "+ str(np.round(score,2)) )
            if score > best_restult: #If we find better match
                best_restult = score #Set highest score yet
                matching_digit = number #Set best match number
        print("Best match: " + matching_digit)
    
    最终结果将是图像3中第一个数字的“?”,因为我们银行中没有数字“1”,第二个结果将是得分为0.97的“6”

    TLDR:我制作了一种算法,将数字从图像中分离出来,并比较这些数字。将打印最佳匹配项。

    可能的副本
    bank_of_digits = {"9":d_1, "6":d_3} 
    for digit in get_images_of_digits(image3):
        #print(digit)
        best_restult = 0.9 #If score is above 0.9, we say it is match
        #Maybe tweak this higher for separating chars "8" and "9" and "0"
        matching_digit = "?" #Default char, when there is no match
        for number in bank_of_digits:
            score = cv2.filter2D(digit,-1,bank_of_digits[number]).max() #Returns 0-1 . 1 Means perfect match       
            print("Score for number " + number +" is: "+ str(np.round(score,2)) )
            if score > best_restult: #If we find better match
                best_restult = score #Set highest score yet
                matching_digit = number #Set best match number
        print("Best match: " + matching_digit)