使用OpenCV处理路口监控摄像头视频实现车辆的识别

使用OpenCV处理路口监控摄像头视频实现车辆的识别主要分为视频加载,形态学处理,逻辑处理,显示信息四个模块

一、视频加载模块:

1.获取视频文件

利用cap = cv.VideoCapture("1.mp4")获取视频文件

2.循环读取视频帧显示在窗口

读取视频帧-循环处理视频的每一帧

while True:

        ret,frame = cap.read()#读取视频返回值ret和frame

        ret: 布尔值,表示是否成功读取帧

        frame: 当前帧的图像数据

        if (ret == True):#判断是否成功读取

        cv.imshow("video",frame) #读取的每一帧显示在窗口上

3.键盘控制窗口关闭

#按ESC退出

key = cv.waitKey(1)

if(key == 27):

break

4.释放视频及窗口

释放视频捕获对象 cap.release()

关闭所有OpenCV窗口 cv.destroyAllWindows()

二、形态学处理模块

1.创建背景减除器和形态学内核

背景减除器-用于从视频中提取前景(移动物体)bgsubmog = cv.createBackgroundSubtractorMOG2()

形态学操作的内核-用于后续的图像处理操作 kernel = cv.getStructuringElement(cv.MORPH_RECT,(5,5))

2.帧预处理:

将帧转换为灰度图像

cv.cvtColor(frame,cv.COLOR_BGR2GRAY)

3.高斯模糊去噪

应用高斯模糊去噪 - 减少图像噪声,提高后续处理的准确性

参数: 输入图像, 核大小(3x3), 标准差(5)

blue = cv.GaussianBlur(frame,(3,3),5)

4.去背景

对模糊后的图像应用背景减除

mask = bgsubmog.apply(blue)

5.形态学操作(腐蚀、膨胀、闭操作)以优化前景掩码

腐蚀,去掉图中小斑块 erode = cv.erode(mask,kernel)

膨胀-还原被腐蚀的物体,并放大特征 dilate = cv.dilate(erode,kernel,iterations = 3)

闭操作-先膨胀后腐蚀,用于填充物体内部的小空洞 close = cv.morphologyEx(dilate,cv.MORPH_CLOSE,kernel)

6.查找、遍历、绘制轮廓

查找轮廓 - 在二值图像中查找物体的轮廓

cnts,h = cv.findContours(close,cv.RETR_TREE,cv.CHAIN_APPROX_SIMPLE)

cnts: 轮廓列表  h: 层次结构信息

遍历所有检测到的轮廓

for(i,c)in enumerate(cnts):

(x,y,w,h)=cv.boundingRect(c)获取轮廓的边界矩形

绘制矩形框标记检测到的车辆 - 红色框,线宽为2像素

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

三、逻辑处理模块

1.计算车辆中心点坐标

def center(x,y,w,h):

计算矩形区域的中心点坐标 参数: x, y: 矩形左上角坐标 w, h: 矩形的宽度和高度 返回: (cx, cy): 矩形中心点坐标

x1 = int(w/2)计算宽度的一半

y1 = int(h/2)计算高度的一半

cx = x + x1计算中心点的x坐标

cy = y + y1计算中心点的y坐标

return cx,cy返回中心点坐标

利用上面定义函数计算车辆中心点 cpoint = center(x,y,w,h)

将中心点添加到车辆列表中 cars.append(cpoint)
 

2.判断检测到的物体是否为有效车辆(基于尺寸阈值)

min_w = 90最小车辆宽度阈值(像素)

min_h = 90最小车辆高度阈值(像素)

#检查矩形尺寸是否满足车辆的最小尺寸要求

isValid = (w>=min_w) and (h>=min_h) 对车辆宽高进行判断

验证是否是有效的车辆

if(not isValid):

continue 

3.实现车辆计数逻辑(检测车辆是否通过检测线)

line_high = 900#检测线高度

offset = 9#线的偏移

carno = 0#统计车的数量

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

检查所有已检测车辆是否通过检测线

cv.line(frame,(10,line_high),(18000,line_high),(0,0,255),3)

for(x,y) in cars:

cv.imshow("video",frame) 是OpenCV库中用于显示视频帧的重要函数。该函数通常与视频捕获功能配合使用,可以实现实时视频流的显示和处理。以下是完整的视频帧读取和显示流程:

  1. 首先需要创建视频捕获对象:
cap = cv.VideoCapture(0)  # 0表示默认摄像头,也可以是视频文件路径

  1. 然后使用循环持续读取视频帧:
while True:
    ret, frame = cap.read()  # ret表示读取是否成功,frame是当前帧图像
    if not ret:
        break  # 如果读取失败则退出循环
    
    # 在这里可以对frame进行各种图像处理
    
    cv.imshow('video', frame)  # 显示当前帧
    
    if cv.waitKey(1) & 0xFF == ord('q'):  # 按q键退出
        break

  1. 最后需要释放资源:
cap.release()
cv.destroyAllWindows()

应用场景包括:

  • 实时视频监控系统
  • 视频会议应用
  • 计算机视觉项目开发
  • 视频内容分析

注意事项:

  • 帧率会根据硬件性能有所不同
  • 在高分辨率下可能需要优化处理算法
  • 可以添加各种图像处理操作在显示前
  • 在多线程应用中需要注意资源管理

if((y> line_high - offset) and (y<line_high + offset)):

carno += 1检查车辆中心点是否在检测线的偏移范围内

cars.remove((x,y))增加车辆计数

print(carno)从列表中移除已计数的车辆

打印当前车辆计数

四、显示信息模块

1.绘制检测线

在帧上绘制检测线-红色线,线宽为3像素

cv.line(frame,(10,line_high),(18000,line_high),(0,0,255),3)

2.显示车辆计数信息

 在帧上显示车辆计数 - 蓝色文字,大小为2,线宽为5

cv.putText(frame,"Cars Count:" + str(carno),(500,60),cv.FONT_HERSHEY_SIMPLEX,2,(255,0,0),5)

3.显示处理后的视频帧

cv.imshow("video",frame)

源代码如下:
import cv2 as cv

# 参数配置
min_w = 90#最小车辆宽度阈值(像素)
min_h = 90#最小车辆高度阈值(像素)
line_high = 900#检测线高度
offset = 9#线的偏移
carno = 0#统计车的数量
cars = []#存放有效车辆的数组

def center(x,y,w,h):
    """
      计算矩形区域的中心点坐标
      参数:
          x, y: 矩形左上角坐标
          w, h: 矩形的宽度和高度
      返回:
          (cx, cy): 矩形中心点坐标
      """
    x1 = int(w/2)#计算宽度的一半
    y1 = int(h/2)#计算高度的一半
    cx = x + x1#计算中心点的x坐标
    cy = y + y1#计算中心点的y坐标
    return cx,cy#返回中心点坐标

#视频加载
cap = cv.VideoCapture("1.mp4")
# 创建背景减除器-用于从视频中提取前景(移动物体)
bgsubmog = cv.createBackgroundSubtractorMOG2()

#创建形态学操作的内核-用于后续的图像处理操作
kernel = cv.getStructuringElement(cv.MORPH_RECT,(5,5))


#读取视频帧-循环处理视频的每一帧
while True:
    # ret: 布尔值,表示是否成功读取帧
    # frame: 当前帧的图像数据
    ret,frame = cap.read()
    if (ret == True):
        mask = bgsubmog.apply(frame)

        cv.imshow("video",mask)#显示前景掩码

        #将帧转换为灰度图像(但这里没有保存结果,所以这行代码实际上没有效果)
        cv.cvtColor(frame,cv.COLOR_BGR2GRAY)

        # 应用高斯模糊去噪 - 减少图像噪声,提高后续处理的准确性
        # 参数: 输入图像, 核大小(3x3), 标准差(5)
        blue = cv.GaussianBlur(frame,(3,3),5)

        #对模糊后的图像应用背景减除
        mask = bgsubmog.apply(blue)

        #腐蚀,去掉图中小斑块
        erode = cv.erode(mask,kernel)

        #膨胀操作-还原被腐蚀的物体,并放大特征
        #iterations=3 表示进行3次膨胀操作
        dilate = cv.dilate(erode,kernel,iterations = 3)

        #闭操作-先膨胀后腐蚀,用于填充物体内部的小空洞
        close = cv.morphologyEx(dilate,cv.MORPH_CLOSE,kernel)

        # 查找轮廓 - 在二值图像中查找物体的轮廓
        # cnts: 轮廓列表
        # h: 层次结构信息(这里使用_表示我们不使用这个变量)
        cnts,h = cv.findContours(close,cv.RETR_TREE,cv.CHAIN_APPROX_SIMPLE)

        # 在帧上绘制检测线-红色线,线宽为3像素
        cv.line(frame,(10,line_high),(18000,line_high),(0,0,255),3)

        # 遍历所有检测到的轮廓
        for(i,c)in enumerate(cnts):
            # 获取轮廓的边界矩形
            (x,y,w,h)=cv.boundingRect(c)

            # 检查矩形尺寸是否满足车辆的最小尺寸要求
            isValid = (w>=min_w) and (h>=min_h)

            #对车辆宽高进行判断
            #验证是否是有效的车辆
            if(not isValid):
                continue
            #到这里都是有效的车
            # 绘制矩形框标记检测到的车辆 - 红色框,线宽为2像素
            cv.rectangle(frame, (x, y), (x + w, y + h), (0, 0, 255), 2)
            # 计算车辆中心点
            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) #打印当前车辆计数

        # 在帧上显示车辆计数 - 蓝色文字,大小为2,线宽为5
        cv.putText(frame,"Cars Count:" + str(carno),(500,60),cv.FONT_HERSHEY_SIMPLEX,2,(255,0,0),5)
        # 显示处理后的帧
        cv.imshow("video",frame)

#ESC退出
    key = cv.waitKey(1)
    if(key == 27):
        break

# 释放视频捕获对象
cap.release()
# 关闭所有OpenCV窗口
cv.destroyAllWindows()
原视频:

OpenCV处理后:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值