1. 程式人生 > 其它 >用OpenCV計算道路交通流量的一個直觀教程

用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%。但這並不是一個大問題,因為我們可以設定最小值/最大值的限制,或者根據光照條件使用額外的濾波,比如測試一些重點區域的邊緣(例如一些白矩形)。而且這些資料主要用作額外的資料,所以只需要相對值。

為什麼需要這些資料?

所有資料都是必需的,即使你現在不知道如何使用它們。在使用這些資料的情況下,我們可以解釋為什麼在某個時間點上最大車流量是有限的。

為什麼不使用一個大的演算法來完成所有的工作呢?

你必須記住的主要事情是,在資料科學專案中,它們不僅應該在領域中有效,而且對於業務來說也應該具有成本效益,包括速度、記憶體使用、可伸縮性、一小時執行時的成本和規模。

高效執行在任何條件下是沒有演算法的,例如,排序演算法,被用於本地專案而不會被用於大資料專案因為它的速度十分緩慢,大資料演算法不會用於本地專案的原因也同理(因為它們只有在大的資料量上更快)。

因此,你應該瞭解你的專案和業務限制,從而構建你的管道。