【P81 10-7】OpenCV Python【实战项目】——车辆识别、车流统计(图像/视频加载、图像运算与处理、形态学、轮廓查找、车辆统计及显示)
P81 10-7
- 1.项目总览
- 2. 视频加载
- 3. 去背景
- 4.形态学处理,轮廓统计
- 5.逻辑处理
- 6 实时显示统计信息
- 6.2 SyntaxError: positional argument follows keyword argument
- 7 完整代码
- 8 传统方法 存在的缺陷
1.项目总览
2. 视频加载
import cv2
import numpy as npcap=cv2.VideoCapture('video.mp4')while True:ret,fram=cap.read()cv2.imshow('video',fram)key=cv2.waitKey(100)if(key==27):break
cap.release()
cv2.destroyAllWindows()
3. 去背景
opencv–背景减除–BackgroundSubtractorMOG2
createBackgroundSubtractorMOG();
该函数可以使用默认参数,修改最多的是history,值越大计算越准,越耗时;
.apply()
就可以得到前景的掩模了
移动的物体会被标记为白色,背景会被标记为黑色的
前景的掩模就是白色的了
import cv2
import numpy as npcap=cv2.VideoCapture('video.mp4')#获取背景,此功能需要安装opencv扩展库
bgsubmog = cv2.bgsegm.createBackgroundSubtractorMOG()while True:ret,fram=cap.read()if(ret==True):#灰度cv2.cvtColor(fram,cv2.COLOR_BGRA2GRAY)#去噪(高斯)blur=cv2.GaussianBlur(fram,(3,3),5)#去背景,.apply() 得到前景的掩模了,移动的物体会被标记为白色,背景会被标记为黑色的mask=bgsubmog.apply(blur)cv2.imshow('mask',mask)key=cv2.waitKey(100)if(key==27):break
cap.release()
cv2.destroyAllWindows()
高斯滤波去噪
4.形态学处理,轮廓统计
- 腐蚀, 去掉图中小斑块
- 膨胀, 还原放大
- 闭操作, 去掉物体内部小块
import cv2
from cv2 import COLOR_BGRA2GRAY
from cv2 import erode
from cv2 import dilate
from cv2 import CHAIN_APPROX_SIMPLE
import numpy as npcap=cv2.VideoCapture('video.mp4')
#获取背景,此功能需要安装opencv扩展库
bgsubmog = cv2.bgsegm.createBackgroundSubtractorMOG()#形态学kernel
kernel=cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))while True:ret,fram=cap.read()if(ret==True):#灰度cv2.cvtColor(fram,cv2.COLOR_BGRA2GRAY)#去噪(高斯)blur=cv2.GaussianBlur(fram,(3,3),5)#去背景,.apply() 得到前景的掩模了,移动的物体会被标记为白色,背景会被标记为黑色的mask=bgsubmog.apply(blur)#腐蚀,去掉图中小斑块erode=cv2.erode(mask,kernel)#膨胀,还原放大dilate=cv2.dilate(erode,kernel,iterations=3)#闭操作,去掉物体内部小块close=cv2.morphologyEx(dilate,cv2.MORPH_CLOSE,kernel)close=cv2.morphologyEx(dilate,cv2.MORPH_CLOSE,kernel)cv2.imshow('mask',mask)cv2.imshow('erode',erode)cv2.imshow('dilate',dilate)cv2.imshow('close',close)key=cv2.waitKey(100)if(key==27):break
cap.release()
cv2.destroyAllWindows()
#轮廓查找contours,hierarchy=cv2.findContours(close,cv2.RETR_TREE,CHAIN_APPROX_SIMPLE)for (i,c) in enumerate(contours):(x,y,w,h)=cv2.boundingRect(c)print(x,x,w,h)cv2.rectangle(fram,(x,y),(x+w,y+h),(0,0,255),2)
5.逻辑处理
import cv2
import numpy as np#车辆的最小宽高
min_w=90
min_h=90#定义线高
line_high=550
#线的偏移量
offset=7#存放车辆数组
cars=[]
#统计车的数量
carno=0#计算车辆中心
def center(x,y,w,h):x1=int(w/2)y1=int(h/2)cx=x+x1cy=y+y1return cx,cycap=cv2.VideoCapture('video.mp4')
#获取背景,此功能需要安装opencv扩展库
bgsubmog = cv2.bgsegm.createBackgroundSubtractorMOG()#形态学kernel
kernel=cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))while True:ret,fram=cap.read()if(ret==True):#灰度cv2.cvtColor(fram,cv2.COLOR_BGRA2GRAY)#去噪(高斯)blur=cv2.GaussianBlur(fram,(3,3),5)#去背景,.apply() 得到前景的掩模了,移动的物体会被标记为白色,背景会被标记为黑色的mask=bgsubmog.apply(blur)#腐蚀,去掉图中小斑块erode=cv2.erode(mask,kernel)#膨胀,还原放大dilate=cv2.dilate(erode,kernel,iterations=3)#闭操作,去掉物体内部小块close=cv2.morphologyEx(dilate,cv2.MORPH_CLOSE,kernel)close=cv2.morphologyEx(dilate,cv2.MORPH_CLOSE,kernel)#轮廓查找cnts,h=cv2.findContours(close,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)#划一条检测线cv2.line(fram,(10,line_high),(1200,line_high),(255,225,0),3)for (i,c) in enumerate(cnts):(x,y,w,h)=cv2.boundingRect(c)#对车辆宽高进行判断,验证是否有效的车辆isValid=(w>=min_w) and (h>=min_h)if(not isValid):continue#到这里的是有效的车cv2.rectangle(fram,(x,y),(x+w,y+h),(0,0,255),2)#计数方式,计算汽车轮廓中心点,当这个中心点经过指定的那条界限,数量加一cpoint =center(x,y,w,h)#print(cpoint)cars.append(cpoint)#要有一条线#偏移范围6,点在线的附近+-6处经过都有效#从数组中减去for (x, y) in cars:if((y > line_high - offset) and (y < line_high + offset)):carno +=1cars.remove((x,y))print(carno)cv2.imshow('video',fram)key=cv2.waitKey(1)if(key==27):breakcap.release()
cv2.destroyAllWindows()
6 实时显示统计信息
putText函数直接写在内循环,屏幕上打印的text会一闪而过
for (x, y) in cars:if((y > line_high - offset) and (y < line_high + offset)):carno +=1cars.remove((x,y))print(carno)cv2.putText(fram,"Cars Contur:"+str(carno),(500,60),fontFace=FONT_HERSHEY_COMPLEX_SMALL,fontScale=2,color=(0,255,0),thickness=5)
6.2 SyntaxError: positional argument follows keyword argument
SyntaxError: positional argument follows keyword argument
出现这个bug的原因在于参数位置不正确,关键字参数必须跟随在位置参数后面! 因为python函数在解析参数时, 是按照顺序来的, 位置参数是必须先满足, 才能考虑其他可变参数.
解决方法1: 出错的位置起,每个变量前面都加上形参的名字
cv2.putText(fram,"Cars Contur:"+str(carno),(500,60),fontFace=FONT_HERSHEY_COMPLEX_SMALL,fontScale=2,color=(0,255,0),thickness=5)
解决方法2: 删掉所有形参的名字
cv2.putText(fram,"Cars Contur:"+str(carno),(500,60),FONT_HERSHEY_COMPLEX_SMALL,2,(0,255,0),5)
7 完整代码
import cv2
from cv2 import FONT_HERSHEY_COMPLEX_SMALL
import numpy as np#车辆的最小宽高
min_w=100
min_h=90#定义线高
line_high=550
#线的偏移量
offset=7#存放车辆数组
cars=[]
#统计车的数量
carno=0#计算车辆中心
def center(x,y,w,h):x1=int(w/2)y1=int(h/2)cx=x+x1cy=y+y1return cx,cycap=cv2.VideoCapture('video.mp4')
#获取背景,此功能需要安装opencv扩展库
bgsubmog = cv2.bgsegm.createBackgroundSubtractorMOG()#形态学kernel
kernel=cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))while True:ret,fram=cap.read()if(ret==True):#灰度cv2.cvtColor(fram,cv2.COLOR_BGRA2GRAY)#去噪(高斯)blur=cv2.GaussianBlur(fram,(3,3),5)#去背景,.apply() 得到前景的掩模了,移动的物体会被标记为白色,背景会被标记为黑色的mask=bgsubmog.apply(blur)#腐蚀,去掉图中小斑块erode=cv2.erode(mask,kernel)#膨胀,还原放大dilate=cv2.dilate(erode,kernel,iterations=3)#闭操作,去掉物体内部小块close=cv2.morphologyEx(dilate,cv2.MORPH_CLOSE,kernel)close=cv2.morphologyEx(dilate,cv2.MORPH_CLOSE,kernel)#轮廓查找cnts,h=cv2.findContours(close,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)#划一条检测线cv2.line(fram,(10,line_high),(1200,line_high),(255,225,0),3)for (i,c) in enumerate(cnts):(x,y,w,h)=cv2.boundingRect(c)#对车辆宽高进行判断,验证是否有效的车辆isValid=(w>=min_w) and (h>=min_h)if(not isValid):continue#到这里的是有效的车cv2.rectangle(fram,(x,y),(x+w,y+h),(0,0,255),2)#计数方式,计算汽车轮廓中心点,当这个中心点经过指定的那条界限,数量加一cpoint =center(x,y,w,h)cv2.circle(fram,cpoint,5,(0,0,255),-1)#print(cpoint)cars.append(cpoint)#要有一条线#偏移范围6,点在线的附近+-6处经过都有效#从数组中减去for (x, y) in cars:if((y > line_high - offset) and (y < line_high + offset)):carno +=1cars.remove((x,y))print(carno)# cv2.putText(fram,"Cars Contur:"+str(carno),(500,60),fontFace=FONT_HERSHEY_COMPLEX_SMALL,fontScale=2,color=(0,255,0),thickness=5)cv2.putText(fram,"Cars Contur: "+str(carno),(500,60),FONT_HERSHEY_COMPLEX_SMALL,2,(255,0,0),3)cv2.imshow('video',fram)key=cv2.waitKey(50)if(key==27):breakcap.release()
cv2.destroyAllWindows()
8 传统方法 存在的缺陷
但是仍然存在一下问题,
1.检测线的高低;
2.检测物体的长宽设置;
3.检测线偏移量;
4.以检测框的中心经过检测线作为检测表标准,容易漏记多计;
以上提到的几个事项的参数,都是人为设定的,不够灵活。这是传统算法的缺点,深度学习可以跟踪,从车辆进入视线和离开视线跟踪为一辆车,不会重复,漏计等