数字识别,使用opencv
Digit recognizing, using opencv
我有 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 基于特征的级联目标检测分类器 ( https://docs.opencv.org/3.4/d5/d54/group__objdetect.html , https://docs.opencv.org/3.4/dc/d88/tutorial_traincascade.html )
示例代码在 https://coding-robin.de/2013/07/22/train-your-own-opencv-haar-classifier.html
我不知道这是否是一项作业,如果您固定使用 opencv,则可以使用神经网络,请参阅 的 Tunnel Vision 章https://medium.com/@ageitgey/machine-learning-is-fun-part-3-deep-learning-and-convolutional-neural-networks-f40359318721 or https://towardsdatascience.com/convnets-series-spatial-transformer-networks-cff47565ae81 然而 空间变换网络 对于这个问题来说有点过于复杂
你可以找到很多关于OCR的论文和软件,因为它在很多应用中都有广泛的应用。我想为您的问题提供非常简单的解决方案,使用 numpy 和 opencv,这将完成这项工作。
我们将做什么:
- 导入 numpy 和 opencv
- 加载您提供的图片
- 他们的门槛
- 创建函数,将 return 给定图像中的数字数组
- 比较图像 1 和图像 2 的数字
- 制作我们的 "bank of digits" 以便我们知道数字 9 的样子
- 将我们在图 3 中找到的数字与 "bank of digits"
进行比较
代码:
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)
函数,将 return 给定图像中的数字数组:
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
#
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”,第二个结果将是“6”,分数为 0.97。
TLDR:我制作了从图像中分离数字并比较这些数字的算法。打印最佳匹配项。
我有 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 基于特征的级联目标检测分类器 ( https://docs.opencv.org/3.4/d5/d54/group__objdetect.html , https://docs.opencv.org/3.4/dc/d88/tutorial_traincascade.html )
示例代码在 https://coding-robin.de/2013/07/22/train-your-own-opencv-haar-classifier.html
我不知道这是否是一项作业,如果您固定使用 opencv,则可以使用神经网络,请参阅 的 Tunnel Vision 章https://medium.com/@ageitgey/machine-learning-is-fun-part-3-deep-learning-and-convolutional-neural-networks-f40359318721 or https://towardsdatascience.com/convnets-series-spatial-transformer-networks-cff47565ae81 然而 空间变换网络 对于这个问题来说有点过于复杂
你可以找到很多关于OCR的论文和软件,因为它在很多应用中都有广泛的应用。我想为您的问题提供非常简单的解决方案,使用 numpy 和 opencv,这将完成这项工作。
我们将做什么:
- 导入 numpy 和 opencv
- 加载您提供的图片
- 他们的门槛
- 创建函数,将 return 给定图像中的数字数组
- 比较图像 1 和图像 2 的数字
- 制作我们的 "bank of digits" 以便我们知道数字 9 的样子
- 将我们在图 3 中找到的数字与 "bank of digits" 进行比较
代码:
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)
函数,将 return 给定图像中的数字数组:
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
#
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”,第二个结果将是“6”,分数为 0.97。
TLDR:我制作了从图像中分离数字并比较这些数字的算法。打印最佳匹配项。