????計算機視覺作為人工智能領(lǐng)域一個最火的應(yīng)用點,最近幾年被媒體宣傳的沸沸揚揚,像商湯伶唯、曠視、壕屙铮康威視等等基于計算機視覺技術(shù)的公司都是各種投資者的寵兒抵怎。上個月曠視科技獲得了微軟舉辦的COCO Challenge 2017的冠軍更是讓“計算機視覺”重新成為了媒體報道的熱點奋救。
????人臉識別作為計算機視覺中的一個已經(jīng)很成熟的應(yīng)用點,在很多行業(yè)外的人眼中往往披了一層神秘的面紗反惕。那么“人臉識別”真的很困難嗎尝艘?其實未必,以一種稍微抽象點的方式理解的話姿染,“人臉識別”就如同小品里說的將大象裝進冰箱一樣簡單:1)將冰箱打開背亥;2)把大象裝進去;3)把冰箱門關(guān)上
????同樣的悬赏,“人臉識別”也能分三步實現(xiàn)
????1)將圖片中的人臉找出來狡汉;2)對找出來的人臉進行特征轉(zhuǎn)換(可以簡單理解為轉(zhuǎn)換成計算機能更好理解的格式);3)對轉(zhuǎn)換后的特征進行識別闽颇,看看是誰的臉盾戴。這其中每一步都能使用不同的機器學(xué)習(xí)算法來進行處理
????下邊我將針對開源人臉識別框架 openface 中的源碼進行解析幫助大家更好的理解人臉識別背后的分析邏輯到底是什么。openface的安裝過程請參照Mac上開源人臉識別軟件OPENFACE安裝全流程教程
????OpenFace開源框架提供了許多的 demo 腳本兵多,這能幫助我們更好的理解如何使用這個框架尖啡。下邊是調(diào)用demo腳本進行一個人臉識別的具體過程:
mkdir -p classify-test/raw/{lennon,clapton}
cp images/examples/lennon-* classify-test/raw/lennon
cp images/examples/clapton-* classify-test/raw/clapton
./util/align-dlib.py classify-test/raw align outerEyesAndNose classify-test/aligned --size96
./batch-represent/main.lua -outDir classify-test/features -data classify-test/aligned
./demos/classifier.py train classify-test/features
./demos/classifier.py infer ./classify-test/features/classifier.pkl images/examples/{carell,adams,lennon}*
????下邊我將通過分別解析上邊的openface使用語句,幫助大家理解openface是如何“將大象裝進冰箱里”的:
? ? 0)準備訓(xùn)練樣本
mkdir -p classify-test/raw/{lennon,clapton}
cp images/examples/lennon-* classify-test/raw/lennon
cp images/examples/clapton-* classify-test/raw/clapton
????這里作者在 classify-test/raw 文件目錄下放置好訓(xùn)練數(shù)據(jù)剩膘,將要進行訓(xùn)練的數(shù)據(jù)按照類別在 raw 下分別創(chuàng)建子目錄衅斩。這里我創(chuàng)建了 Lennon 和 clapton 兩個類別,然后將這兩個人的照片分別放進子文件夾中
????1)利用dlib開源包怠褐,對圖片中的人臉進行識別
./util/align-dlib.py classify-test/raw align outerEyesAndNose classify-test/aligned --size96
????這里 align-dliv.py 從 classify-test/raw 原始圖片文件夾中對里邊的每個圖片進行識別畏梆,然后將識別出來的人臉放入 classify-test/aligned 文件夾中。這里 align-dlib.py 很智能奈懒,對 raw 文件夾下的所有子文件夾都會對應(yīng)的在 aligned 下進行創(chuàng)建
????2)對識別出來的人臉進行抽象
./batch-represent/main.lua -outDir classify-test/features -data classify-test/aligned
????這里 main.lua 對 aligned 文件夾下的人臉進行特征轉(zhuǎn)化奠涌,形成兩個文件 reps.csv 和 labels.csv。reps.csv 中的每一行代表 aligned 文件夾下的一張圖片的特征值磷杏,而 labels.csv 中的每一行對應(yīng)的是每一張圖片的類別標簽(這個案例只有 lennon 和 clapton 兩類溜畅,各位可以根據(jù)自己需要放置數(shù)據(jù))
????3)對抽象出的特征進行分類
????第一步,用 ?2)中提取的特征值和標簽對模型進行訓(xùn)練茴丰,并將訓(xùn)練好的模型存在 classify-test/features 文件夾下达皿,一般存為 classifier.pkl天吓。值得注意的是這里特征提取使用的是一個已經(jīng)訓(xùn)練好了的神經(jīng)網(wǎng)絡(luò)模型贿肩,其置于 models/openface/nn4.small2.v1.t7
./demos/classifier.py train classify-test/features
????第二步,用訓(xùn)練好的分類模型 classifier.pkl 對新的圖片進行分類
./demos/classifier.py infer ./classify-test/features/classifier.pkl images/examples/{carell,adams,lennon}*
????理解了人臉識別的套路龄寞,那么如何一站式的實現(xiàn)人臉識別呢汰规?比如利用攝像頭對人臉進行捕捉,然后動態(tài)的進行人臉識別物邑。這樣的話溜哮,我們就能將它應(yīng)用在門禁系統(tǒng)滔金、安檢系統(tǒng)中了。
????不用擔心茂嗓,openface 的 demo/classifier_webcam.py 就是這個場景的一個簡單實踐餐茵,讓我們過一遍
????首先,將人臉識別所需要的模型準備好:
align = openface.AlignDlib(args.dlibFacePredictor) ?# 人臉檢測模型 dlib
net = openface.TorchNeuralNet(?? ??? ??? ??? ??? ??? ??? ?? ?# 特征抽象模型 神經(jīng)網(wǎng)絡(luò)
????args.networkModel,
????imgDim=args.imgDim,
????cuda=args.cuda)
????其次述吸,調(diào)用 opencv 的視頻流接口來使用攝像頭攝取的圖形進行實時監(jiān)測
# Capture device. Usually 0 will be webcam and 1 will be usb cam.
video_capture = cv2.VideoCapture(args.captureDevice)
video_capture.set(3, args.width) ? ? ? ? # 設(shè)定視頻窗口的長和寬
video_capture.set(4, args.height)
confidenceList = []
whileTrue: ? ?# 不斷循環(huán)讀取視頻流中的圖像
????ret, frame = video_capture.read() ? ?# 循環(huán)讀取圖片
????……
????然后忿族,對每張讀取到的圖像進行人臉識別:
persons, confidences = infer(frame, args)
????這里程序調(diào)用了函數(shù) infer,將讀取到的圖像 frame 和程序設(shè)定的參數(shù) args(主要是分類模型的位置)作為參數(shù)輸入函數(shù)中蝌矛,返回分類預(yù)測結(jié)果和結(jié)果的置信度
????接著道批,讓我們進入 infer 函數(shù)中,看看其到底做了什么吧
????[1] 將分類標簽和分類器讀入內(nèi)存
with open(args.classifierModel,'r') as f:
????(le, clf) = pickle.load(f)# le - label and clf - classifer
????[2] 進行圖像預(yù)處理
????—> 將輸入圖像進行顏色轉(zhuǎn)換
rgbImg = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
????—> 調(diào)用之前準備好的 dlib 模型 align 將圖像進行對圖像中的人臉進行識別入撒,并截取出來
bb = align.getAllFaceBoundingBoxes(rgbImg)
alignedFaces = []
for box in bb:
????alignedFaces.append(
????????align.align(
????????????args.imgDim,
????????????rgbImg,
????????????box,
????????????landmarkIndices=openface.AlignDlib.OUTER_EYES_AND_NOSE))
????—> 對識別出來的人臉隆豹,使用之前準備好的神經(jīng)網(wǎng)絡(luò)模型 net 進行特征轉(zhuǎn)換
reps = []
for alignedFace in alignedFaces:
????reps.append(net.forward(alignedFace))
[3] 對處理好的圖像特征值進行分類預(yù)測
for rep in reps:
????try:
????????rep = rep.reshape(1, -1) ?# 對特征值的形式進行轉(zhuǎn)換,將其轉(zhuǎn)換成一行
????except:?? ??? ??? ??? ??? ??? ??? ?? ?# 當 rep 為空時茅逮,跳出
????????print("No Face detected")
????????return(None,None)
????predictions = clf.predict_proba(rep).ravel() ? ? # 對 rep 進行預(yù)測
????maxI = np.argmax(predictions)?? ??? ??? ??? ??? ?? ?# 找出預(yù)測概率最大的那個結(jié)果的下標
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # max index
????persons.append(le.inverse_transform(maxI)) ?# 找到這個最大預(yù)測值所對應(yīng)的人名
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#(類別)璃赡,并放入 persons 數(shù)組中
????confidences.append(predictions[maxI])?? ?? ? ? # 將最大預(yù)測概率的值放入
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # confidences 數(shù)組中
????最后我們來總結(jié)一下,人臉識別的邏輯十分簡單氮唯,即將人臉從圖片中識別出來鉴吹,抽象轉(zhuǎn)換為計算機更容易理解的結(jié)構(gòu),并通過分類算法對訓(xùn)練數(shù)據(jù)進行訓(xùn)練惩琉,然后用訓(xùn)練好的模型進行分類豆励。
????由于人臉識別的應(yīng)用已經(jīng)很多年了,第一步中的人臉提取算法十分成熟瞒渠,我們甚至都不需要知道其中的具體細節(jié)良蒸,只要懂得如何調(diào)用 dlib 工具對人臉進行提取即可,而要在人臉識別上獲得很好的效果伍玖,除了需要足夠的訓(xùn)練數(shù)據(jù)之外嫩痰,就在于第二步和第三步模型算法的選擇和調(diào)優(yōu)上了。但這不是這篇的重點窍箍,我們下次再說