OpenCV:09车辆统计项目

车辆统计项目

效果图:

OpenCV:09车辆统计项目

; 涉及到的内容

  • 窗口的展示
  • 图像/视频的加载
  • 基本图像的绘制
    • 车辆识别
  • 基本图像运算与处理
  • 形态学
  • *轮廓查找

大体流程

1. 加载视频
2. 通过形态学识别车辆
3. 对车辆进行统计
4. 显示车辆统计信息

知识补充

背景减除

背景减除( Background Subtraction 是许多基于计算机视觉的任务中主要的 预处理步骤。如果我们有完整的静止的背景帧,那么我们可以通过帧差法来计算像素差从而获取到前景对象。

但是在大多数情况下,我们可能没有这样的图像,所以我们 需要从我们拥有的任何图像中提取背景。当运动物体有阴影时,由于阴影也在移动,情况会变得更加复杂,为此引入 背景减除算法

通过这一方法我们能够从视频中分离出运动的物体前景,从而达到目标检测的目的

  • BackgroundSubtractorMOG
  • 这是一个以混合高斯模型为基础的前景/背景分割算法
  • 它使用K(K = 3 或 5)个高斯分布混合对背景图像进行建模。使用这些颜色(在整个视频中)存在时间的长短作为混合的权重,背景的颜色一般持续时间最长,而且更加静止
  • 在编写代码时,我们需要使用函数 cv2.createBackgroundSubtractorMOG2()创建一个背景对象。这个函数有些可选参数,比如要进行建模场景的时间长度,高斯混合成分的数量,阈值等。 将它们全部设置为默认值,然后在整个视频中我们是需要使用 backgroundsubtractor.apply()就可以得到 前景的掩膜
  • *移动的物体会被标记为白色,背景会被标记为黑色的

具体流程

视频加载

关键API:打开摄像头 cap = cv2.VideoCapture('./video.mp4');读取数据 ret,frame = cap.read()


import cv2
import numpy as np

cap = cv2.VideoCapture('./video.mp4')

while True :
    ret,frame = cap.read()

    if ret == True:
        cv2.imshow('video',frame)

    key = cv2.waitKey(1)

    if key == 27:
        break

cap.release()
cv2.destroyAllWindows()

去除背景

OpenCV会把不会动的东西(蓝天白云…)分辨出 背景;把会动的东西(车辆、行人…)叫做 前景

由于我们要 检测会动的车辆(前景),所以要 把不会动的背景去除掉,用到了 背景减除( Background Subtraction ——>效果是: 动的东西(前景)会变成白色 ;不动的东西(背景)会变成黑色

关键API: cv2.createBackgroundSubtractorMOG2() # 直接用 不用写参数


import cv2
import numpy as np

cap = cv2.VideoCapture('./video.mp4')

mog = cv2.createBackgroundSubtractorMOG2()

while True:
    ret,frame = cap.read()

    if ret == True :
        fgmask = mog.apply(frame)
        cv2.imshow('video',fgmask)

    key = cv2.waitKey(100)

    if key == 27:
        break

cap.release()
cv2.destroyAllWindows()

结果:

OpenCV:09车辆统计项目

形态学识别车辆

从去背景例程中,我们可以发现有很多白点(噪声),因此我们需要 降噪

我们可以发现噪声比较均匀,不适合用中值滤波去除,而是用 高斯滤波

关键API: cv2.GaussianBlur(gray,(7,7),5)

降噪:


import cv2
import numpy as np

cap = cv2.VideoCapture('./car.mp4')

mog = cv2.createBackgroundSubtractorMOG2()

kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))

min_w = 90
min_h = 90

while True:
    ret,frame = cap.read()

    if ret == True :

        gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)

        blur = cv2.GaussianBlur(gray,(7,7),5)

        fgmask = mog.apply(blur)

        erode = cv2.erode(fgmask,kernel)

        dilate = cv2.dilate(erode,kernel,iterations = 2)

        close = cv2.morphologyEx(dilate,cv2.MORPH_CLOSE,kernel)

        cv2.imshow('video',close)

    key = cv2.waitKey(1)

    if key == 27:
        break

cap.release()
cv2.destroyAllWindows()

结果:

OpenCV:09车辆统计项目

识别车辆轮廓:

关键API: cv2.findContours(close,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

我们设置一个阈值,如果某一像素面积大于这个阈值,那么就说明这是🚗

降噪后的黑白图中得到轮廓的对应 (x,y,w,h)坐标,再用 cv2.rectangle(frame,(int(x),int(y)),(int(x+w),int(y+h)),(0,255,255),2)原图中画出


import cv2
import numpy as np

cap = cv2.VideoCapture('./car.mp4')

mog = cv2.createBackgroundSubtractorMOG2()

kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))

min_w = 90
min_h = 90

while True:
    ret,frame = cap.read()

    if ret == True :

        gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)

        blur = cv2.GaussianBlur(gray,(7,7),5)

        fgmask = mog.apply(blur)

        erode = cv2.erode(fgmask,kernel)

        dilate = cv2.dilate(erode,kernel,iterations = 2)

        close = cv2.morphologyEx(dilate,cv2.MORPH_CLOSE,kernel)

        contours,h  = cv2.findContours(close,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

        for contour in contours:

            (x,y,w,h) = cv2.boundingRect(contour)

            if (w < min_w) and (h < min_h) :
                continue
            cv2.rectangle(frame,(int(x),int(y)),(int(x+w),int(y+h)),(0,255,255),2)

        cv2.imshow('frame',frame)

    key = cv2.waitKey(1)

    if key == 27:
        break

cap.release()
cv2.destroyAllWindows()

对车辆进行统计

我们不可能对整幅图进行统计,那样太乱了,也有很多噪声—— 我们应该画一条线,对经过这条线的车辆进行统计

这就有两个难点了:

1.如何画线,在哪画线

  • 关键API: 画线 cv2.line(frame,(10,line_high),(1200,line_high),(255,255,0),3) # &#x53C2;&#x6570;&#xFF1A;&#x753B;&#x5728;&#x90A3;&#x3001;&#x8D77;&#x59CB;&#x70B9;&#x3001;&#x7ED3;&#x675F;&#x70B9;&#x3001;&#x989C;&#x8272;

2.如何统计

  • 把车抽象为一个点 ——> 即外接矩形的中心点,记录下当前的点,并且用中心点的y坐标和检测线加上偏移量进行对比,如果坐标在区间内,则检测到车辆,否则不算
  • 设置一个空列表 cars[ ],以追加cars.append()的方式把每一个点都追加到列表中,后用for循环遍历这些点,对于满足的点剔除掉 cars.remove((x,y)),避免重复

import cv2
import numpy as np

cap = cv2.VideoCapture('./car.mp4')

mog = cv2.createBackgroundSubtractorMOG2()

kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))

min_w = 90
min_h = 90

line_high = 450

offset = 6

cars = []

car_num = 0

def center(x,y,w,h):
    x1 = int(w / 2)
    y1 = int(h / 2)
    cx = int(x) + x1
    cy = int(y) + y1
    return cx,cy

while True:
    ret,frame = cap.read()

    if ret == True :

        gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)

        blur = cv2.GaussianBlur(gray,(7,7),5)

        fgmask = mog.apply(blur)

        erode = cv2.erode(fgmask,kernel)

        dilate = cv2.dilate(erode,kernel,iterations = 2)

        close = cv2.morphologyEx(dilate,cv2.MORPH_CLOSE,kernel)

        contours,h  = cv2.findContours(close,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

        cv2.line(frame,(10,line_high),(1200,line_high),(255,255,0),3)

        for contour in contours:

            (x,y,w,h) = cv2.boundingRect(contour)

            if (w < min_w) and (h < min_h) :
                continue
            cv2.rectangle(frame,(int(x),int(y)),(int(x+w),int(y+h)),(0,255,255),2)

            my_center = center(x,y,w,h)
            cv2.circle(frame,(my_center),5,(0,255,255),-1)

            cars.append(my_center)

            for (x , y) in cars:
                if (y > line_high - offset) and (y < line_high + offset):

                    car_num += 1

                    cars.remove((x,y))

        cv2.imshow('frame',frame)

    key = cv2.waitKey(100)

    if key == 27:
        break

cap.release()
cv2.destroyAllWindows()

结果:

OpenCV:09车辆统计项目

显示车辆统计信息

关键API: cv2.putText(frame,'Vehicle Count:' + str(car_num) ,(200,60),cv2.FONT_HERSHEY_SIMPLEX,2,(0,0,255),3)

总体代码:


import cv2
import numpy as np

cap = cv2.VideoCapture('./car.mp4')

mog = cv2.createBackgroundSubtractorMOG2()

kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))

min_w = 85
min_h = 80

line_high = 465

offset = 6

cars = []

car_num = 0

def center(x,y,w,h):
    x1 = int(w / 2)
    y1 = int(h / 2)
    cx = int(x) + x1
    cy = int(y) + y1
    return cx,cy

while True:
    ret,frame = cap.read()

    if ret == True :

        gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)

        blur = cv2.GaussianBlur(gray,(7,7),5)

        fgmask = mog.apply(blur)

        erode = cv2.erode(fgmask,kernel,iterations = 2)

        dilate = cv2.dilate(erode,kernel,iterations = 3)

        close = cv2.morphologyEx(dilate,cv2.MORPH_CLOSE,kernel)

        contours,h  = cv2.findContours(close,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

        cv2.line(frame,(10,line_high),(1200,line_high),(255,255,0),3)

        for contour in contours:

            (x,y,w,h) = cv2.boundingRect(contour)

            if (w < min_w) and (h < min_h) :
                continue
            cv2.rectangle(frame,(int(x),int(y)),(int(x+w),int(y+h)),(0,255,255),2)

            my_center = center(x,y,w,h)
            cv2.circle(frame,(my_center),5,(0,255,255),-1)

            cars.append(my_center)

            for (x , y) in cars:
                if (y >= line_high - offset) and (y  line_high + offset):

                    car_num += 1

                    cars.remove((x,y))

        cv2.putText(frame,'Vehicle Count:' + str(car_num) ,(200,60),cv2.FONT_HERSHEY_SIMPLEX,2,(0,0,255),3)

        cv2.imshow('frame',frame)

    key = cv2.waitKey(10)

    if key == 27:
        break

cap.release()
cv2.destroyAllWindows()

结果:

OpenCV:09车辆统计项目

Original: https://blog.csdn.net/m0_59466249/article/details/125934965
Author: Lionetxx
Title: OpenCV:09车辆统计项目

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/702287/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球