OpenCV+Tensorflow實現(xiàn)實時人臉識別演示
點擊上方“小白學(xué)視覺”,選擇加"星標(biāo)"或“置頂”
重磅干貨,第一時間送達(dá)
本文轉(zhuǎn)自|OpenCV學(xué)堂
Facenet網(wǎng)絡(luò)介紹
FaceNet是谷歌提出的人臉識別模型,它跟其他人臉識別模型最大的一個不同就是它不是一個中間層輸出,而是直接在歐幾里德低維空間嵌入生成人臉特征,這個對以后的各種識別、分類、相似度比較都非常方便。相比其他的深度學(xué)習(xí)方法,F(xiàn)aceNet僅需要128個字節(jié)來表示一張臉。FaceNet網(wǎng)絡(luò)設(shè)計目標(biāo)任務(wù)有如下
1.驗證-驗證是否為同一張臉
2.識別-識別是否為同一個人
3.聚類-發(fā)現(xiàn)人臉具有相同之處的人關(guān)于什么是神經(jīng)網(wǎng)絡(luò)嵌入,這個解釋比較復(fù)雜,簡單的說神經(jīng)網(wǎng)絡(luò)的嵌入學(xué)習(xí)可以幫助我們把離散變量表示為連續(xù)的向量,在低維空間找到最近鄰,tensorflow中的word2vec就是用了嵌入。一旦嵌入神經(jīng)網(wǎng)絡(luò)訓(xùn)練好以后,目標(biāo)任務(wù)就變得很簡單:
人臉驗證 – 就變成相似度比較問題
人臉識別 – 就變成KNN分類問題
人臉聚類 – 就變成通過K-Means可以完成的問題相比其它的人臉識別網(wǎng)絡(luò),通過添加分類層實現(xiàn)人臉識別,在分類層之前輸出的人臉特征數(shù)據(jù)動則就幾千個維度數(shù)據(jù),而且不能很好表達(dá)一張新的人臉。FaceNet使用三元損失函數(shù)基于LMNN訓(xùn)練輸出128維的連續(xù)向量。三元損失包含了兩個匹配人臉的指紋與一個不匹配的人臉指紋,損失函數(shù)訓(xùn)練的目標(biāo)是訓(xùn)練它在匹配人臉指紋與不匹配人臉指紋之間距離margin足夠大為止。人臉指紋來自人臉區(qū)域圖像,沒有經(jīng)過對齊,只是結(jié)果簡單的幾何變換。整個網(wǎng)絡(luò)架構(gòu)與三元表示如下:
其中
對正負(fù)樣本的選擇需要選擇難樣本得到triplet,有利于更好的訓(xùn)練效果與模型收斂。
代碼實現(xiàn):
借用了Github上的一個tensorflow版本facenet實現(xiàn),下載了預(yù)訓(xùn)練的facenet模型,基于得到embedding數(shù)據(jù),這個會輸出512個維度數(shù)據(jù),進(jìn)行比較實現(xiàn)人臉相似度計算。相似度計算采用了余弦相似度度量,兩個嵌入數(shù)據(jù)距離為0表示完全一致,距離為1表示完全不同。0.5或者90度表示二者相互獨立。
facenet預(yù)訓(xùn)練模型下載:
https://github.com/davidsandberg/facenet加載模型與樣本數(shù)據(jù)代碼如下
with tf.Graph().as_default():
with tf.Session() as sess:
# Load the model
facenet.load_model("D:/python/facenet/data/20180408-102900")
# Get input and output tensors
images_placeholder = tf.get_default_graph().get_tensor_by_name("input:0")
embeddings = tf.get_default_graph().get_tensor_by_name("embeddings:0")
phase_train_placeholder = tf.get_default_graph().get_tensor_by_name("phase_train:0")
# Run forward pass to calculate embeddings
images, names = load_face_labels()
num_labels = len(names)
feed_dict = {images_placeholder: images, phase_train_placeholder: False}
labels_embeddings = sess.run(embeddings, feed_dict=feed_dict)人臉比較的代碼如下
def face_compare(face_image):
# Run forward pass to calculate embeddings
feed_dict = {images_placeholder: face_image, phase_train_placeholder: False}
embedding_result = sess.run(embeddings, feed_dict=feed_dict)
minDist = 1000000
label_index = -1
for i in range(num_labels):
# 余弦相似
dist = facenet.distance([labels_embeddings[i]], [embedding_result[0]], 1)
if minDist > dist:
label_index = i
minDist = dist
print("minDist: %1.4f"%minDist)
if minDist > 0.25:
return "unknown"
if names[label_index] == 3:
return "zhigang"
if names[label_index] == 2:
return "peter"
if names[label_index] == 1:
return "balvin"OpenCV實時攝像頭調(diào)用與輸出
capture = cv.VideoCapture(0)
height = capture.get(cv.CAP_PROP_FRAME_HEIGHT)
width = capture.get(cv.CAP_PROP_FRAME_WIDTH)
out = cv.VideoWriter("D:/faces.mp4", cv.VideoWriter_fourcc('D', 'I', 'V', 'X'), 15,
(np.int(width), np.int(height)), True)
while True:
ret, frame = capture.read()
if ret is True:
frame = cv.flip(frame, 1)
cv.imshow("frame", frame)
rgb = cv.cvtColor(frame, cv.COLOR_BGR2RGB)
result, bb = mtcnn_align_demo(rgb)
if result is not None:
name = face_compare(result)
cv.rectangle(frame, (bb[0], bb[1]), (bb[2], bb[3]), (0, 0, 255), 1, 8, 0)
cv.putText(frame, name, (bb[0], bb[1]), cv.FONT_HERSHEY_SIMPLEX, 1.0, (0, 255, 0), 2, 8)
cv.imshow("face recognition demo", frame)
out.write(frame)
cv.imwrite("D:/face_recognition.png", frame)
c = cv.waitKey(10)
if c == 27:
break
else:
break
out.release()
capture.release()
cv.destroyAllWindows()人臉數(shù)據(jù)采集
通過MTCNN進(jìn)行人臉實時檢測,采集了待比較的每個人的人臉數(shù)據(jù),進(jìn)行了數(shù)據(jù)采選,打上了標(biāo)簽。采集數(shù)據(jù)代碼如下:
while True:
ret, frame = capture.read()
if ret is True:
frame = cv.flip(frame, 1)
cv.imshow("frame", frame)
rgb = cv.cvtColor(frame, cv.COLOR_BGR2RGB)
result = detection(rgb)
out.write(result)
c = cv.waitKey(10)
if c == 27:
break
else:
break
cv.destroyAllWindows()更詳細(xì)的關(guān)于MTCNN可以看推薦閱讀
運(yùn)行效果
balvin與我
交流群
歡迎加入公眾號讀者群一起和同行交流,目前有SLAM、三維視覺、傳感器、自動駕駛、計算攝影、檢測、分割、識別、醫(yī)學(xué)影像、GAN、算法競賽等微信群(以后會逐漸細(xì)分),請掃描下面微信號加群,備注:”昵稱+學(xué)校/公司+研究方向“,例如:”張三 + 上海交大 + 視覺SLAM“。請按照格式備注,否則不予通過。添加成功后會根據(jù)研究方向邀請進(jìn)入相關(guān)微信群。請勿在群內(nèi)發(fā)送廣告,否則會請出群,謝謝理解~





