import cv2
import numpy as np
mode_dict={}
mode=cv2.imread('mode.png',1)
#读入模板图
mode1 = cv2.cvtColor(mode, cv2.COLOR_BGR2GRAY)
#将模板图转成灰度图
mode2=cv2.threshold(mode1,10,255,cv2.THRESH_BINARY_INV)[1]
#将模板灰度图转成二值图
mode_c,mode_h=cv2.findContours(mode2.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
#检测模板轮廓
cv2.drawContours(mode,mode_c,-1,(0,100,100),3,cv2.LINE_AA)
#画出模板轮廓
boundingBoxes = [cv2.boundingRect(c) for c in mode_c]
(mode_c, boundingBoxes) = zip(*sorted(zip(mode_c, boundingBoxes),key=lambda b: b[1][0]))
for (i, c) in enumerate(mode_c):
# 计算外接矩形并且修改成成合适大小
(x, y, w, h) = cv2.boundingRect(c)
roi = mode2[y:y + h, x:x + w]
roi = cv2.resize(roi, (57, 88))
# 每一个数字对应每一个模板
mode_dict[i] = roi
# 读入卡图
card = cv2.imread('card.png', 1)
#将卡图转成二值图
card1=cv2.cvtColor(card,cv2.COLOR_BGR2GRAY)
# 初始化卷积核
RK = cv2.getStructuringElement(cv2.MORPH_RECT, (27, 17))
SK = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
#礼帽操作,突出明亮区域
card2=cv2.morphologyEx(card1,cv2.MORPH_TOPHAT,SK)
#阈值处理
card3=cv2.threshold(card2,20,255,cv2.THRESH_BINARY)[1]
#闭操作处理
card4=cv2.morphologyEx(card3,cv2.MORPH_CLOSE,RK)
#找出轮廓
card_c,card_h=cv2.findContours(card4,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
#绘制轮廓
card5=cv2.drawContours(card.copy(),card_c,-1,(0,0,255),2)
#保存有用轮廓
loc=[]
output=[]
for (i,c) in enumerate(card_c):
(x,y,w,h)=cv2.boundingRect(c)
ar = w / float(h)
# 选择合适的区域,根据实际任务来,这里的基本都是四个数字一组
if ar > 3.3 and ar < 3.5:
# 符合的留下来
loc.append((x, y, w, h))
for (i, (X, Y, W, H)) in enumerate(loc):
out=[]
cv2.rectangle(card, (X - 5, Y - 5), (X + W + 5, Y + H + 5), (0, 100, 255), 2)
#提取每段数字
group = card1[Y - 5:Y + H + 5, X - 5:X + W + 5]
group = cv2.threshold(group, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
#group = cv2.threshold(group, 100, 255, cv2.THRESH_BINARY)[1]
group_c,group_h=cv2.findContours(group,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
for c in group_c:
# 找到当前数值的轮廓,resize成合适的的大小
(x, y, w, h) = cv2.boundingRect(c)
roi = group[y:y + h, x:x + w]
roi = cv2.resize(roi, (57, 88))
# 计算匹配得分
scores = []
# 在模板中计算每一个得分
for (A, B) in mode_dict.items():
# 模板匹配
result = cv2.matchTemplate(roi, B,cv2.TM_CCOEFF)
(_, score, _, _) = cv2.minMaxLoc(result)
scores.append(score)
# 得到最合适的数字
out.append(str(np.argmax(scores)))
# 画出来
out.reverse()
cv2.rectangle(card, (X - 5, Y - 5),(X + W + 5, Y + H + 5), (0, 0, 255), 1)
cv2.putText(card, "".join(out), (X, Y - 15),cv2.FONT_HERSHEY_SIMPLEX, 0.65, (0, 0, 255), 2)
# 得到结果
output.extend(out)
cv2.imshow('card',card)
cv2.waitKey(0)
cv2.destroyAllWindows()
card.png:
mode.png:
结果: