1.测试图片
2.基本思路
原图 -> 灰度处理 -> 二值化处理(数字部分为白色)-> 膨胀处理 -> 寻找轮廓
找出所有数字的轮廓,分别传入识别函数
(穿针法识别:tubo_roi为各段的区域,通过判断abcdefg有哪几个是白色,来组合成不同的数字)
特殊数字:1 ,通过长宽比大于2来判断为数字1
3.代码运行效果
经过多重处理,成功识别出1,2,3,4,5,6,7,8,9
仅本测试图片可用,其他测试场景可能需要优化图片预处理逻辑
4.代码
使用测试图片可直接运行,注意图片名称以及路径
import cv2
import numpy as np
#原图
image = cv2.imread('photo.jpg',cv2.imread_color)
cv2.imshow("image",image)
#灰度图处理
image_gry = cv2.imread('photo.jpg',cv2.imread_grayscale)
if image_gry is none:
print("not read")
exit()
cv2.imshow("image_gry", image_gry)
#二值化
_, image_bin = cv2.threshold(image_gry,80,255,cv2.thresh_binary)
cv2.imshow("image_bin",image_bin)
#进行膨胀处理
element = cv2.getstructuringelement(cv2.morph_rect,(20,20))
image_dil = cv2.dilate(image_bin, element)
cv2.imshow("image_dil",image_dil)
#轮廓寻找
contours_out,hierarchy=cv2.findcontours(image_dil, cv2.retr_external, cv2.chain_approx_none)
#cv2.drawcontours(image_bin,contours,-1,(0,255,0),2)
num_location = [cv2.boundingrect(contour) for contour in contours_out]
num_location.sort(key=lambda x: x[0])
inmage_with_contours = cv2.cvtcolor(image_bin,cv2.color_gray2bgr)
cv2.drawcontours(inmage_with_contours,contours_out,-1,(0,225,0),2)
cv2.imshow("contours",inmage_with_contours)
# 定义判断区域是否全为白色的函数
def is_all_white(image, row_start, row_end, col_start, col_end):
white_num = 0
j=row_start
i=col_start
while(j <= row_end):
while(i <= col_end):
if(image[j][i] == 255):
white_num+=1
i+=1
j+=1
i=col_start
#print('white num is',white_num)
if(white_num >= 5):
return true
else:
return false
# 定义穿线法识别数字的函数
def tube_identification(inputmat):
tube = 0
tubo_roi = [
[inputmat.shape[0] * 0/3, inputmat.shape[0] * 1/3, inputmat.shape[1] * 1/2,inputmat.shape[1] * 1/2], #a
[inputmat.shape[0] * 1/3, inputmat.shape[0] * 1/3, inputmat.shape[1] * 2/3,inputmat.shape[1] - 1 ], #b
[inputmat.shape[0] * 2/3, inputmat.shape[0] * 2/3, inputmat.shape[1] * 2/3,inputmat.shape[1] - 1 ], #c
[inputmat.shape[0] * 2/3, inputmat.shape[0] -1 , inputmat.shape[1] * 1/2,inputmat.shape[1] * 1/2], #d
[inputmat.shape[0] * 2/3, inputmat.shape[0] * 2/3, inputmat.shape[1] * 0/3,inputmat.shape[1] * 1/3], #e
[inputmat.shape[0] * 1/3, inputmat.shape[0] * 1/3, inputmat.shape[1] * 0/3,inputmat.shape[1] * 1/3], #f
[inputmat.shape[0] * 1/3, inputmat.shape[0] * 2/3, inputmat.shape[1] * 1/2,inputmat.shape[1] * 1/2] #g
]
i = 0
while(i < 7):
if(is_all_white(inputmat,int(tubo_roi[i][0]),int(tubo_roi[i][1]), int(tubo_roi[i][2]),int(tubo_roi[i][3]))):
tube = tube + pow(2,i)
cv2.line(inputmat, ( int(tubo_roi[i][3]),int(tubo_roi[i][1])),
(int(tubo_roi[i][2]), int(tubo_roi[i][0])),
(255,0,0), 1)
i += 1
if (inputmat.shape[0] / inputmat.shape[1] > 2): # 1 is special, which is much narrower than others
tube = 6
if(tube==63):
onenumber = 0
elif(tube==6):
onenumber = 1
elif(tube==91):
onenumber = 2
elif(tube==79):
onenumber = 3
elif(tube==102 or tube==110):
#110是因为有干扰情况
onenumber = 4
elif(tube==109):
onenumber = 5
elif(tube==125):
onenumber = 6
elif(tube==7):
onenumber = 7
elif(tube==127):
onenumber = 8
elif(tube==111):
onenumber = 9
else:
print("error tube = ",tube)
onenumber = -1
return onenumber
# 存储通过穿线法识别的数字
detected_numbers = []
# 遍历每个数字区域
for i in range(len(num_location)):
x, y, w, h = num_location[i]
num_region = image_dil[y:y+h, x:x+w] # 提取数字区域
# 调用穿线法识别数字
detected_number = tube_identification(num_region)
detected_numbers.append(detected_number)
# 显示数字区域
#cv2.imshow(str(i), num_region)
# 输出识别到的数字
print("detected numbers:", detected_numbers)
cv2.waitkey(0)
cv2.destroyallwindows()
发表评论