啰唆幾句
最近在研究人臉探測,人臉驗證,人臉識別。在理論知識補充后就是要自己動手寫code了。在寫code之前基于不做“重復(fù)工作”的懶人思想在網(wǎng)上搜索了下現(xiàn)有的人臉識別開源項目,在對比過幾種方法后發(fā)現(xiàn)了face_recognition這個項目,該項目使用dlib作為人臉探測,而在face_recognition中也提供了兩種探測方式:HOG和CNN。探測到人臉后提取128維面部特征,這128維的數(shù)據(jù)作為一個unknown的嵌入(embedding)和已知(標(biāo)記)的嵌入進行相似度比較,在接受的閾值范圍內(nèi)認定是同一個人,雖然其頁面上沒有詳細說明是怎樣判定距離的,從其程序運行反饋的一些結(jié)果上我猜測是使用了Siamese network。face_recognition雖然使用十分簡單,但還是有一些概念需要提一下:
- HOG
剛才已經(jīng)提到HOG是face_recognition使用的一種面部探測的方式,HOG是Histogram of Oriented Gradients的簡稱也就是方向梯度直方圖。 - CNN
基于卷積神經(jīng)網(wǎng)絡(luò)的探測臉的方式原則上會比HOG的準(zhǔn)確度高,其原理我會記錄在后續(xù)的理論文章中,大致理解就是使用一個bounding box去掃描整張圖片并查看每一個bounding box中是否有目標(biāo)對象 - 其他
除了上述兩種人臉探測的方式還有不少其他的方式比如opencv中所采用的Haar Cascades,其實用了adaboost的方法來分類(熟悉機器學(xué)習(xí)的朋友會心一笑,懂了。。。),但其效果理論上是比不上CNN的。當(dāng)然也有更精確的人臉探測方式Multi-task CNN,在git上也有其python的實現(xiàn)facenet。
實現(xiàn)步驟
啰嗦了這么多我們來看下怎么快速的實現(xiàn)一個人臉識別
- dlib
dlib是關(guān)鍵,ubuntu和win上的安裝很簡單,先說ubuntu吧- ubuntu
apt-get install -y --fix-missing
build-essential
cmake
gfortran
git
wget
curl
graphicsmagick
libgraphicsmagick1-dev
libatlas-dev
libavcodec-dev
libavformat-dev
libgtk2.0-dev
libjpeg-dev
liblapack-dev
libswscale-dev
pkg-config
python3-dev
python3-numpy
software-properties-common
zip
&& apt-get clean
這樣dlib所需的Cmake和boost就安裝好了
mkdir -p dlib
git clone -b 'v19.9' --single-branch https://github.com/davisking/dlib.git dlib/
cd dlib
python setup.py install --yes USE_AVX_INSTRUCTIONS
以上就在ubuntu的環(huán)境中安裝好了dlib,可以進入python 然后import dlib嘗試下。
- win
mkdir CMAKE
cd CMAKE
cmake -G "Visual Studio 14 2015 Win64" -T host=x64 ..
cmake --build . --config Release
然后下載dlib,進入其folder
python setup.py install
在dlib安裝好以后安裝face_recognition
pip install face_recognition
開始人臉識別
import face_recognition
from PIL import Image, ImageDraw
#已知(標(biāo)記)人臉照片讀取
1_image = face_recognition.load_image_file("1.jpg")
1_face_encoding = face_recognition.face_encodings(1_image)[0]
2_image = face_recognition.load_image_file("2.jpg")
2_face_encoding = face_recognition.face_encodings(2_image)[0]
#embedding
known_face_encodings = [
1_face_encoding,
2_face_encoding
]
known_face_names = [
"張三",
"李四"
]
#輸入未標(biāo)記的照片
unknown_image = face_recognition.load_image_file("unknown.jpg")
unknown_face_locations = face_recognition.face_locations(unknown_image)
# unknown_face_locations = face_recognition.face_locations(unknown_image,number_of_times_to_upsample=0, model="cnn")如果電腦有N卡并安裝了cuda,使用cnn
unknown_face_encodings = face_recognition.face_encodings(unknown_image, unknown_face_locations)
pil_image = Image.fromarray(unknown_image)
draw = ImageDraw.Draw(pil_image)
# 探測人臉并和已知人臉比對
for (top, right, bottom, left), unknown_face_encoding in zip(unknown_face_locations, unknown_face_encodings):
matches = face_recognition.compare_faces(known_face_encodings, unknown_face_encoding,tolerance=0.4)
# distance = face_recognition.face_distance(known_face_encodings, unknown_face_encoding)
print(matches)
name = "Unknown"
if True in matches:
first_match_index = matches.index(True)
name = known_face_names[first_match_index]
#if 之后代碼部分能優(yōu)化成選取distance小于tolerance中的最小的一個值
#draw bounding box并標(biāo)記
draw.rectangle(((left, top), (right, bottom)), outline=(0, 0, 255))
text_width, text_height = draw.textsize(name)
draw.rectangle(((left, bottom - text_height - 10), (right, bottom)), fill=(0, 0, 255), outline=(0, 0, 255))
draw.text((left + 6, bottom - text_height - 5), name, fill=(255, 255, 255, 255))
del draw
pil_image.show()
上述就實現(xiàn)了一個人臉識別,由于手頭素材涉及同事照片就不把識別結(jié)果分享出來了,我個人實現(xiàn)的實際效果還不錯。