python-opencv 视频车辆检测方法(单车道)
import numpy as np
import cv2 as cv
from PIL import Image
//门口摄像头
//背景去除的三种方法:
//1)BackgroundSubtractorMOG ---去除效果最好
//2)BackgroundSubtractorMOG2
//3)BackgroundSubtractorGMG
//本地录像文件视频
cap = cv.VideoCapture("d:/Download/cars.mp4")
//摄像头RTSP流
cap = cv.VideoCapture("rtsp://admin:admin%40sbdz@192.168.1.40:554/h264/sub/av_stream",cv.CAP_ANY)
min_w=30
min_h=30
carno=0
// 门口
leftpoint=144
rightpoint=208
// 存放有效车辆数组
cars = []
// 检测线的高度
// 门口
line_heigh = 180
// 线的偏移量
offset = 6
def center(x,y,w,h):
x1=int(w/2)
y1=int(h/2)
cx=x+x1
cy=y+y1
return cx,cy
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
bgsubmog = cv.bgsegm.createBackgroundSubtractorMOG()
#形态学kernel
kernel=cv.getStructuringElement(cv.MORPH_RECT,(5,5))
frameno=0
historyFrameNo=0
while(1):
ret, frame = cap.read()
if(ret==True):
frameno+=1
frame=cv.resize(frame,(702,576))
roi_as = []
#门口:根据矩形框抠出视频
roi_as.append(np.array([[215,144], [256, 144], [100, 271], [12, 267]],dtype=np.int32)) #702X576
img=img_paste(frame, roi_as)
cropped = img [120:280,0:262]
sp = cropped.shape
leftpoint=0
rightpoint=sp[1]
line_heigh=int(sp[0]/2)
#灰度
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=9)
#闭操作:两次闭操作
close=cv.morphologyEx(dilate,cv.MORPH_CLOSE,kernel)
close=cv.morphologyEx(close,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)
for(i,c) in enumerate(cnts):
(x,y,w,h) = cv.boundingRect(c)
#对车辆的宽高进行判断
#以验证是否是有效的车辆
isValid=(w>=min_w) and (h>=min_h)
if(not isValid):
continue
#到这里都是有效的车
cv.rectangle(cropped,(x,y),(x+w,y+h),(0,0,255),2)
cpoint=center(x,y,w,h)
cars.append(cpoint)
for(x,y) in cars:
if((y>line_heigh-offset) and (y<line_heigh+offset)):
if(historyFrameNo==0):
carno+=1
historyFrameNo=frameno
if(carno>=1):
if(frameno-historyFrameNo>30):
carno+=1
historyFrameNo=frameno
cars.clear()
cv.putText(frame,"Car Count:" + str(carno),(300,60),cv.FONT_HERSHEY_SIMPLEX,1,(255,0,0),3)
cv.imshow('frame',frame)
cv.imshow("cropped",cropped)
k = cv.waitKey(1)
if k == 27:
break
cap.release()
cv.destroyAllWindows(
)