用OpenCV计算道路交通流量的一个直观教程

这篇文章将向你展示一个非常简单但功能强大的示例,说明如何使用你可以在设备上运行的算法来计算交通流量。

阅读本文之前,建议你阅读这篇关于道路交通分类的文章,它提到了我们在本项目中将要介绍的基础管道架构的一部分。

文章地址:http://www.atyun.com/7883_基于计算机视觉和opencv:创建一个能够计算道路交通.html

本项目需要的完整代码:

https://github.com/creotiv/object_detection_projects/tree/master/opencv_traffic_capacity_counting

这个算法包括4个步骤:

1.获得车架边缘 2.模糊车架边缘以得到更多填充区 3.二进制阈值将图像变得模糊 4.重叠阈值图像中你感兴趣的区域(重点区域),你可以在你的计算位置上进行掩膜,并在提供了最大车辆通行量的情况下计算黑像素/白像素。

下面你可以看到每一个步骤的图示:

class CapacityCounter(PipelineProcessor):


    def __init__(self, area_mask, save_image=False, image_dir='./'):
         super(CapacityCounter,self).__init__()

        self.area_mask= area_mask
         self.all = np.count_nonzero(area_mask)
         self.image_dir= image_dir
        self.save_image= save_image


    def calculate_capacity(self, frame, frame_number):
         base_frame= frame
         # CLAHE (Contrast Limited Adaptive Histogram Equalization)
         # this used for noise reduction at night time
         frame= cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)
         clahe= cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
         cl1= clahe.apply(frame)


         # getting edges with Canny filter
         edges= cv2.Canny(frame,50,70)
         # invert them to get white background
         edges= ~edges


         # blur with additional use of bilateralFilter to remove color noise
         blur= cv2.bilateralFilter(cv2.blur(edges,(21,21),100),9,200,200)


         # threshold with ROI overlapping
         _, threshold= cv2.threshold(blur,230,255,cv2.THRESH_BINARY)
        t= cv2.bitwise_and(threshold,threshold,mask= self.area_mask)


         # counting capacity area
         free= np.count_nonzero(t)
         capacity= 1 - float(free)/self.all


         # creating plot for debugging and visualization
         if self.save_image:
             img= np.zeros(base_frame.shape, base_frame.dtype)
             img[:, :]= EXIT_COLOR
             mask= cv2.bitwise_and(img, img, mask=self.area_mask)
             cv2.addWeighted(mask,1, base_frame,1,0, base_frame)


             fig= plt.figure()
             fig.suptitle("Capacity: {}%".format(capacity*100), fontsize=16)
            plt.subplot(221),plt.imshow(base_frame),plt.title('Original')
            plt.xticks([]), plt.yticks([])
            plt.subplot(222),plt.imshow(edges),plt.title('Cany edges')
             plt.xticks([]), plt.yticks([])
             plt.subplot(223),plt.imshow(blur),plt.title('Blur')
             plt.xticks([]), plt.yticks([])
             plt.subplot(224),plt.imshow(t),plt.title('Threshold with ROI mask')
             plt.xticks([]), plt.yticks([])


             fig.savefig(self.image_dir+ ("/processed_%s.png" % frame_number), dpi=500)


         return capacity

     def __call__(self, context):
         frame= context['frame'].copy()
     frame_number= context['frame_number']
                   capacity= self.calculate_capacity(frame, frame_number)

       self.log.debug("Capacity: {}%".format(capacity*100))
       context['capacity']= capacity

        return context

边缘

使用CLAHE(限制对比度的自适应直方图均衡)来消除图像上的噪声,然后使用Canny边缘检测器从图像中获取边缘。最后把它转化成白色背景(只是为了方便视觉)。

更多信息:CLAHE:http://docs.opencv.org/3.1.0/d5/daf/tutorial_py_histogram_equalization.html

Canny边缘检测器:http://docs.opencv.org/trunk/da/d22/tutorial_py_canny.html

模糊

我们使用基本的模糊和双边滤波(Bilateral filter)算法来消除一些颜色的噪声,并提供更好的分割。

阈值

最后的滤波是一个二进制的阈值,只使用白色和黑色的像素作为我们对汽车/非汽车的分割。

计算

最后一个简单的步骤就是将黑像素的数量与白像素的数量进行区分,以获得最大车流量。

问题

由于一些相机的噪声和户外条件不同,精确度可能不会达到70-85%。但这并不是一个大问题,因为我们可以设置最小值/最大值的限制,或者根据光照条件使用额外的滤波,比如测试一些重点区域的边缘(例如一些白矩形)。而且这些数据主要用作额外的数据,所以只需要相对值。

为什么需要这些数据?

所有数据都是必需的,即使你现在不知道如何使用它们。在使用这些数据的情况下,我们可以解释为什么在某个时间点上最大车流量是有限的。

为什么不使用一个大的算法来完成所有的工作呢?

你必须记住的主要事情是,在数据科学项目中,它们不仅应该在领域中有效,而且对于业务来说也应该具有成本效益,包括速度、内存使用、可伸缩性、一小时运行时的成本和规模。

高效运行在任何条件下是没有算法的,例如,排序算法,被用于本地项目而不会被用于大数据项目因为它的速度十分缓慢,大数据算法不会用于本地项目的原因也同理(因为它们只有在大的数据量上更快)。

因此,你应该了解你的项目和业务限制,从而构建你的管道。

原文发布于微信公众号 - ATYUN订阅号(atyun_com)

原文发表时间:2017-09-21

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏人工智能头条

关于NLP你还不会却必须要学会的事儿—NLP实践教程指南第一编

1141
来自专栏一心无二用,本人只专注于基础图像算法的实现与优化。

图像抠图算法学习 - Shared Sampling for Real-Time Alpha Matting

 一、序言      陆陆续续的如果累计起来,我估计至少有二十来位左右的朋友加我QQ,向我咨询有关抠图方面的算法,可惜的是,我对这方面之前一直是没有研究过的。除...

4746
来自专栏Python小屋

Python实现中英文分词

首先给出昨天文章里最后的小思考题的答案,原文链接为: Python从序列中选择k个不重复元素 既然选择的是不重复的元素,那么试图在[1,100]这样的区间里选...

3908
来自专栏贾志刚-OpenCV学堂

图形图像算法中必须要了解的设计模式(1)

随着信息的多元化,信息的概念不仅仅指的是文字,它还包含图片、声音、视频等其它丰富的信息。文字信息越来越多地被图片、声音、视频信息所替代,而视频又是由一针一针的图...

883
来自专栏人工智能

C+实现神经网络之壹—Net类的设计和神经网络的初始化

闲言少叙,直接开始 既然是要用C++来实现,那么我们自然而然的想到设计一个神经网络类来表示神经网络,这里我称之为Net类。由于这个类名太过普遍,很有可能跟其他人...

1868
来自专栏从流域到海域

自相关和偏自相关的简单介绍

原文地址:https://machinelearningmastery.com/gentle-introduction-autocorrelation-part...

5167
来自专栏AI研习社

基于 Tensorflow eager 的文本生成,注意力,图像注释的完整代码

我总是发现生成和序列模型令人着迷:他们提出的问题与我们刚开始学习机器学习时常遇到的问题不同。当我第一次开始学习ML时,我学了分类和回归(和大多数人一样)。这些帮...

902
来自专栏数据派THU

一文解读Tensor到底是个啥玩意儿?(附代码)

本文介绍了各种数值型数据的容器(标量、向量、矩阵、张量)之间的关系,在实践中,张量特指3维及更高维度的数据容器。

1203
来自专栏智能算法

机器学习三人行(系列二)----机器学习前奏,洞悉数据之美

前沿 当你想了解机器学习,最好的方式就是用真实的数据入手做实验。网络上有很多优秀的开源资料,包括数据集,这里我们选择了加利福尼亚的房价数据集(数据的获得后面会给...

3587
来自专栏大数据挖掘DT机器学习

【案例】SPSS商业应用系列第2篇: 线性回归模型

商业保险公司希望通过分析以往的固定资产保险理赔案例,能够预测理赔金额,借以提高其服务中心处理保险理赔业务的速度和服务质量,并降低公司运营风险。业界领先...

3637

扫码关注云+社区