• 22.【实战】车辆统计


    理论知识见上一节,最终效果如下

    涉及到的内容

    (1)窗口的展示

    (2)图像/视频的加载

    (3)基本图形的绘制

    (4)车辆识别

    基本图像运算与处理、形态学处理、轮廓查找

    涉及到的知识点

    加载视频

    通过形态学识别车辆

    对车辆进行统计

    显示车辆统计信息

    加载视频

    1. import cv2
    2. import numpy as np
    3. cap = cv2.VideoCapture('E:\\video.mp4') #加载视频
    4. while True:
    5. ret, frame = cap.read()
    6. if (ret == True) :
    7. cv2.imshow('video',frame)
    8. key = cv2.waitKey(1)
    9. if(key == 27) : #esc键
    10. break
    11. cap.release()
    12. cv2.destroyAllWindows()

    去除背景(关键)

    运动的物体为前景,静止的物体为背景。将前景提取出来,把背景去除。

    createBackgroundSubtractorMOG()

    history:缓冲,表示多少毫秒,可不指定参数,用默认的即可;
    具体实现原理比较复杂,用到了一些视频序列关联信息,把像素值不变的认为是背景;

    注意:在opencv中已经不支持该函数,而是用createBackgroundSubtractorMOG2()替代;如果需要使用可以安装opencv_contrib模块,在其中的bgsegm中保留了该函数;

    API使用默认参数即可,调整比较多的是history

    在视频中,以时间轴为顺序。如果像素在整个时间轴内不发生变化,则认为是背景,如果发生变化且很频繁,则认为是前景。

    去除背景参考论文:

    An Improved Adaptive Background Mixture Model for Real-time Tracking with Shadow Detection

    在去除背景之前去噪:首先将原始图像进行灰度化,然后经过高斯滤波进行去噪

    1. import cv2
    2. import numpy as np
    3. cap = cv2.VideoCapture('E:\\video.mp4') #加载视频
    4. bgsubmog = cv2.createBackgroundSubtractorMOG2()
    5. test = cv2.createBackgroundSubtractorMOG2() #测试未经过高斯去噪的图像效果
    6. while True:
    7. ret, frame = cap.read()
    8. if (ret == True) :
    9. # 灰度化处理
    10. cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    11. # 去噪(高斯)
    12. blur = cv2.GaussianBlur(frame, (7,7),5)
    13. # 去背景
    14. mask = bgsubmog.apply(blur)
    15. test1 = test.apply(frame)
    16. cv2.imshow('video', mask)
    17. cv2.imshow('test1', test1)
    18. key = cv2.waitKey(1)
    19. if(key == 27) : #esc键
    20. break
    21. cap.release()
    22. cv2.destroyAllWindows()

    形态学处理

    腐蚀、膨胀、开运算、闭运算、顶帽、黑帽

    1. import cv2
    2. from cv2 import erode
    3. from cv2 import dilate
    4. import numpy as np
    5. cap = cv2.VideoCapture('E:\\video.mp4') #加载视频
    6. bgsubmog = cv2.createBackgroundSubtractorMOG2()
    7. # 形态学kernel
    8. kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))
    9. while True:
    10. ret, frame = cap.read()
    11. if (ret == True) :
    12. # 灰度化处理
    13. cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    14. # 去噪(高斯)
    15. blur = cv2.GaussianBlur(frame, (7,7),5)
    16. # 去背景
    17. mask = bgsubmog.apply(blur)
    18. # 腐蚀
    19. erode = cv2.erode(mask, kernel)
    20. # 膨胀
    21. dilate = cv2.dilate(erode, kernel, iterations= 2)
    22. # 形态学闭运算,去除图像里面的噪点
    23. close = cv2.morphologyEx(dilate, cv2.MORPH_CLOSE, kernel)
    24. # 查找轮廓
    25. cnts, h = cv2.findContours(close, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    26. # 对所有轮廓进行遍历
    27. for (i, c) in enumerate(cnts):
    28. (x,y,w,h) = cv2.boundingRect(c)
    29. cv2.rectangle(frame, (x,y),(x+w,y+h),(0,0,255),2)
    30. cv2.imshow('video', frame)
    31. # cv2.imshow('close', close)
    32. key = cv2.waitKey(1)
    33. if(key == 27) : # esc键
    34. break
    35. cap.release()
    36. cv2.destroyAllWindows()

     逻辑处理

    通过宽和高去除小的矩形

    绘制检测线,计算车的中心点

    如果车的中心点落在检测线的有效区域内,则计数加1

    显示车辆统计信息

    将统计的信息显示在视频中,车辆被重复计数产生的原因:检测线过宽,车辆还未完全出去就又被统计一次,还有一个原因是检测线的位置

    传统的车辆检测方法弊端:车速过慢容易造成重复检测,车速过快造成漏检

    目前用的较多的方法为深度学习,对车辆进行跟踪

    完整程序如下:

    1. from asyncio import CancelledError
    2. import cv2
    3. from cv2 import erode
    4. from cv2 import dilate
    5. import numpy as np
    6. # 滤除的最小矩形的范围
    7. min_w = 90
    8. min_h = 90
    9. # 定义检测线的高度,与视频大小有关,视频左上角为(0,0)
    10. line_high = 550
    11. # 线的偏移量
    12. offset = 7
    13. # 统计车的数量
    14. carno = 0
    15. # 存放有效车辆的数组
    16. cars = []
    17. # 求车的中心点
    18. def center(x,y,w,h):
    19. x1 = int(w/2)
    20. y1 = int(h/2)
    21. cx = x + x1
    22. cy = y + y1
    23. return cx,cy
    24. cap = cv2.VideoCapture('E:\\video.mp4') #加载视频
    25. bgsubmog = cv2.createBackgroundSubtractorMOG2()
    26. # 形态学kernel
    27. kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))
    28. while True:
    29. ret, frame = cap.read()
    30. if (ret == True) :
    31. # 灰度化处理
    32. cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    33. # print(frame.shape) # 获取视频大小的信息
    34. # exit() # 该命令之后的所有程序都不执行
    35. # 去噪(高斯)
    36. blur = cv2.GaussianBlur(frame, (7,7),5)
    37. # 去背景
    38. mask = bgsubmog.apply(blur)
    39. # 腐蚀
    40. erode = cv2.erode(mask, kernel)
    41. # 膨胀
    42. dilate = cv2.dilate(erode, kernel, iterations= 2)
    43. # 形态学闭运算,去除图像里面的噪点
    44. close = cv2.morphologyEx(dilate, cv2.MORPH_CLOSE, kernel)
    45. # 查找轮廓
    46. cnts, h = cv2.findContours(close, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    47. # 绘制一条检测线
    48. cv2.line(frame, (10,line_high),(1200, line_high),(255,255,0),3)
    49. # 对所有轮廓进行遍历
    50. for (i, c) in enumerate(cnts):
    51. (x,y,w,h) = cv2.boundingRect(c)
    52. # 对车辆的宽高进行判断,以验证是否为有效的车辆
    53. isValid = (w >= min_w) and ( h >= min_h)
    54. if( not isValid):
    55. continue
    56. # 到这里都是有效的车,绘制车的矩形
    57. cv2.rectangle(frame, (x,y),(x+w,y+h),(0,0,255),2)
    58. # 存储车的中心点
    59. cpoint = center(x,y,w,h) # 计算车的中心点
    60. cars.append(cpoint) # 将中心点数据存储到cars这个数组中
    61. for (x,y) in cars : # 遍历数组,如果车的中心点落在检测线的有效区域内,则计数+1,然后去除该数组
    62. if ((y > line_high - offset) and (y < line_high + offset)):
    63. carno += 1
    64. cars.remove((x,y))
    65. print(carno)
    66. # 显示统计信息
    67. cv2.putText(frame, "Cars Count:" + str(carno),(500,60), cv2.FONT_HERSHEY_SIMPLEX, 2, (255, 0, 0), 5)
    68. cv2.imshow('video', frame)
    69. # cv2.imshow('close', close)
    70. key = cv2.waitKey(1)
    71. if(key == 27) : # esc键
    72. break
    73. cap.release()
    74. cv2.destroyAllWindows()

  • 相关阅读:
    创建容器镜像:如何编写正确、高效的Dockerfile
    PKDGAN: Private Knowledge Distillation with Generative Adversarial Networks
    JAVA基础算法(6)----- 国际象棋 α 皇后问题
    09_子查询
    计算机中的一些基本概念(速度,比特,门,电路图)
    教你如何使用Nodejs搭建HTTP web服务器并发布上线公网
    IDL 文本编码、代码补全快捷方式、IDL doc、格式器、行号显示设置
    Nginx+Keepalived+LVS集群实战
    数据库、计算机网络,操作系统刷题笔记4
    排序算法之【归并排序】
  • 原文地址:https://blog.csdn.net/qq_45355603/article/details/125286992