學習在不使用機器學習或任何框架的情況下,如何在Python中進行物體檢測。
作者 | Ravindu Senaratne
譯者 | 彎月,責編 | 屠敏
頭圖 | CSDN 下載自視覺中國
以下為譯文:
每當我們聽說「物體檢測」時,就會想到機器學習和各種不同的框架。但實際上,我們可以在不使用機器學習或任何其他框架的情況下進行物體檢測。在本文中,我將向你展示如何僅使用Python進行操作。
首先,我們定義一個模板圖像(或者叫模板物體),然後程序將在源圖像中查找與我們選擇的模板匹配的所有其他物體。舉例來說明一下。下面有兩張圖片,上面是飛機的源圖像,下面是模板照片,其中的物體為飛機。
下面我們來編寫python代碼,圈出源圖像中所有匹配模板圖像的區域。
首先,我們來檢測一個物體。然後再調整代碼實現多個物體的檢測。
檢測一個物體:最準確的那個物體
我們需要一個源圖像和一個模板圖像。模板圖像在源圖像上滑動(像2D卷積有一樣),然後程序將嘗試找到最準確的匹配項。
下面我們開始寫代碼。
import cv2import numpy as npfrom matplotlib import pyplot as pltimg_rgb = cv2.imread('SourceIMG.jpeg')img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)template = cv2.imread('TemplateIMG.jpeg', 0)
在上述代碼中,我們使用OpenCV讀取SourceIMG.jpeg和TemplateIMG.jpeg。
height, width = template.shape[::]
模板圖像會在整個源圖像上滑動,對整個區域進行搜索(將左上角作為參考框)。模板圖像與源圖像匹配後,我們記下左上角的位置,然後在實際匹配的區域周圍繪製一個框。為此,我們需要知道此模板圖像的高度和寬度。下面我們來繪製矩形。
res = cv2.matchTemplate(img_gray, template, cv2.TM_SQDIFF)
模板匹配是OpenCV提供的功能,它利用源圖像和模板圖像的灰度圖像,計算我們需要的統計指標。這裡我使用的是最小平方差(TM_SQDIFF),因為我們尋找的是模板圖像和源圖像之間的最小差。
plt.imshow(res, cmap='gray')
如果將到目前為止的結果繪製成圖,就會得到一個概率圖。從下圖可以看到,這些小點是模板實際匹配的位置。
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
我們可以使用上面的代碼從概率圖中找出小點的位置。然後使用minMaxLoc(res)提取最小值、最大值、最小值的位置和最大值的位置。
top_left = min_loc bottom_right = (top_left[0] + width, top_left[1] + height)cv2.rectangle(img_rgb, top_left, bottom_right, (255, 0, 0), 2)
為了在模板圖像匹配的源圖像上繪製一個藍色矩形,我們需要獲得最小值的位置min_loc(該位置為匹配開始的位置)作為左上角。同樣,我們可以通過top_left[0] + width和top_left [1] + height獲得右下角。通過這些尺寸,我們可以使用cv2.rectangle繪製藍色矩形。
一切準備就緒,下面我們進行可視化。
cv2.imshow("Matchedimage", img_rgb)cv2.waitKey()cv2.destroyAllWindows()
完整的代碼:
import cv2import numpy as npfrom matplotlib import pyplot as pltimg_rgb = cv2.imread('SourceIMG.jpeg')img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)template = cv2.imread('TemplateIMG.jpeg', 0)height, width = template.shape[::]res = cv2.matchTemplate(img_gray, template, cv2.TM_SQDIFF)plt.imshow(res, cmap='gray')min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)top_left = min_loc #Change to max_loc for all except for TM_SQDIFFbottom_right = (top_left[0] + width, top_left[1] + height)cv2.rectangle(img_rgb, top_left, bottom_right, (255, 0, 0), 2) cv2.imshow("Matched image", img_rgb)cv2.waitKey()cv2.destroyAllWindows()
檢測多個物體:在給定閾值下進行檢測
上述我們已經完成了單個物體的檢測,即選擇源圖像和模板圖像之差的最小值。通過定義閾值的方法,我們可以檢測所有與模板圖像相似的物體。
為此,我將使用與上例相同的源圖像和模板圖像,並設置閾值為概率大於0.5(你可以查看res數組來確定閾值)。我們只需要更改幾行代碼即可檢測多個物體。
res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)
在這裡,我使用TM_CCOEFF_NORMED,因為我們需要獲取最大值,而不是最小值。這意味著我們需要尋找多個物體而不是一個。
threshold = 0.5 #For TM_CCOEFF_NORMED, larger values means good fitloc = np.where( res >= threshold)
我們要查找所有大於閾值的位置值。loc接收2個輸出數組,並將這些數組組合在一起,這樣就可以獲得x,y坐標。
forptinzip(*loc[::-1]):cv2.rectangle(img_rgb, pt, (pt[0] + width, pt[1] + height), (255, 0, 0), 1)
這裡有多個位置。因此,我們需要針對所有位置繪製藍色矩形。下面我們來進行可視化。
完整的代碼:
import cv2import numpy as npfrom matplotlib import pyplot as pltimg_rgb = cv2.imread('SourceIMG.jpeg')img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)template = cv2.imread('TemplateIMG.jpeg', 0)height, width = template.shape[::]res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)plt.imshow(res, cmap='gray')threshold = 0.5 #For TM_CCOEFF_NORMED, larger values = good fit.loc = np.where( res >= threshold) for pt in zip(loc[::-1]): cv2.rectangle(img_rgb, pt, (pt[0] + width, pt[1] + height), (255, 0, 0), 1) cv2.imshow("Matched image", img_rgb)cv2.waitKey()cv2.destroyAllWindows()
看起來很簡單吧?但是如果我們使用機器學習或框架,則可以達到更高的準確性。
感謝您的閱讀,希望本文對您有所幫助。
原文:https://towardsdatascience.com/object-detection-on-python-using-template-matching-ab4243a0ca62
本文為 CSDN 翻譯,轉載請註明來源出處。