使用版本:2009
數據說明網址:https://faces.dmi.unibas.ch/bfm/index.php?nav=1-1-0&id=details
數據下載網址:https://faces.dmi.unibas.ch/bfm/index.php?nav=1-2&id=downloads
使用Matlab導入01_MorphableModel.mat
load('解壓目錄\01_MorphableModel.mat')
160470=53490*3,即形狀(Shape)\(S=(x_1, y_1, z_1, ..., x_n, y_n, z_n)\)
包含內容:
- segbin:猜是segment binary,用熱點法標注屬於面部哪一部分。
- shapeEV:形狀方差;
- shapeMU(160470*1):平均形狀;
- shapePC:形狀的主成分;
- texEV:紋理方差;
- texMU:平均紋理
- texPC:紋理的主成分;
新建一個Matlab腳本,輸入如下代碼:
shape = reshape(shapeMU, 3, 53490)
shape = shape.'
x = shape(:, 1)
y = shape(:, 2)
z = shape(:, 3)
scatter3(x,y,z, 1, 'filled');
該代碼將原本一行的形狀向量轉換為n*3的矩陣,然后將其在三維坐標系下畫出來,我們可以看到顯示如圖人臉。
官方提供的landmark對應關系格式如下(Farkas_face05.fp):
# Feature Points
# Filename: /net/faces/projects/model200/fps/new_farkas/face05_farkas.fp
# Format: (vertex_nr) (x y z) (x y) (name)
19963 -88262.2 36394.8 -4947.64 0 0 sa
20205 -71257.4 -20598.4 13258.3 0 0 sba
21629 -77516 30127.9 12058.9 0 0 pra
...
因此我們通過一個python腳本讀取其中的三維點信息並保存到mat矩陣當中:
import scipy.io as scio
file = open("Farkas_face05.fp")
landmarks = []
while True:
line = file.readline()
if not line:
break
if line[0] < '0' or line[0] > '9':
continue
args = line.split()
coord = [float(args[1]), float(args[2]), float(args[3])]
landmarks.append(coord)
scio.savemat('landmarks.mat', {'landmarks': landmarks})
隨后從Matlab中讀取這個mat文件,並進行打印:
scatter3(x,y,z,2, 'filled');
hold on;
for i = 1:70
scatter3(landmarks(i,1), landmarks(i,2), landmarks(i,3),10, 'r');
end
顯示效果圖如下
因為我們最終想通過與dlib提供的68個點進行擬合,因此不能使用這種方法得到的特征點。
這邊找到了Github上有人提供的68個特征點在BFM上的對應關系:https://github.com/anilbas/BFMLandmarks
我們將其中的Landmarks68_BFM.anl文件內的68個下標導入Matlab然后更新代碼:
% tmp存儲了Landmarks68_BFM.anl中的68個下標
scatter3(x,y,z,2, 'filled');
hold on;
for i = 1:68
scatter3(x(tmp(i)), y(tmp(i)), z(tmp(i)),10, 'r');
end
顯示結果如下:
這便是我們想要得到的68個點,最后我們把這68個點的坐標導出到本地:
landmarks = zeros(68,3);
for i = 1:68
landmarks(i, :) = [x(tmp(i)), y(tmp(i)), z(tmp(i))];
end
save landmarks landmarks
這樣我們就可以在后續的代碼中通過導入landmarks.mat來獲取標准臉的68位特征點坐標了。