【P81 10-7】OpenCV Python【实战项目】——车辆识别、车流统计(图像/视频加载、图像运算与处理、形态学、轮廓查找、车辆统计及显示)

发布于:2025-08-16 ⋅ 阅读:(15) ⋅ 点赞:(0)

P81 10-7

1.项目总览

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

2. 视频加载

import cv2
import numpy as np

cap=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 np

cap=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 np

cap=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+x1
    cy=y+y1

    return cx,cy

cap=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 +=1
                    cars.remove((x,y))
                    print(carno)


        cv2.imshow('video',fram)
        


    key=cv2.waitKey(1)
    if(key==27):
        break
    
cap.release()
cv2.destroyAllWindows()

在这里插入图片描述

6 实时显示统计信息

putText函数直接写在内循环,屏幕上打印的text会一闪而过

   for (x, y) in cars:
                if((y > line_high - offset) and (y < line_high + offset)):
                    carno +=1
                    cars.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+x1
    cy=y+y1

    return cx,cy

cap=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 +=1
                    cars.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):
        break
    
cap.release()
cv2.destroyAllWindows()

在这里插入图片描述

8 传统方法 存在的缺陷

但是仍然存在一下问题,
1.检测线的高低;
2.检测物体的长宽设置;
3.检测线偏移量;
4.以检测框的中心经过检测线作为检测表标准,容易漏记多计;

以上提到的几个事项的参数,都是人为设定的,不够灵活。这是传统算法的缺点,深度学习可以跟踪,从车辆进入视线和离开视线跟踪为一辆车,不会重复,漏计等


网站公告

今日签到

点亮在社区的每一天
去签到