基于模板匹配的交通标志定位与识别
最近在用python和opencv做交通标志的定位和检测,本案例只能检测出限速标志的交通标志,第一次写博客,写的不好请见谅.
博主也是刚刚接触机器视觉的学习,后期会继续发布一些这方面的内容,希望我们可以互相学习,共同进步,
先说一下代码的运行效果吧
这里是一张图片的原图和运行以后的结果
1.导入需要模块,先创建一个变量a后面会用到
import cv2 as cv
import numpy as np
import os
a=0
2,加载图片
src=cv.imread('tim.jpg')
3,提取红色和蓝色部分,这张图片只有红色的部分,但是有的图片上的交通标志是蓝色的,所以这里就提取了红蓝两种颜色**
hsv = cv.cvtColor(src,cv.COLOR_BGR2HSV)
low_hsv=np.array([0,43,46])
high_hsv=np.array([10,255,255])
low_hsv2=np.array([100,43,46])
high_hsv2=np.array([124,255,255])
mask=cv.inRange(hsv,lowerb=low_hsv,upperb=high_hsv)
mask2=cv.inRange(hsv,lowerb=low_hsv2,upperb=high_hsv2)
print(type(mask))
red_blue=cv.bitwise_or(mask,mask2)
cv.imshow('red_blue',red_blue)
4,对图像进行一些形态学操作把一些白色的小点去掉,把轮廓边缘变得更加清晰
#高斯模糊
mohu=cv.GaussianBlur(red_blue,(5,5),0)
#二值处理
thresh=cv.threshold(mohu,0,255,cv.THRESH_BINARY | cv.THRESH_OTSU)[1]
#闭运算
ker=np.ones((5,5),np.uint8)
close=cv.morphologyEx(thresh,cv.MORPH_CLOSE,ker)
cv.imshow('close',close)
5,找到上面图像的所有外轮廓,可以看到上面图像上有很多的轮廓,我们需要分别获得他们的外接矩形,然后根据矩形的面积和矩形的长宽比例来选择合适的轮廓,然后在原图上把这些轮廓的外接矩形截取下来,对他们进行一些形态学操作,提取到矩形中间的数字和我们的模板进行匹配,模板文件夹我放在最后了,下面是代码
contours,hierarchy=cv.findContours(close,cv.RETR_EXTERNAL,cv.CHAIN_APPROX_NONE)
print('总轮廓=',len(contours))
for i in contours:
# print(cv.contourArea(i),cv.arcLength(i,True))#计算轮廓面积和周长
#获取轮廓外接矩形左上角坐标(x,y)和矩形的宽高
#然后提取宽高比例在0.8到1.3和面积大于200的轮廓
#x,y,w,h=cv.boundingRect(i)
if 0.8 <=w/h<=1.3:
if w*h<200:
pass
else:
#裁剪矩形并保存图片
a+=1
img=src[y:y+h,x:x+w]
#放大到指定尺寸
img=cv.resize(img,(500,460))
cv.rectangle(src,(x-5,y-5),(x+w+5,y+h+5),(0,255,0),2)
# 对截取矩形图片处理
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(gray, 70, 255, cv.THRESH_BINARY_INV)
# 开闭运算
ker = np.ones((6, 6), np.uint8)
close = cv.morphologyEx(thresh, cv.MORPH_CLOSE, ker)
# 掩码
h, w = gray.shape[0], gray.shape[1]
point1 = [0.15 * w, h / 4]
point2 = [0.15 * w, 4 * h / 5]
point3 = [0.83 * w, 4 * h / 5]
point4 = [0.83 * w, h / 4]
list1 = np.array([[point1, point2, point3, point4]], dtype=np.int32)
mask = np.zeros_like(gray)
mask = cv.fillConvexPoly(mask, list1, 255)
mask1 = cv.bitwise_and(mask, thresh)
# 开运算
ker = np.ones((6, 6), np.uint8)
mask1 = cv.morphologyEx(mask1, cv.MORPH_OPEN, ker)
# 闭运算
ker = np.ones((5, 5), np.uint8)
mask1 = cv.morphologyEx(mask1, cv.MORPH_CLOSE, ker)
# 找外轮廓,
contours1, hierarchy1 = cv.findContours(mask1, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_NONE)
a = len(contours1)
#cv.drawContours(src, contours1, -1, (0, 255, 0), 3)
if 0<a<=3:
print('单个矩形内的轮廓', a)
list3=[]
for i,element in enumerate(contours1):
x2, y2, w2, h2 = cv.boundingRect(element)
# print('x2,y2,w2,h2=', x2, y2, w2, h2)
# dist1[str(i)]=x2
list3.append(x2)
# print('list3=',min(list3))
# print(type(element))
# 轮廓外接矩形
# boundingboxes = [cv.boundingRect(c) for c in close] # 返回外接矩形的四个值x,y,h,w
list2 = []#存放轮廓列表
for lk in contours1:
x1, y1, w1, h1 = cv.boundingRect(lk)
roi = mask1[y1:y1 + h1, x1:x1 + w1]
roi = cv.resize(roi, (60, 90))
#把roi变成三通道图像
roi=cv.cvtColor(roi,cv.COLOR_GRAY2BGR)
list2.append(roi)
#cv.imshow('a4',list2[0])
#遍历模板,进行模板匹配
filename = os.listdir(r'D:\图片处理\muban')
scores = []
for i in range(9):
src1 = cv.imread('muban/' + filename[i])
# gray=cv.cvtColor(src,cv.COLOR_BGR2GRAY)
# ret,thresh=cv.threshold(gray,70,255,cv.THRESH_BINARY)
result = cv.matchTemplate(src1, roi, cv.TM_CCOEFF)
(_, score, _, _) = cv.minMaxLoc(result)
scores.append(score)
print('得分列表:',scores)
x3 = np.argmax(scores) # x是列表最大值所对应的下标
y3=scores[x3]
print('最可能取值:', x3,'分数=',scores[x3])
if y3>158063248:
print('x1=',x1,list3)
if x1==min(list3):
cv.putText(src,'limt:'+str(x3),(x,y+20),cv.FONT_HERSHEY_DUPLEX,1,(255,0,0),2)
elif x1==max(list3):
cv.putText(src, 'limt:'+' '+str(x3), (x,y+20), cv.FONT_HERSHEY_DUPLEX, 1, (255,0,0), 2)
else:
cv.putText(src, 'limt:' +' '+ str(x3), (x, y + 20), cv.FONT_HERSHEY_DUPLEX, 1,
(255,0,0), 2)
else:pass
else:pass
else:pass
# cv.imshow('img',img)
# cv.imshow('mask1',mask1)
cv.imshow('src',src)
cv.waitKey(0)
cv.destroyAllWindows()
这是最终的运行结果
模板文件夹好像没法上传上来,你们可以自己做一个模板
模板大概就是下面图片的样子
模板匹配识别交通标志有太多限制,必须保证交通标志非常清晰的情况下才可以识别。
使用卷积神经网络就没有这么多限制了,准确率还很高,有兴趣可以查看我的另一篇基于卷积神经网络的交通标志识别:博客地址