【OpenCV实战】 视频车辆统计

项目总体分为四大步:

  1. 加载视频
  2. 车辆识别
  3. 车辆统计
  4. 信息显示

1. 加载视频

import cv2
import numpy as np

# 读取视频
cap = cv2.VideoCapture('video/cars.mp4')

while True:
    # 读取帧
    ret, frame = cap.read()
    if (ret == True):
        cv2.imshow('video', frame)
    else:
        break
    
    key = cv2.waitKey(1)
    if (key == 27):
        break

cap.release()

cv2.destroyAllWindows()

2. 车辆识别

形态学处理

import cv2
import numpy as np

# 读取视频
cap = cv2.VideoCapture('video/cars.mp4')

bgsubmog = cv2.bgsegm.createBackgroundSubtractorMOG()

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

while True:
    # 读取帧
    ret, frame = cap.read()
    if (ret == True):
        # 灰度
        cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        # 去噪
        blur = cv2.GaussianBlur(frame, (3, 3), 5)
        # 去背影
        mask =  bgsubmog.apply(blur)

        # 腐蚀 去掉小方块
        erode = cv2.erode(mask, kernel)

        # 膨胀 还原放大
        dilate = cv2.dilate(erode, kernel, iterations=3)

        # 闭操作 去掉物体内部方块
        close = cv2.morphologyEx(dilate, cv2.MORPH_CLOSE, kernel)

        # 
        cnts, h = cv2.findContours(close, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

        for (i, c)  in enumerate(cnts):
            (x, y, w, h) = cv2.boundingRect(c)
            cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 0, 255), 2)


        cv2.imshow('video', mask)
        cv2.imshow('erode', close)
    else:
        print("Error")
        break
    
    key = cv2.waitKey(1)
    if (key == 27):
        break

cap.release()

cv2.destroyAllWindows()     

3. 车辆统计

最小合法车宽高和检测线高度根据实际情况需要调整。

import cv2
import numpy as np

# 最小合法车宽高
min_w = 50
min_h = 60

# 检测线高度
line_high = 600

# 存放有效车辆数组
cars = []

# 线的偏移量
offset = 6

# 统计车的数量
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/cars.mp4')

bgsubmog = cv2.bgsegm.createBackgroundSubtractorMOG()

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

while True:
    # 读取帧
    ret, frame = cap.read()
    if (ret == True):
        # 灰度
        cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        # 去噪
        blur = cv2.GaussianBlur(frame, (3, 3), 5)
        # 去背影
        mask =  bgsubmog.apply(blur)

        # 腐蚀 去掉小方块
        erode = cv2.erode(mask, kernel)

        # 膨胀 还原放大
        dilate = cv2.dilate(erode, kernel, iterations=3)

        # 闭操作 去掉物体内部方块
        close = cv2.morphologyEx(dilate, cv2.MORPH_CLOSE, kernel)

        # 
        cnts, 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 (i, c)  in enumerate(cnts):
            (x, y, w, h) = cv2.boundingRect(c)
            cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 0, 255), 2)

            # 对车辆的宽高进行判断
            # 以验证是否是有效车辆
            isValid = (w >= min_w) and (h >= min_h)

            if (not isValid):
                continue

            # 到这里都是有效车
            cpoint = center(x, y, w, h)
            cars.append(cpoint)

            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', frame)

    else:
        print("Error")
        break
    
    key = cv2.waitKey(1)
    if (key == 27):
        break

cap.release()

cv2.destroyAllWindows()     

4. 显示信息(完整代码)

这部分我根据视频的实际情况,对形态学操作做了一些调整。
但识别效果仍然不是太好,还需要进一步调整。
image

import cv2
import numpy as np

# 最小合法车宽高
min_w = 50
min_h = 60

# 检测线高度
line_high = 600

# 存放有效车辆数组
cars = []

# 线的偏移量
offset = 6   

# 统计车的数量
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/cars.mp4')

bgsubmog = cv2.bgsegm.createBackgroundSubtractorMOG()

# 
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))

while True:
    # 读取帧
    ret, frame = cap.read()
    if (ret == True):

        # 灰度
        cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        
        # 去噪
        blur = cv2.GaussianBlur(frame, (5, 5), 5)
        
        # 去背影
        mask =  bgsubmog.apply(blur)

        # 膨胀 还原放大
        dilate = cv2.dilate(mask , kernel, iterations=5)
        
        # 腐蚀 去掉小方块
        erode = cv2.erode(dilate, kernel, iterations=3)

        # 闭操作 去掉物体内部方块
        close = cv2.morphologyEx(erode, cv2.MORPH_CLOSE, kernel, iterations=6)

        # 
        cnts, 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 (i, c)  in enumerate(cnts):
            (x, y, w, h) = cv2.boundingRect(c)

            # 对车辆的宽高进行判断
            # 以验证是否是有效车辆
            isValid = (w >= min_w) and (h >= min_h)

            if (not isValid):
                continue

            # 到这里都是有效车
            cpoint = center(x, y, w, h)
            cars.append(cpoint)

            cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 0, 255), 2)

            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(frame, "Cars Count:" + str(carno), (500, 60), cv2.FONT_HERSHEY_SCRIPT_SIMPLEX, 2, (255, 0, 0), 5)
        cv2.imshow('video', frame)

        cv2.imshow('1', close)

    else:
        print("Error")
        break
    
    key = cv2.waitKey(1)
    if (key == 27):
        break

cap.release()

cv2.destroyAllWindows()     
posted @ 2025-10-09 14:55  苦涩如影相随固  阅读(19)  评论(0)    收藏  举报