检车步骤:
(python代码)
一、获取摄像头视频
cap = cv.VideoCapture("d:/Download/cars.mp4")
二、改变图像尺寸
frame=cv.resize(frame,(702,576))
三、按多边形生成局部的检测图片
def img_paste(image, roi_t):
im = np.zeros(image.shape[:3], dtype="uint8")
#把所有的点画出来
cv.polylines(im, roi_t, True, (255, 0, 255)) # 画任意多边形
# 把所有点连接起来,形成封闭区域
cv.fillPoly(im, roi_t, (255, 255, 255))
mask = im
#将连接起来的区域对应的数组和原图对应位置按位相与
masked = cv.bitwise_and(image, mask)
#cv2中的图片是按照bgr顺序生成的,我们需要按照rgb格式生成
b, g, r = cv.split(masked)
masked = cv.merge([r, g, b])
return masked
roi_as.append(np.array([[371,389], [452, 387], [480, 572], [344, 570]],dtype=np.int32))
img=img_paste(frame, roi_as)
cropped = img [377:576,319:499]
四、灰度化
gray=cv.cvtColor(cropped,cv.COLOR_BGR2GRAY)
五、去噪
blur=cv.GaussianBlur(gray,(3,3),5)
六、去背景
mask=bgsubmog.apply(blur)
七、腐蚀
erode=cv.erode(mask,kernel)
八、膨胀
dilate=cv.dilate(erode,kernel,iterations=5)
九、闭操作
close=cv.morphologyEx(dilate,cv.MORPH_CLOSE,kernel)
十、查找轮廓
cnts, h = cv.findContours(close,cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE) #cv.RETR_EXTERNAL只检测外轮廓
十一、画检测线并根据检测线设置检测范围
cv.line(cropped,(leftpoint,line_heigh),(rightpoint,line_heigh),(255,255,0),2)
十二、计算轮廓中心点
def center(x,y,w,h):
x1=int(w/2)
y1=int(h/2)
cx=x+x1
cy=y+y1
return cx,cy
cnts, h = cv.findContours(close,cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE) #cv.RETR_EXTERNAL只检测外轮廓
for(i,c) in enumerate(cnts):
(x,y,w,h) = cv.boundingRect(c)
cpoint=center(x,y,w,h)
cars.append(cpoint)
十三、检测:1、根据轮廓中心点是否包含在检测范围内,因为检测线范围太窄,中心点正好在检测线的机率很小,必须设置一个检测范围,比如:line_height=200为检测线的y坐标,检测范围就是:(y>line_heigh-offset) and (y<line_heigh+offset),其中offset就是偏移量,检测区是一个带状区,检测区不宜过大,也不宜过小,适当即可。
2、大于等于轮廓阈值:isValid=(w>=min_w) and (h>=min_h)
十四、计数:因为每帧都会产生不同的多个轮廓,应设置判断条件避免重复检出车辆。
for(x,y) in cars:
if((y>line_heigh-offset) and (y<line_heigh+offset)):
if(historyFrameNo==0):
carno+=1
historyFrameNo=frameno
outtime=time.time()
out_y=calcActualDistance(371+y)
if(carno>=1):
if(frameno-historyFrameNo>30):
carno+=1
historyFrameNo=frameno
outtime=time.time()
out_y=calcActualDistance(371+y)
cars.clear()