本項目部分基于這個博客Computer Vision for Predicting Facial Attractiveness韵吨。按照上面這個博客復(fù)現(xiàn)起來比較麻煩(當(dāng)然是對我而言)逾礁,而且我想要做的是對于任意一張人臉進(jìn)行檢測之后都可以進(jìn)行顏值估計,但是他給出的代碼還需要進(jìn)行改動不少才行∪崽希現(xiàn)在就把自己的復(fù)現(xiàn)過程記錄下來。
本文中只展示了部分關(guān)鍵代碼萍虽。完整代碼和測試用的數(shù)據(jù)可以在GitHub上獲取睛廊。
不同點(diǎn)
- 在提取人臉關(guān)鍵點(diǎn)的時候,原文中提到用的是CLM framework杉编,本文用的是之前配置好的Dlib喉前。
- 實(shí)現(xiàn)了對自選圖片中人臉的顏值估計
用到的Python庫
- numpy
- opencv
- dlib
- sklearn
主要步驟
- 訓(xùn)練模型
- 人臉關(guān)鍵點(diǎn)提取
- 特征生成
- 顏值預(yù)測
1. 訓(xùn)練模型
訓(xùn)練一個模型最重要的就是輸入數(shù)據(jù)和模型的選取。這里訓(xùn)練模型用到的輸入數(shù)據(jù)是給出的features_All.txt和rating.txt王财。這是華南理工大學(xué)人機(jī)智能交互實(shí)驗室給出的數(shù)據(jù)集中提取出來的特征和標(biāo)簽卵迂。一共用了500幅人臉圖像。
root = 'E:/Github/predict-facial-attractiveness/'
features = np.loadtxt(root + 'data/features_ALL.txt', delimiter=',')
#features = preprocessing.scale(features)
features_train = features[0:-50]
features_test = features[-50:]
pca = decomposition.PCA(n_components=20)
pca.fit(features_train)
features_train = pca.transform(features_train)
features_test = pca.transform(features_test)
ratings = np.loadtxt(root + 'data/ratings.txt', delimiter=',')
#ratings = preprocessing.scale(ratings)
ratings_train = ratings[0:-50]
ratings_test = ratings[-50:]
- 值得注意的是绒净,這里用PCA算法對特征進(jìn)行了壓縮和降維见咒。降維之后特征變成了20維,也就是說特征一共有500行挂疆,每行是一個人的特征向量改览,每個特征向量有20個元素。
根據(jù)Computer Vision for Predicting Facial Attractiveness一文中給出的結(jié)果缤言,我們選取表現(xiàn)最好的模型之一——隨機(jī)森林作為此次復(fù)現(xiàn)用的算法模型宝当。
regr = RandomForestRegressor(n_estimators=50, max_depth=None, min_samples_split=1, random_state=0)
regr = regr.fit(features_train, ratings_train)
#一定要把conpress設(shè)為true或者其他的值,沒有設(shè)置會輸出很多的*.pkl
joblib.dump(regr, root + 'model/my_face_rating.pkl',compress=1)
print "Generate Model Successfully!"
- 用隨機(jī)森林訓(xùn)練模型胆萧。因為想要預(yù)測自選圖片的人臉顏值庆揩,所以要把模型保存下來以備后用俐东。
2. 人臉關(guān)鍵點(diǎn)提取
在之前的博客OpenCV實(shí)踐之路——用dlib庫進(jìn)行人臉檢測與人臉標(biāo)記中已經(jīng)提到過如何進(jìn)行人臉關(guān)鍵點(diǎn)提取,這里的工作基于之前的內(nèi)容订晌,不同之處在于要把提取到的關(guān)鍵點(diǎn)按照模型可以用的方式進(jìn)行保存虏辫。部分代碼如下:
f = open(root + 'data/landmarks.txt','w')
for i in range(len(rects)):
使用predictor進(jìn)行人臉關(guān)鍵點(diǎn)識別
landmarks = numpy.matrix([[p.x,p.y] for p in predictor(im,rects[i]).parts()])
im = im.copy()
#使用enumerate 函數(shù)遍歷序列中的元素以及它們的下標(biāo)
for idx,point in enumerate(landmarks):
pos = (point[0,0],point[0,1])
f.write(str(point[0,0]))
f.write(',')
f.write(str(point[0,1]))
f.write(',')
#cv2.putText(im,str(idx),pos,
#6.繪制特征點(diǎn)
cv2.circle(im,pos,3,color=(0,255,0))
f.write('\n')
print "landmarks,get!"
3. 特征生成
特征生成直接用了原始代碼,只對路徑進(jìn)行了一些改動锈拨。這一部分我暫時也不太明朗砌庄,所以不敢多說。有興趣的還是直接看代碼吧奕枢。篇幅原因娄昆,這里只是部分代碼,特征生成的完整代碼在這里缝彬。
def generateFeatures(pointIndices1, pointIndices2, pointIndices3, pointIndices4, allLandmarkCoordinates):
size = allLandmarkCoordinates.shape
allFeatures = numpy.zeros((size[0], len(pointIndices1)))
for x in range(0, size[0]):
landmarkCoordinates = allLandmarkCoordinates[x, :]
ratios = [];
for i in range(0, len(pointIndices1)):
x1 = landmarkCoordinates[2*(pointIndices1[i]-1)]
y1 = landmarkCoordinates[2*pointIndices1[i] - 1]
x2 = landmarkCoordinates[2*(pointIndices2[i]-1)]
y2 = landmarkCoordinates[2*pointIndices2[i] - 1]
x3 = landmarkCoordinates[2*(pointIndices3[i]-1)]
y3 = landmarkCoordinates[2*pointIndices3[i] - 1]
x4 = landmarkCoordinates[2*(pointIndices4[i]-1)]
y4 = landmarkCoordinates[2*pointIndices4[i] - 1]
points = [x1, y1, x2, y2, x3, y3, x4, y4]
ratios.append(facialRatio(points))
allFeatures[x, :] = numpy.asarray(ratios)
return allFeatures
4. 顏值預(yù)測
到了這一步稿黄,我們就可以用第一步得到的模型和上一步得到的特征進(jìn)行顏值的估計了。
#use your own path
root = 'E:/Github/predict-facial-attractiveness/'
clf = joblib.load(root+'model/my_face_rating.pkl')
features = np.loadtxt(root + 'data/features_ALL.txt', delimiter=',')
my_features = np.loadtxt(root + 'data/my_features.txt', delimiter=',')
pca = decomposition.PCA(n_components=20)
pca.fit(features)
predictions = np.zeros([6,1]);
for i in range(0, 6):
features_test = features[i, :]
features_test = pca.transform(features_test)
#regr = linear_model.LinearRegression()
#regr.fit(features_train, ratings_train)
predictions[i] = clf.predict(features_test)
#predictions = clf.predict(features)
print predictions
- 這里有一點(diǎn)需要注意:一定要用原來的特征進(jìn)行PCA的fit跌造,因為自己的圖片提取的只有六個特征杆怕,而PCA要壓縮成20維,根本沒法壓縮壳贪,所以先用原本的特征進(jìn)行PCA的fit陵珍,這樣即使只有一個特征,也可以降維到20列违施。否則會出錯互纯。
仍然用這張圖片測試
結(jié)果如下圖所示,可能是因為訓(xùn)練的時候用的都是亞洲女性的圖片磕蒲,所以測試歐美女性的時候有一些偏差留潦,本結(jié)果只是測試結(jié)果,不說明任何問題辣往。
- 滿分5分