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

2017年09月21日 由 yining 发表 396258 0
用OpenCV计算道路交通流量的一个直观教程

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

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

文章地址:基于计算机视觉和OpenCV:创建一个能够计算道路交通流量的应用

本项目需要的完整代码:

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

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

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

用OpenCV计算道路交通流量的一个直观教程
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边缘检测器从图像中获取边缘。最后把它转化成白色背景(只是为了方便视觉)。

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

模糊

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






阈值









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






计算









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

问题

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

为什么需要这些数据?

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

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

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

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







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






欢迎关注ATYUN官方公众号
商务合作及内容投稿请联系邮箱:bd@atyun.com
评论 登录
写评论取消
回复取消