使用OpenCV和Python構建自己的車輛檢測模型

2021-01-11 人工智慧遇見磐創

介紹

我喜歡智慧城市的理念。自動智能能源系統、電網、一鍵接入埠的想法等等。這是一個令人著迷的概念!老實說,這是一個數據科學家的夢想,我很高興世界上很多城市都在朝著更智能的方向發展。

智能城市的核心組成部分之一是自動交通管理。這不禁讓我思考——我能用我的數據科學知識來建立一個車輛檢測模型,在智能交通管理中發揮作用嗎?

想想看,如果你能在紅綠燈攝像頭中集成車輛檢測系統,你可以輕鬆地同時跟蹤許多有用的東西:

白天交通路口有多少輛車?什麼時候交通堵塞?什麼樣的車輛(重型車輛、汽車等)正在通過交叉路口?有沒有辦法優化交通,並通過不同的街道進行分配?還有很多例子就不一一列舉。應用程式是無止境的!

我們人類可以很容易地在一瞬間從複雜的場景中檢測和識別出物體。然而,將這種思維過程轉化為機器的思維,需要我們學習使用計算機視覺算法進行目標檢測。

因此在本文中,我們將建立一個自動車輛檢測器和計數器模型。以下視頻是你可以期待的體驗:

https://youtu.be/C_iZ2yivskE

注意:還不懂深度學習和計算機視覺的新概念?以下是兩門熱門課程,可開啟你的深度學習之旅:

深度學習基礎(https://courses.analyticsvidhya.com/courses/fundamentals-of-deep-learning?utm_source=blog&utm_medium=vehicle-detection-opencv-python)利用深度學習的計算機視覺(https://courses.analyticsvidhya.com/courses/computer-vision-using-deep-learning-version2?utm_source=blog&utm_medium=vehicle-detection-opencv-python)目錄

視頻中運動目標檢測的思想視頻中目標檢測的真實世界用例視頻目標檢測的基本概念 幀差分 圖像閾值 檢測輪廓 圖像膨脹利用OpenCV構建車輛檢測系統視頻中運動目標檢測的思想

目標檢測是計算機視覺中一個引人入勝的領域。當我們處理視頻數據時,它達到了一個全新的水平,複雜性上升了一個等級,但也有回報!

我們可以使用目標檢測算法來執行超級有用的高價值任務,如監視、交通管理、打擊犯罪等。下面的GIF圖演示了這個想法:

在目標檢測中,我們可以執行許多子任務,例如計算目標數量、查找目標的相對大小或查找目標之間的相對距離。這些子任務都很重要,因為它們有助於解決一些最棘手的現實問題。

如果你希望從頭開始學習目標檢測,我建議你使用以下教程:

逐步介紹基本的目標檢測算法(https://www.analyticsvidhya.com/blog/2018/10/a-step-by-step-introduction-to-the-basic-object-detection-algorithms-part-1/?utm_source=blog&utm_medium=vehicle-detection-opencv-python)利用SlimYOLOv3進行實時目標檢測(https://www.analyticsvidhya.com/blog/2019/08/introduction-slimyolov3-real-time-object-detection/?utm_source=blog&utm_medium=vehicle-detection-opencv-python)其他目標檢測物品和資源(https://www.analyticsvidhya.com/blog/tag/object-detection/?utm_source=blog&utm_medium=vehicle-detection-opencv-python)讓我們看看一些令人興奮的現實世界中的目標檢測用例。

視頻中目標檢測的真實世界用例

如今,視頻目標檢測正被廣泛應用於各個行業。使用案例從視頻監控到體育廣播,再到機器人導航。

好消息是,在未來的視頻目標檢測和跟蹤用例中,可能性是無窮的。這裡我列出了一些有趣的應用程式:

人群計數(https://www.analyticsvidhya.com/blog/2019/02/building-crowd-counting-model-python/)車牌檢測與識別運動中的球跟蹤(https://www.analyticsvidhya.com/blog/2020/03/ball-tracking-cricket-computer-vision/)機器人學交通管理(我們將在本文中看到這個想法)視頻目標檢測的基本概念

在開始構建視頻檢測系統之前,你應該知道一些關鍵概念。一旦你熟悉了這些基本概念,就可以為你選擇的任何用例構建自己的檢測系統。

那麼,你希望如何檢測視頻中的移動目標?

我們的目標是捕捉運動物體的坐標並在視頻中突出顯示該物體。請考慮下面視頻中的這一幀:

我們希望我們的模型能夠檢測視頻中的運動目標,如上圖所示。檢測到移動的汽車,並在汽車周圍創建一個邊界框。

解決這個問題有多種方法。你可以為目標檢測訓練一個深度學習模型,也可以選擇一個預先訓練好的模型並根據你的數據對其進行微調。然而,這些方法都是有監督的學習方法,需要標記數據來訓練目標檢測模型。

在本文中,我們將重點討論視頻中無監督的目標檢測方法,即不使用任何標記數據的目標檢測。我們將使用幀差分技術。讓我們了解它是如何工作的!

幀差分

視頻是一組按正確順序堆疊在一起的幀。所以,當我們看到一個物體在視頻中移動時,這意味著這個物體在每一個連續的幀上都處於不同的位置。

如果我們假設除了該目標之外,在一對連續的幀中沒有其他物體移動,那麼第一幀與第二幀的像素差將突出顯示移動目標的像素。現在,我們得到了移動物體的像素和坐標。這就是幀差分法的工作原理。

舉個例子。考慮視頻中的以下兩個幀:

你能看出這兩幀的區別嗎?

握筆的手的位置從第1幀變為第2幀。其餘的物體根本沒有移動。所以,正如我前面提到的,為了定位移動目標,我們將執行幀差分。結果如下:

你可以看到高亮或白色區域,這是手最初出現的地方。除此之外,記事本的邊緣也會突出顯示一點。這可能是由於手的移動改變了光照。建議不要對靜止物體進行不必要的檢測。因此,我們需要對幀執行某些圖像預處理步驟。

圖像閾值

在這種方法中,灰度圖像的像素值根據閾值被指定為表示黑白顏色的兩個值之一。因此,如果一個像素的值大於一個閾值,它被賦予一個值,否則它被賦予另一個值。

在本例中,我們將對上一步驟中幀差分的輸出圖像應用圖像閾值:

你可以看到,不需要的高亮區域的大部分已經消失了。高亮顯示的「記事本」邊緣不再可見。合成的圖像也可以稱為二值圖像,因為其中只有兩種顏色。在下一個步驟中,我們將看到如何捕獲這些高亮區域。

檢測輪廓

輪廓用於識別圖像中具有相同顏色或強度的區域的形狀。輪廓就是目標區域周圍的邊界。因此,如果我們在閾值步驟後對圖像應用輪廓檢測,我們將得到以下結果:

白色區域被淺灰色的邊界所包圍,這些邊界就是輪廓。我們很容易得到這些輪廓的坐標。這意味著我們可以得到高亮區域的位置。

請注意,有多個高亮顯示區域,每個區域由輪廓包圍。在我們的例子中,具有最大面積的輪廓是我們期望的區域。因此,輪廓最好儘可能少。

在上圖中,仍然有一些不必要的白色區域碎片。還有改進的餘地。我們的想法是合併附近的白色區域以獲得更少的輪廓,為此,我們可以使用另一種稱為圖像膨脹的技術。

圖像膨脹

這是對圖像的卷積操作,其中核心(矩陣)傳遞到整個圖像上。為了給你直覺,右邊的圖像是左邊圖像的放大版本:

所以,讓我們對我們的圖像進行圖像膨脹,然後我們將再次找到輪廓:

事實證明,許多支離破碎的區域已經相互融合。現在我們可以再次在這張圖片中找到輪廓:

在這裡,我們只有四個候選輪廓,從中我們可以選擇一個有最大面積的輪廓。也可以在原始幀上繪製這些輪廓,以查看輪廓圍繞移動目標的情況:

用OpenCV和Python構建車輛檢測系統

我們準備建立我們的車輛檢測系統!在這個實現中,我們將大量使用計算機視覺庫OpenCV(4.0.0版)(https://www.analyticsvidhya.com/blog/2019/03/opencv-functions-computer-vision-python/?utm_source=blog&utm_medium=vehicle-detection-opencv-python) 。我們先導入所需的庫和模塊。

導入庫

import osimport reimport cv2 # opencv libraryimport numpy as npfrom os.path import isfile, joinimport matplotlib.pyplot as plt導入視頻幀

請從此連結下載原始視頻的幀。

https://drive.google.com/file/d/1P0yiO5KlnU8dGgB_L68KB_hjIvUec55f/view

將框架保存在工作目錄中名為「frames」的文件夾中。從該文件夾中,我們將導入幀並將其保存在列表中:

# get file names of the framescol_frames = os.listdir('frames/')# sort file namescol_frames.sort(key=lambda f: int(re.sub('\D', '', f)))# empty list to store the framescol_images=[]for i in col_frames: # read the frames img = cv2.imread('frames/'+i) # append the frames to the list col_images.append(img)數據探索

讓我們顯示兩個連續的幀:

# plot 13th framei = 13for frame in [i, i+1]: plt.imshow(cv2.cvtColor(col_images[frame], cv2.COLOR_BGR2RGB)) plt.title("frame: "+str(frame)) plt.show()

很難在這兩個框架中找到區別,不是嗎?如前所述,獲取兩個連續幀的像素值的差值將有助於我們觀察移動目標。那麼,讓我們在上面兩個幀上使用該技術:

# convert the frames to grayscalegrayA = cv2.cvtColor(col_images[i], cv2.COLOR_BGR2GRAY)grayB = cv2.cvtColor(col_images[i+1], cv2.COLOR_BGR2GRAY)# plot the image after frame differencingplt.imshow(cv2.absdiff(grayB, grayA), cmap = 'gray')plt.show()

現在我們可以清楚地看到第13幀和第14幀中的移動目標。其他沒有移動的東西都被減去了。

圖像預處理

讓我們看看對上面的圖像應用閾值後會發生什麼:

diff_image = cv2.absdiff(grayB, grayA)# perform image thresholdingret, thresh = cv2.threshold(diff_image, 30, 255, cv2.THRESH_BINARY)# plot image after thresholdingplt.imshow(thresh, cmap = 'gray')plt.show()

現在,移動物體(車輛)看起來更像我們期望看到的那樣了,大部分噪音(不希望出現的白色區域)都消失了。但是,突出顯示的區域有點零碎。因此,我們可以對該圖像應用圖像膨脹:

# apply image dilationkernel = np.ones((3,3),np.uint8)dilated = cv2.dilate(thresh,kernel,iterations = 1)# plot dilated imageplt.imshow(dilated, cmap = 'gray')plt.show()

移動的物體有更多的實心高亮區域。希望幀中每個目標的輪廓數不超過3。

但是,我們不會使用整個框架來檢測移動的車輛。我們將首先選擇一個區域,如果車輛進入該區域,則僅檢測到該區域。

那麼,讓我向你展示我們將會使用的區域:

# plot vehicle detection zoneplt.imshow(dilated)cv2.line(dilated, (0, 80),(256,80),(100, 0, 0))plt.show()

水平線y = 80以下的區域是我們的車輛檢測區域。我們將只檢測在這個區域發生的任何移動。你還可以創建自己的檢測區。

現在讓我們在上述幀的檢測區域中找到輪廓:

# find contourscontours, hierarchy = cv2.findContours(thresh.copy(),cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)上面的代碼查找整個圖像中的所有輪廓,並將它們保存在變量"contours"中。由於我們只需要找到檢測區域中存在的輪廓,我們將對發現的輪廓進行兩次檢查。

第一個檢查是輪廓左上角的y坐標是否應大於等於80(我這裡包括另一個檢查,x坐標小於等於200)。另一個檢查是輪廓的面積應該大於等於25。在cv2.courtoArea()函數的幫助下,你可以找到輪廓區域。

valid_cntrs = []for i,cntr in enumerate(contours): x,y,w,h = cv2.boundingRect(cntr) if (x <= 200) & (y >= 80) & (cv2.contourArea(cntr) >= 25): valid_cntrs.append(cntr)# count of discovered contours len(valid_cntrs)接下來,讓我們繪製輪廓和原始幀:

dmy = col_images[13].copy()cv2.drawContours(dmy, valid_cntrs, -1, (127,200,0), 2)cv2.line(dmy, (0, 80),(256,80),(100, 255, 255))plt.imshow(dmy)plt.show()

太酷了!只有位於檢測區域內的車輛輪廓可見。這就是我們在整個畫面中檢測車輛的方法

視頻中的車輛檢測

現在是時候對所有幀應用相同的圖像變換和預處理操作,並找到所需的輪廓。重申一下,我們將遵循以下步驟:

對每對連續幀應用幀差分對上一步的輸出圖像應用圖像閾值對上一步的輸出圖像進行圖像放大在上一步的輸出圖像中查找輪廓檢測區域出現的候選輪廓保存幀與最終輪廓# kernel for image dilationkernel = np.ones((4,4),np.uint8)# font stylefont = cv2.FONT_HERSHEY_SIMPLEX# directory to save the ouput framespathIn = "contour_frames_3/"for i in range(len(col_images)-1): # frame differencing grayA = cv2.cvtColor(col_images[i], cv2.COLOR_BGR2GRAY) grayB = cv2.cvtColor(col_images[i+1], cv2.COLOR_BGR2GRAY) diff_image = cv2.absdiff(grayB, grayA) # image thresholding ret, thresh = cv2.threshold(diff_image, 30, 255, cv2.THRESH_BINARY) # image dilation dilated = cv2.dilate(thresh,kernel,iterations = 1) # find contours contours, hierarchy = cv2.findContours(dilated.copy(), cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) # shortlist contours appearing in the detection zone valid_cntrs = [] for cntr in contours: x,y,w,h = cv2.boundingRect(cntr) if (x <= 200) & (y >= 80) & (cv2.contourArea(cntr) >= 25): if (y >= 90) & (cv2.contourArea(cntr) < 40): break valid_cntrs.append(cntr) # add contours to original frames dmy = col_images[i].copy() cv2.drawContours(dmy, valid_cntrs, -1, (127,200,0), 2) cv2.putText(dmy, "vehicles detected: " + str(len(valid_cntrs)), (55, 15), font, 0.6, (0, 180, 0), 2) cv2.line(dmy, (0, 80),(256,80),(100, 255, 255)) cv2.imwrite(pathIn+str(i)+'.png',dmy)準備視頻

在這裡,我們為所有幀中的所有移動車輛添加了輪廓。現在是時候堆疊幀並創建視頻了:

# specify video namepathOut = 'vehicle_detection_v3.mp4'# specify frames per secondfps = 14.0接下來,我們將閱讀列表中的最後一幀:

frame_array = []files = [f for f in os.listdir(pathIn) if isfile(join(pathIn, f))]files.sort(key=lambda f: int(re.sub('\D', '', f)))for i in range(len(files)): filename=pathIn + files[i] #read frames img = cv2.imread(filename) height, width, layers = img.shape size = (width,height) #inserting the frames into an image array frame_array.append(img)最後,我們將使用以下代碼製作目標檢測視頻:

out = cv2.VideoWriter(pathOut,cv2.VideoWriter_fourcc(*'DIVX'), fps, size)for i in range(len(frame_array)): # writing to a image array out.write(frame_array[i])out.release()恭喜你學會了車輛目標檢測!

尾注

在本教程中,我們學習了如何使用幀差分技術在視頻中執行移動目標檢測。我們還討論了目標檢測和圖像處理的一些概念。然後用OpenCV建立了自己的運動目標檢測系統。

相關焦點

  • OpenCV中的快速直線檢測
    該函數是LineSegmentDetector因版權問題從OpenCV中移除後最易用的直線檢測小能手,沒有之一。本文介紹該功能的使用方法其輸出結果剖析。在python的opencv相關的安裝包中,opencv-python 包含主要模塊,opencv-contrib-python 包含主要模塊以及一些擴展模塊。但這兩個模塊並不兼容,如果已經安裝過opencv-python,需要先卸載,再安裝opencv-contrib-python。
  • 基於TensorFlow 、OpenCV 和 Docker 的實時視頻目標檢測
    翻譯 | 於志鵬  徐普     校對 | 陶玉龍     整理 | 孔令雙在本文中,我將介紹如何在 Docker 容器中使用 Tensorflow Object-detection API 來執行實時(網絡攝像頭)和視頻的目標檢測。
  • 如何快速簡單的安裝opencv-python
    :可以在使用pip的時候,加上參數-i和鏡像地址(如https://pypi.tuna.tsinghua.edu.cn/simple),例如:>pip install -i https://pypi.tuna.tsinghua.edu.cn/simple opencv-contrib-python這樣就會從清華鏡像安裝opencv-contrib-python庫。
  • 目標檢測必須要OpenCV?10行Python代碼也能實現,親測好用!
    大數據文摘出品編譯:朱一輝、雪清、小魚短短10行代碼就可以實現目標檢測?!本文作者和他的團隊構建了一個名為ImageAI 的Python庫,集成了現今流行的深度學習框架和計算機視覺庫。本文將手把手教你構建自己的第一個目標檢測應用,而且文摘菌已經幫你踩過坑了,親測有效!
  • Python中的簡單人臉檢測(建議收藏)
    如何使用OpenCV庫檢測圖像中的人臉在本文中,將展示如何使用Python構建簡單的面部檢測器。建立一個可以檢測人臉的程序是一個很好的項目,可以開始使用計算機視覺。從名稱可以理解,我們將編寫一個程序來檢測圖像中的面部。當我說「程序」時,您可以將其理解為教機器做什麼。我喜歡使用教學而不是編程,因為這實際上是我們正在做的事情。
  • opencv-python圖像預處理-濾波
    為了消除外界環境對圖像採集的幹擾,增強圖像的邊緣及灰度跳變的部分,使圖像變得清晰以及提高圖像處理速度需要對圖像進行預處理操作,主要是對圖像進行濾波和增強操作。使用的方法可以分為空間域處理和頻率域處理兩類。空間域指圖像平面本身,這類圖像處理方法用各種模板直接與圖像進行卷積運算,實現對圖像的處理。
  • opencv-python獲取圖像:面向對象與面向過程
    關於圖片的來源:1973年6月,美國南加州大學的信號圖像處理研究所的一個助理教授和他的一個研究生打算為了一個學術會議找一張數字照片,而他們對於手頭現有成堆"無聊"照片感到厭煩。事實上他們需要的是一個人臉照片,同時又能讓人眼前一亮。這時正好有人走進實驗室,手上帶著一本當時的花花公子雜誌,結果故事發生了……而限於當時實驗室設備和測試圖片的需要,lenna的圖片只摳到了原圖的肩膀部分。
  • 「python opencv視覺零基礎」十、圖片效果毛玻璃
    一、學習目標了解高斯模糊的使用方法了解毛玻璃的圖片效果添加了解如何自己做一個噪聲圖片目錄「python opencv 計算機視覺零基礎實戰」 第一節「python opencv視覺入門到實戰」二、格式與攝像頭「python opencv 視覺入門到實戰」 三、圖像編輯「python opencv視覺入門到實戰
  • 「python opencv視覺零基礎」十四、直方圖反向投影
    前文提醒:博主正在參加博客之星評比,成功入選Top200,現在暫居第九歡迎各位點擊了解更多幫我投票,非常感謝~目錄「python opencv 計算機視覺零基礎實戰」 第一節「python opencv視覺入門到實戰」二、格式與攝像頭「python opencv 視覺入門到實戰」 三、圖像編輯「python
  • 世界上最好的語言PHP:OpenCV與計算機視覺已在我掌控之下
    在過去的半年中,作者利用空閒時間探索 PHP 與 OpenCV 的結合,並藉此調用與訓練優秀的機器學習模型。本文從實踐的角度介紹了如何使用 PHP 與 OpenCV 構建人臉檢測、人臉識別、超解析度與目標檢測等系統,因此 PHP 的各位擁躉們,可以盡情使用 OpenCV 探索計算機視覺了。本文首發於公眾號機器之心(ID:almosthuman2014),部分代碼格式有誤可參閱原文章。
  • 「python opencv計算機視覺零基礎到實戰」九模糊
    一、學習目標了解什麼是卷積了解模糊的使用方法與應用目錄「python opencv 計算機視覺零基礎實戰」 第一節「python opencv視覺入門到實戰」二、格式與攝像頭「python opencv 視覺入門到實戰」 三、圖像編輯「python opencv視覺入門到實戰」 第四節色彩空間
  • 「python opencv視覺零基礎實戰」七邏輯運算應用
    一、學習目標了解opencv中圖像的邏輯運算了解opencv中邏輯運算的應用如有錯誤歡迎指出~目錄「python opencv 計算機視覺零基礎實戰」 第一節「python opencv視覺入門到實戰」二、格式與攝像頭「python opencv 視覺入門到實戰」 三、圖像編輯「python
  • 基於opencv 的圖像處理入門教程
    前言雖然計算機視覺領域目前基本是以深度學習算法為主,但實際上很多時候對圖片的很多處理方法,並不需要採用深度學習的網絡模型,採用目前成熟的圖像處理庫即可實現,比如 OpenCV 和 PIL ,對圖片進行簡單的調整大小、裁剪、旋轉,或者是對圖片的模糊操作。
  • 「python opencv視覺零到實戰」八、圖片選區操作
    一、學習目標了解什麼是ROI了解floodFill的使用方法如有錯誤歡迎指出~目錄「python opencv 計算機視覺零基礎實戰」 第一節「python opencv視覺入門到實戰」二、格式與攝像頭「python opencv 視覺入門到實戰」 三、圖像編輯「python opencv視覺入門到實戰
  • 基於OpenCv 和 Python 的手指識別及追蹤
    使用閾值處理和濾波技術來進行背景消除以獲得最佳結果。我在手指識別時遇到的挑戰之一是將手與背景區分開並識別手指的尖端。我將向您展示我用於手指跟蹤的技術,我在此項目中使用了該技術。如果想要查看手指識別和跟蹤的實際操作,請觀看我上傳的視頻。
  • 史上最全 OpenCV 活體檢測教程!
    在開始訓練我們的活體檢測模型前, 我們先查看一下使用的數據集。我在本文的「下載」部分為大家提供了真實人臉視頻和偽造人臉視頻。你可以直接使用這些視頻開始構建數據集,但是我建議你收集更多的數據,從而幫助提升你的活體檢測器的魯棒性和準確率。通過測試,我確認這個模型會偏向於檢測出我自己的人臉——因為所有的模型都是使用我自己的視頻訓練的,因此這個模型依舊是有意義的。
  • 一文總結數據科學家常用的Python庫(下)
    (https://www.analyticsvidhya.com/blog/2015/01/scikit-learn-python-machine-learning-tool/)/* TensorFlow */TensorFlow由Google開發,是一個流行的深度學習庫,可幫助您構建和培訓不同的模型。它是一個開源的端到端平臺。
  • Python中如何利用Opencv打開視頻或圖像並用PyQt控制項顯示
    OpenCV是一個基於BSD許可(開源)發行的跨平臺計算機視覺庫,可以運行在Linux、Windows、Android和Mac OS作業系統上,使用起來十分方便,把它與PyQt結合起來,就可以順利的操作視頻、圖像了。具體安裝請自行百度,這裡介紹使用方法。
  • 使用Python,Keras和OpenCV進行實時面部活體檢測
    1.已知的面部數據集編碼該算法能夠識別自己和巴拉克歐巴馬。我選了大約10張照片。下面是處理和編碼已知面部數據集的Python代碼。現在我們知道了我們想要識別的每個人的編碼,我們可以嘗試通過網絡攝像頭識別和識別人臉。但是,在此之前,我們需要區分面部照片和活人臉部。
  • 資料| Practical Python and OpenCV 一周時間帶你入門CV