作者|Jaime Duránx
編譯|Flin
來源|medium

目前我正在研究一個涉及面部分類的計算機視覺問題,這通常意味著應用深度學習,因此在將影像注入到我們的神經網路之前需要一個特殊的預處理階段,
為了提高我們的模型精度,這是一項非常重要的任務,通過以下幾個簡單的步驟可以很容易地完成,對于本文,我們可以使用OpenCV:一個高度優化的計算機視覺開源庫,在C++、java和Python中可用,
這是一篇簡短的文章,包含了一些基本的指導原則、示例和代碼,你可能需要將它們應用到每個面部分類或識別問題上,
注意:本文中使用的所有靜態影像都來自 https://imgflip.com/memetemplates
圖片載入
我們將使用imread()函式加載影像,指定檔案的路徑和mode,第二個引數對于動態運行基本通道和深度轉換非常重要,
- mode:https://docs.opencv.org/4.1.0/d4/da8/group__imgcodecs.html#ga61d9b0126a3e57d9277ac48327799c80
img = cv2.imread('path/image.jpg', cv2.IMREAD_COLOR)
要查看影像,我們有imshow()函式:
cv2.imshow(img)

如果你寫的是型別(img),你會看到尺寸是(height, weight, channels),
我們的彩色影像有3個通道:藍色,綠色和紅色(在OpenCV中按這個順序),

我們可以輕松查看單個通道:
# Example for green channel
img[:, :, 0]; img[:, :, 2]; cv2.imshow(img)
灰度版本
為了避免在面部影像分類中分心,使用黑白圖片是個好主意(也可能不是!)你可以兩者都試試),為了得到灰度版本,我們只需要在影像加載函式中指定,將適當的值作為第二個引數傳遞:
img = cv2.imread('path/image.jpg', cv2.IMREAD_GRAYSCALE)

現在我們的影像有了一個單獨的通道!
人臉和眼睛檢測
當處理面部分類問題時,我們可能想要做面部檢測,以驗證(是否有臉?),裁剪和拉直我們的影像,我們將使用OpenCV中包含的基于Haar特性的級聯分類器進行物件檢測,(https://docs.opencv.org/2.4/modules/objdetect/doc/cascade_classification.html)
首先,我們選擇預先訓練的人臉和眼睛檢測分類器,有一個可用的XML檔案串列,我們可以使用此串列:
- https://github.com/opencv/opencv/tree/master/data/haarcascades
1)對于人臉檢測,OpenCV提供以下(從最寬松的先驗到最嚴格的先驗):
-
haarcascade_frontalface_default.xml
-
haarcascade_frontalface_alt.xml
-
haarcascade_frontalface_alt2.xml
-
haarcascade_frontalface_alt_tree.xml
2) 對于眼睛檢測,我們可以選擇兩種方法:
-
haarcascade_eye.xml
-
haarcascade_eye_tree_eyegasses.xml
我們以這種方式加載預先訓練的分類器:
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + ‘haarcascade_frontalface_default.xml’)
eyes_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + ‘haarcascade_eye.xml’)
你可以測驗幾種組合,記住,在所有情況下,它們中沒有一個是最優的(如果第一個分類器失敗,你可以嘗試第二個分類器,或者甚至嘗試所有分類器),
對于人臉檢測,我們使用以下代碼:
faces_detected = face_cascade.detectMultiScale(img, scaleFactor=1.1, minNeighbors=5)
結果是一個陣列,包含所有檢測到的人臉,我們可以很容易地畫出矩形:
(x, y, w, h) = faces_detected[0]
cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 1);
cv2.imshow(img)

對于眼睛,我們以類似的方式進行搜索,但將搜索范圍縮小到面部矩形:
eyes = eyes_cascade.detectMultiScale(img[y:y+h, x:x+w])
for (ex, ey, ew, eh) in eyes:
cv2.rectangle(img, (x+ex, y+ey), (x+ex+ew, y+ey+eh),
(255, 255, 255), 1)
成啦!

雖然這是預期的結果,但我們會遇到很多其他方面的問題,很多時候,我們沒有正面和清晰的人的臉,甚至……
沒有眼睛:

眼睛是被白色包圍的黑色污點:

此處有4只眼,僅檢測到3只眼:

拉直臉部
通過計算兩只眼睛之間的角度,我們可以拉直臉部影像(這很容易),計算后,我們僅需兩個步驟即可旋轉影像:
rows, cols = img.shape[:2]
M = cv2.getRotationMatrix2D((cols/2, rows/2), <angle>, 1)
img_rotated = cv2.warpAffine(face_orig, M, (cols,rows))

裁剪臉部
為了幫助我們的神經網路完成面部分類任務,最好去掉背景、衣服或配飾等外部干擾資訊,在這種情況下,裁剪臉部是一個很好的選擇,
我們需要做的第一件事是從拉直的影像中再次得到人臉矩形,然后我們需要做一個決定:我們可以按原樣裁剪矩形區域,或者添加一個額外的填充,這樣我們可以獲得更多的空間,
這取決于要解決的具體問題(按年齡、性別、種族等分類);也許你想要更多的頭發;也許不需要,

最后,裁剪(p表示填充):
cv2.imwrite('crop.jpg', img_rotated[y-p+1:y+h+p, x-p+1:x+w+p])
看!這張臉是孤立的,幾乎可以進行深度學習了

影像縮放
神經網路需要所有的輸入影像具有相同的形狀和大小,因為GPU在同一時間對一批影像應用相同的指令,以達到超級快的速度,我們可以動態地調整它們的大小,但這可能不是一個好主意,因為在訓練期間將對每個檔案執行多個轉換,
因此,如果我們的資料集有很多影像,我們應該考慮在訓練階段之前實作批量調整大小的程序,
在OpenCV中,我們可以使用resize()函式執行向下縮放和向上縮放,有幾種可用的插值方法,指定最終尺寸的例子:
cv2.resize(img, (<width>, <height>), interpolation=cv2.INTER_LINEAR)
為了縮小影像,OpenCV建議使用INTER_AREA插值,而要放大影像,可以使用INTER_CUBIC(慢)或INTER_LINEAR(快,效果仍然不錯),
最后是質量和時間之間的權衡,
我做了一個快速的升級比較:

前兩幅影像的質量似乎更高(但你可以觀察到一些壓縮偽像),
線性方法的結果明顯更平滑并且噪點更少,
最后一個是像素化的,
歸一化
我們可以使用normalize()函式應用視覺歸一化,以修復非常暗/亮的圖片(甚至可以修復低對比度),
該歸一化型別(https://docs.opencv.org/3.4/d2/de8/group__core__array.html#gad12cefbcb5291cf958a85b4b67b6149f) 在函式引數中指定:
norm_img = np.zeros((300, 300))
norm_img = cv2.normalize(img, norm_img, 0, 255, cv2.NORM_MINMAX)
例子:


當使用影像作為深度卷積神經網路的輸入時,不需要應用這種歸一化,
在實踐中,我們將對每個通道進行適當的歸一化,比如減去平均值,然后除以像素級的標準差(因此我們得到平均值0和偏差1),如果我們使用遷移學習,最好的方法總是使用預先訓練的模型統計資料,
結論
在處理人臉分類/識別問題時,如果輸入的影像不是護照圖片,則檢測和分離出人臉是一項常見的任務,
OpenCV是一個很好的影像預處理庫,但不僅僅如此,它也是一個強大的工具,為許多計算機視覺應用…



來看檔案吧!
- https://docs.opencv.org/master/
希望你喜歡這篇文章!

原文鏈接:https://medium.com/yottabytes/a-quick-guide-on-preprocessing-facial-images-for-neural-networks-using-opencv-in-python-47ee3438abd4
歡迎關注磐創AI博客站:
http://panchuang.net/
sklearn機器學習中文官方檔案:
http://sklearn123.com/
歡迎關注磐創博客資源匯總站:
http://docs.panchuang.net/
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/131598.html
標籤:其他
