使用 OpenCV 識別圖片中的貓咪
你知道 OpenCV 可以識別在圖片中小貓的臉嗎?而且是拿來就能用,不需要其它的庫之類的。
之前我也不知道。
但是在 Kendrick Tan 曝出這個功能後,我需要親自體驗一下……去看看到 OpenCV 是如何在我沒有察覺到的情況下,將這一個功能添加進了他的軟體庫(就像一隻悄悄溜進空盒子的貓咪一樣,等待別人發覺)。
下面,我將會展示如何使用 OpenCV 的貓咪檢測器在圖片中識別小貓的臉。同樣的,該技術也可以用在視頻流中。
使用 OpenCV 在圖片中檢測貓咪
如果你查找過 OpenCV 的代碼倉庫,尤其是在 haarcascades 目錄里(OpenCV 在這裡保存處理它預先訓練好的 Haar 分類器,以檢測各種物體、身體部位等), 你會看到這兩個文件:
- haarcascade_frontalcatface.xml
- haarcascade_frontalcatface_extended.xml
這兩個 Haar Cascade 文件都將被用來在圖片中檢測小貓的臉。實際上,我使用了相同的 cascades 分類器來生成這篇博文頂端的圖片。
在做了一些調查工作之後,我發現這些 cascades 分類器是由鼎鼎大名的 Joseph Howse 訓練和貢獻給 OpenCV 倉庫的,他寫了很多很棒的教程和書籍,在計算機視覺領域有著很高的聲望。
下面,我將會展示給你如何使用 Howse 的 Haar cascades 分類器來檢測圖片中的小貓。
貓咪檢測代碼
讓我們開始使用 OpenCV 來檢測圖片中的貓咪。新建一個叫 cat_detector.py 的文件,並且輸入如下的代碼:
# import the necessary packages
import argparse
import cv2
# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True,
help="path to the input image")
ap.add_argument("-c", "--cascade",
default="haarcascade_frontalcatface.xml",
help="path to cat detector haar cascade")
args = vars(ap.parse_args())
第 2 和第 3 行主要是導入了必要的 python 包。6-12 行用於解析我們的命令行參數。我們僅要求一個必需的參數 --image
,它是我們要使用 OpenCV 檢測貓咪的圖片。
我們也可以(可選的)通過 --cascade
參數指定我們的 Haar cascade 分類器的路徑。默認使用 haarcascades_frontalcatface.xml
,假定這個文件和你的 cat_detector.py
在同一目錄下。
注意:我已經打包了貓咪的檢測代碼,還有在這個教程里的樣本圖片。你可以在博文原文的 「下載」 部分下載到。如果你是剛剛接觸 Python+OpenCV(或者 Haar cascade),我建議你下載這個 zip 壓縮包,這個會方便你跟著教程學習。
接下來,就是檢測貓的時刻了:
# load the input image and convert it to grayscale
image = cv2.imread(args["image"])
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# load the cat detector Haar cascade, then detect cat faces
# in the input image
detector = cv2.CascadeClassifier(args["cascade"])
rects = detector.detectMultiScale(gray, scaleFactor=1.3,
minNeighbors=10, minSize=(75, 75))
在 15、16 行,我們從硬碟上讀取了圖片,並且進行灰度化(這是一個在將圖片傳給 Haar cascade 分類器之前的常用的圖片預處理步驟,儘管不是必須的)
20 行,從硬碟載入 Haar casacade 分類器,即貓咪檢測器,並且實例化 cv2.CascadeClassifier
對象。
在 21、22 行通過調用 detector
的 detectMultiScale
方法使用 OpenCV 完成貓臉檢測。我們給 detectMultiScale
方法傳遞了四個參數。包括:
- 圖片
gray
,我們要在該圖片中檢測貓臉。 - 檢測貓臉時的圖片金字塔 的檢測粒度
scaleFactor
。更大的粒度將會加快檢測的速度,但是會對檢測 準確性 產生影響。相反的,一個更小的粒度將會影響檢測的時間,但是會增加 準確性 。但是,細粒度也會增加 誤報率 。你可以看這篇博文的「 Haar cascades 注意事項」部分來獲得更多的信息。 minNeighbors
參數控制了檢定框的最少數量,即在給定區域內被判斷為貓臉的最少數量。這個參數可以很好的排除 誤報 結果。- 最後,
minSize
參數不言自明。這個值描述每個檢定框的最小寬高尺寸(單位是像素),這個例子中就是 75*75
detectMultiScale
函數會返回 rects
,這是一個 4 元組列表。這些元組包含了每個檢測到的貓臉的 (x,y) 坐標值,還有寬度、高度。
最後,讓我們在圖片上畫下這些矩形來標識貓臉:
# loop over the cat faces and draw a rectangle surrounding each
for (i, (x, y, w, h)) in enumerate(rects):
cv2.rectangle(image, (x, y), (x + w, y + h), (0, 0, 255), 2)
cv2.putText(image, "Cat #{}".format(i + 1), (x, y - 10),
cv2.FONT_HERSHEY_SIMPLEX, 0.55, (0, 0, 255), 2)
# show the detected cat faces
cv2.imshow("Cat Faces", image)
cv2.waitKey(0)
給我們這些框(比如,rects)的數據,我們在 25 行依次遍歷它。
在 26 行,我們在每張貓臉的周圍畫上一個矩形。27、28 行展示了一個整數,即圖片中貓咪的數量。
最後,31,32 行在屏幕上展示了輸出的圖片。
貓咪檢測結果
為了測試我們的 OpenCV 貓咪檢測器,可以在原文的最後,下載教程的源碼。
然後,在你解壓縮之後,你將會得到如下的三個文件/目錄:
- cat_detector.py:我們的主程序
- haarcascade_frontalcatface.xml: 貓咪檢測器 Haar cascade
- images:我們將會使用的檢測圖片目錄。
到這一步,執行以下的命令:
$ python cat_detector.py --image images/cat_01.jpg
圖 1. 在圖片中檢測貓臉,甚至是貓咪部分被遮擋了。
注意,我們已經可以檢測貓臉了,即使它的其餘部分是被遮擋的。
試下另外的一張圖片:
python cat_detector.py --image images/cat_02.jpg
圖 2. 使用 OpenCV 檢測貓臉的第二個例子,這次貓臉稍有不同。
這次的貓臉和第一次的明顯不同,因為它正在發出「喵嗚」叫聲的當中。這種情況下,我們依舊能檢測到正確的貓臉。
在下面這張圖片的結果也是正確的:
$ python cat_detector.py --image images/cat_03.jpg
圖 3. 使用 OpenCV 和 python 檢測貓臉
我們最後的一個樣例就是在一張圖中檢測多張貓臉:
$ python cat_detector.py --image images/cat_04.jpg
圖 4. 在同一張圖片中使用 OpenCV 檢測多隻貓
注意,Haar cascade 返回的檢定框不一定是以你預期的順序。這種情況下,中間的那隻貓會被標記成第三隻。你可以通過判斷他們的 (x, y) 坐標來自己排序這些檢定框。
關於精度的說明
在這個 xml 文件中的注釋非常重要,Joseph Hower 提到了這個貓臉檢測器有可能會將人臉識別成貓臉。
這種情況下,他推薦使用兩種檢測器(人臉 & 貓臉),然後將出現在人臉識別結果中的結果剔除掉。
Haar cascades 注意事項
這個方法首先出現在 Paul Viola 和 Michael Jones 2001 年出版的 Rapid Object Detection using a Boosted Cascade of Simple Features 論文中。現在它已經成為了計算機識別領域引用最多的論文之一。
這個演算法能夠識別圖片中的對象,無論它們的位置和比例。而且最令人感興趣的或許是它能在現有的硬體條件下實現實時檢測。
在他們的論文中,Viola 和 Jones 關注在訓練人臉檢測器;但是,這個框架也能用來檢測各類事物,如汽車、香蕉、路標等等。
問題是?
Haar cascades 最大的問題就是如何確定 detectMultiScale
方法的參數正確。特別是 scaleFactor
和 minNeighbors
參數。你很容易陷入一張一張圖片調參數的坑,這個就是該對象檢測器很難被實用化的原因。
這個 scaleFactor
變數控制了用來檢測對象的圖片的各種比例的圖像金字塔。如果 scaleFactor
參數過大,你就只需要檢測圖像金字塔中較少的層,這可能會導致你丟失一些在圖像金字塔層之間縮放時少了的對象。
換句話說,如果 scaleFactor
參數過低,你會檢測過多的金字塔圖層。這雖然可以能幫助你檢測到更多的對象。但是他會造成計算速度的降低,還會明顯提高誤報率。Haar cascades 分類器就是這樣。
為了避免這個,我們通常使用 Histogram of Oriented Gradients + 線性 SVM 檢測 替代。
上述的 HOG + 線性 SVM 框架的參數更容易調優。而且更好的誤報率也更低,但是唯一不好的地方是無法實時運算。
對對象識別感興趣?並且希望了解更多?
圖 5. 在 PyImageSearch Gurus 課程中學習如何構建自定義的對象識別器。
如果你對學習如何訓練自己的自定義對象識別器感興趣,請務必要去了解下 PyImageSearch Gurus 課程。
在這個課程中,我提供了 15 節課,覆蓋了超過 168 頁的教程,來教你如何從 0 開始構建自定義的對象識別器。你會掌握如何應用 HOG + 線性 SVM 框架來構建自己的對象識別器來識別路標、面孔、汽車(以及附近的其它東西)。
要學習 PyImageSearch Gurus 課程(有 10 節示例免費課程),點此: https://www.pyimagesearch.com/pyimagesearch-gurus/?src=post-cat-detection
總結
在這篇博文里,我們學習了如何使用 OpenCV 默認就有的 Haar cascades 分類器來識別圖片中的貓臉。這些 Haar casacades 是由 Joseph Howse 訓練兵貢獻給 OpenCV 項目的。我是在 Kendrick Tan 的這篇文章中開始注意到這個。
儘管 Haar cascades 相當有用,但是我們也經常用 HOG + 線性 SVM 替代。因為後者相對而言更容易使用,並且可以有效地降低誤報率。
我也會在 PyImageSearch Gurus 課程中詳細的講述如何構建定製的 HOG + 線性 SVM 對象識別器,來識別包括汽車、路標在內的各種事物。
不管怎樣,我希望你喜歡這篇博文。
via: http://www.pyimagesearch.com/2016/06/20/detecting-cats-in-images-with-opencv/
作者:Adrian Rosebrock 譯者:MikeCoder 校對:wxy
本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive