数字识别,使用opencv [英] Digit recognizing, using opencv

查看:43
本文介绍了数字识别,使用opencv的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有 4 张小图片.

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

There are digits 6, 16 , 9 and 9. I compare pics with digits with my templates, there are only 30 variants [0-30]. Pics - screenshots are. Digits appear at different place at squares (9 in left corner and 9 in right corner on examples).

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

I use two ways: calculate quanity of pixels with white colour.

original = cv2.imread('im/16.png')
sought = [254,254,254]
result = np.count_nonzero(np.all(original==sought,axis=2)) 

这种方式总是有效,除了 6 和 9.在这种情况下,白色像素的数量是相等的.

This way work always, except 6 and 9. Quanity of white pixels are equal in this case.

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

Second way: obtain location of all pixels on image and compare data with other image:

# 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 个图像的图像中,它也识别出差异.

This method help me distinguish 6 from 9, but! In two images with 9 in different corners it also recognise a difference.

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

I want my code recognise every digit and not see a difference between one digit in right or left sides of images.

推荐答案

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

You can find many papers and software about OCR, because it is widely used in many applications. I want to present quite simple solution for your problem, using numpy and opencv, that will do the job.

我们将做什么:

  1. 导入 numpy 和 opencv
  2. 加载您提供的图片
  3. 挑战他们
  4. Make 函数,将返回给定图像中的数字数组
  5. 比较图 1 和图 2 中的数字
  6. 制作我们的数字银行",以便我们知道数字 9 的样子
  7. 将我们在图 3 中找到的数字与我们的数字库"进行比较

代码:

import cv2
import numpy as np

treshold = 70

#Treshold every image, so "0" in image means no digit and "1" is digit 
image1 = (cv2.imread("number_1.png",0) > treshold).astype(np.uint8)
image2 = (cv2.imread("number_2.png",0) > treshold).astype(np.uint8)
image3 = (cv2.imread("number_3.png",0) > treshold).astype(np.uint8)
image4 = (cv2.imread("number_4.png",0) > treshold).astype(np.uint8)

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

Function, that will return array of digits in given image:

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,则不匹配.

Put number "9" from first image and number "6" from last image into digit bank. Then go trough every number we find in image 3 and compare it with our digit bank. If score is below 0.9, it is not match.

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",第二个结果将是6",得分为 0.97.

Final result then will be "?" for first digit in image 3, because there is no number "1" in our bank, and second result will be "6" with score of 0.97.

TLDR:我制作了一种算法,可以将数字与您的图像分开,并比较这些数字.打印最佳匹配.

TLDR: I made algorithm that separates digits from your images, and compares these digits. Best matches are printed.

这篇关于数字识别,使用opencv的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆