BFM使用 - 獲取平均臉模型的68個特徵點座標

使用版本: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=downloadsphp

使用Matlab導入01_MorphableModel.matpython

load('解壓目錄\01_MorphableModel.mat')


160470=53490*3,即形狀(Shape)\(S=(x_1, y_1, z_1, ..., x_n, y_n, z_n)\)
包含內容:git

  • segbin:猜是segment binary,用熱點法標註屬於面部哪一部分。
  • shapeEV:形狀方差;
  • shapeMU(160470*1):平均形狀;
  • shapePC:形狀的主成分;
  • texEV:紋理方差;
  • texMU:平均紋理
  • texPC:紋理的主成分;

新建一個Matlab腳本,輸入以下代碼:github

shape = reshape(shapeMU, 3, 53490)
shape = shape.'
x = shape(:, 1)
y = shape(:, 2)
z = shape(:, 3)
scatter3(x,y,z, 1, 'filled');

該代碼將本來一行的形狀向量轉換爲n*3的矩陣,而後將其在三維座標系下畫出來,咱們能夠看到顯示如圖人臉。
app

官方提供的landmark對應關係格式以下(Farkas_face05.fp):spa

# 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矩陣當中:code

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文件,並進行打印:orm

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

顯示效果圖以下
blog

由於咱們最終想經過與dlib提供的68個點進行擬合,所以不能使用這種方法獲得的特徵點。
這邊找到了Github上有人提供的68個特徵點在BFM上的對應關係:https://github.com/anilbas/BFMLandmarks
咱們將其中的Landmarks68_BFM.anl文件內的68個下標導入Matlab而後更新代碼:ip

% 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位特徵點座標了。

相關文章
相關標籤/搜索