Bootstrap

使用OpenCV来实现车辆统计

1.最终效果展示:

可以统计视频中的车辆

2.实现思路

  1. 加载视频
  2. 图像预处理(去噪、背景减除、形态学)
  3. 对车辆进行统计
  4. 显示车辆统计信息(增加水印)

3.详细步骤与技术实现

在这一部分,我们将深入探讨如何使用OpenCV库来实现车辆统计的具体步骤和技术细节。OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉和机器学习软件库,它提供了大量用于图像处理和计算机视觉任务的函数。

3.1 加载视频

首先,我们需要加载包含车辆运动的视频文件。在OpenCV中,这可以通过cv2.VideoCapture()函数来完成。你需要指定视频文件的路径作为参数。

代码示例:

import cv2  
  
# 视频文件路径  
video_path = 'video.mp4'  
  
# 创建一个VideoCapture对象  
cap = cv2.VideoCapture(video_path)  
  
if not cap.isOpened():  
    print("Error: Could not open video.")  
    exit()
3.2 图像预处理

图像预处理是车辆检测的关键步骤,它可以帮助我们提高检测的准确性和效率。

3.2.1 去噪

为了去除图像中的噪声,我们可以使用高斯模糊或中值模糊等方法。这里我们使用高斯模糊。

代码示例:

# 读取视频帧  
ret, frame = cap.read()  
  
if ret:  
    # 应用高斯模糊  
    blurred_frame = cv2.GaussianBlur(frame, (5, 5), 0)

 

3.2.2 背景减除

背景减除是车辆检测中常用的技术,它可以帮助我们分离出移动的对象(如车辆)。这里我们可以使用混合高斯背景/前景分割器(MOG2)或KNN背景/前景分割器。

代码示例:

# 创建背景减除器  
fgbg = cv2.createBackgroundSubtractorMOG2()  
  
# 对每一帧应用背景减除  
fgmask = fgbg.apply(blurred_frame)
3.2.3 形态学操作

形态学操作如腐蚀和膨胀可以帮助我们去除小的噪声点和填补前景对象中的小洞。

代码示例:

# 腐蚀操作  
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))  
eroded_fg = cv2.erode(fgmask, kernel, iterations=2)  
  
# 膨胀操作  
dilated_fg = cv2.dilate(eroded_fg, kernel, iterations=2)

 

3.3 对车辆进行统计

在形态学处理之后,我们通常会通过轮廓检测来识别出车辆。使用cv2.findContours()函数可以找到图像中的轮廓。

代码示例:

# 找到轮廓  
contours, hierarchy = cv2.findContours(dilated_fg, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)  
  
# 初始化车辆计数器  
vehicle_count = 0  
  
for contour in contours:  
    # 过滤掉小的轮廓  
    if cv2.contourArea(contour) > min_area_threshold:  
        vehicle_count += 1  
        # 可以在这里绘制轮廓或进行其他处理  
        cv2.drawContours(frame, [contour], -1, (0, 255, 0), 3)  
  
# 更新车辆统计信息  
print(f"Total vehicles detected: {vehicle_count}")

 

3.4 显示车辆统计信息(增加水印)

在视频帧上显示车辆统计信息,我们可以使用cv2.putText()函数在图像上添加文本。

代码示例:

# 在视频帧上添加车辆统计信息  
cv2.putText(frame, "car number:{}".format(car_cnt), (50, 50),   
            cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)  
  
# 显示结果  
cv2.imshow('frame', frame)  

 

3.5 清理资源

在视频处理完成后,记得释放VideoCapture对象和关闭所有OpenCV窗口。

代码示例:

# 释放VideoCapture对象  
cap.release()  
cv2.destroyAllWindows()
print("车辆数量:", car_cnt)

 

通过以上步骤,我们可以实现一个基本的车辆统计系统。当然,这个系统可以根据具体需求进行扩展和优化,比如使用更复杂的背景减除算法、引入深度学习模型进行车辆检测等。

4.项目完整代码(这里只使用了形态学进行降噪)

"""
车辆识别
1.前景和后景的分离
二值图
2.通过二值图查找轮廓
3.通过轮廓,获取外接最大的矩形区域,从而查找车辆
4.根据区域上的每一个点P0(x0,y0)
5.绘制一条线的区域范围:
如果P0点穿过线的范围,就统计一辆车

"""

import cv2
cap = cv2.VideoCapture("video.mp4")
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, ksize=(5, 5))
# 前后景分离
bgSegMog = cv2.bgsegm.createBackgroundSubtractorMOG()
line_y = 550
offset = 6
# 统计车辆数量
car_cnt = 0
while cap.isOpened():
    retval, frame = cap.read()
    if not retval:
        print('读取视频失败')
        break
    frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    # erode_frame = cv2.erode(frame_gray, kernel, iterations=10)
    # 前后景分离
    mask = bgSegMog.apply(frame_gray)
    mask_erode = cv2.erode(mask, kernel, iterations=1)
    mask_erode_dilate = cv2.dilate(mask_erode, kernel, iterations=1)
    #查找轮廓
    contours, hierarchy = cv2.findContours(mask_erode_dilate, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    # 绘制一条线的区域范围:
    cv2.line(frame, (0, line_y), (1280, line_y), (0, 0, 255), 2)
    for contour in contours:
        x, y, w, h = cv2.boundingRect(contour)
        if w < 90 and h < 90:
            continue
        if y > (line_y - offset) and y < (line_y + offset):
            car_cnt+=1
            pass
        cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
    cv2.putText(frame, "car number:{}".format(car_cnt), (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
    cv2.imshow("frame", frame)
    # cv2.imshow("mask", mask)
    # cv2.imshow("mask_erode", mask_erode)
    # cv2.imshow("mask_erode_dilate", mask_erode_dilate)
    cv2.waitKey(25)
cap.release()
cv2.destroyAllWindows()
print("车辆数量:", car_cnt)

5.总结

        本文使用OpenCV构建车辆统计系统,涵盖视频加载、图像预处理(去噪、背景减除、形态学操作)、车辆检测与计数,并在视频帧上实时显示车辆总数。通过轮廓检测与面积过滤识别车辆,优化检测准确性。系统实现自动化处理,可进一步扩展功能如车辆跟踪。展示了OpenCV在车辆统计中的强大能力,为相关领域提供了实用参考。

;