使用Python、OpenCV计算道路通行能力
今天我将向您展示一个非常简单但功能强大的示例,说明如何使用可在设备上运行的算法来计算流量容量。
所以这个算法分四步工作:
1.获取帧边缘。
2.模糊它们以获得更多填充区域。
3.二进制阈值模糊图像。
4.用ROI重叠阈值图像(您掩盖您的位置)并计算黑色像素/白色像素,从而为您提供流量容量。
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 Edge Detector从图像中获取边缘。我们反转它得到白色背景(只是为了视觉方便)
模糊
我们使用基本模糊处理和双边滤波来消除一些色彩噪点并提供更好的分割。
阈
最后一个滤波器是一个二进制阈值,我们只用它来获取白色和黑色像素,这些像素可以作为我们在汽车/不是汽车上的细分。
计数
最后一个简单的步骤就是将黑色像素的数量与白色像素的数量相除以获得流量。
问题
由于一些摄像机噪音和不同的户外条件,准确度可能不会那么大〜70-85%。
但这不是一个大问题,因为我们可以设置最小/最大限制,或者使用基于光照条件的附加滤波,例如某些测试ROI(例如某个白色矩形)的边缘数量。
而且这些数据主要用作附加数据,所以只需要相对值。
为什么需要这些数据?
所有数据都是需要的,即使您现在不知道如何使用它,在我们使用这些数据的情况下,我们可以说为什么流量在某个时间点受到限制。
为什么不使用一个可以完成所有工作的大算法?
在数据科学项目中, 它们不仅应该在域中有效, 而且还要具有成本效益, 这包括速度、内存使用率、可伸缩性、一个任务和规模的一个小时运行时成本。
在任何情况下都没有有效运行的算法, 例如, 用于本地项目的排序算法将永远不会在大型数据项目中使用, 因为将会很慢, 而且大数据算法将不会用于本地项目的原因也会很慢 (因为它们只会在大量数据中加速)。
所以你应该根据项目和业务限制使用不同的方法。