最近一直在做3D人脸鼻尖识别项目,因为之前没有相关经验,所以前后花了一个半月才做完。
在此记录一下自己的思路:
1.读取人脸点云数据,代码为Matlab代码:
clc;
read_file = importdata('C:\myfiles\xyz\test1\test3\3.xyz'); %读取文件
file_x = read_file(:,1);
file_y = read_file(:,2);
file_z = read_file(:,3);
set(figure,'name','点云');
plot3(file_x,file_y,file_z,'.')
显示的点云:
2.对人脸数据做插值处理,这里直接做的网格化。
[X,Y,Z] = griddata(file_x,file_y,file_z,linspace(min(file_x),max(file_x),200)',linspace(min(file_y),max(file_y),20),'cubic'); %插值
set(figure,'name','网格');
surf(Z); %显示三维曲面
网格化:
3.对每个Y轴的切片做半圆相交处理(这里我选择用半圆,因为人脸的俯视图是凹的,这跟深度摄像头采集的数据有关,FRGC数据集里面的人脸俯视图是凸的),圆心在切片上滑动,半径采用固定值(我用的是30),相交得到两个交点,计算这两个点和圆心组成的三角形中,以这两个点为底的三角形高H。H的值就是鼻尖置信点的值
这里我写了一个演示代码,方便大家理解这个在切片上做圆,找鼻尖置信点的过程:
% 单层切片遍历所有点,标出鼻尖置信点和两个交点
clc;
read_file = importdata('C:\myfiles\xyz\test1\test3\3.xyz'); %读取文件
file_x = read_file(:,1);
file_y = read_file(:,2);
file_z = read_file(:,3);
% set(figure,'name','点云');
% plot3(file_x,file_y,file_z,'.')
[X,Y,Z] = griddata(file_x,file_y,file_z,linspace(min(file_x),max(file_x),200)',linspace(min(file_y),max(file_y),20),'cubic'); %插值
% set(figure,'name','网格');
% surf(Z); %显示三维曲面
xz = Z(13,:); %获取水平切片,这里的13是自己随便取的一层切片
x = 1:200;
yqu = xz(1,x);
set(figure,'name','切片');
plot(x,yqu);
%画圆
I = find(~isnan(xz)); %获取水平切片非空位置
[x_s,~] = min(I); %水平切片有效起始位置
[x_e,~] = max(I); %水平切片有效终止位置
%r = round((x_e-x_s)/5); %自适应因切圆半径(效果并不好)
r = 30; %指定切圆的半斤,效果更好
h_gaos = []; %切片中每个点作为圆心和切片形成的交点所形成的三角形的高集合
for x1 = x_s+r:x_e-r %圆心的可取值范围
if x1>1 %避免水平切片太小
z1 = xz(1,x1); %切片中对应z的坐标
i = x1-r:x1+r; %圆心的取值范围
y2 = sqrt(r.^2-(i-x1).^2)+z1; %切圆的z坐标(上半圆)
y = xz(1,i);
cy = y2-y;
pos = cy>0;
neg = cy<=0;
%确定变号位置
fro = diff(pos)~=0; %变号的前导位置
rel = diff(neg)~=0; %变号的尾巴位置
zpf = find(fro==1); %记录索引
zpr = find(rel==1)+1; %记录索引
zpfr = [zpf,zpr];
x0 = (i(zpr).*(y2(zpf)-y(zpf))-i(zpf).*(y2(zpr)-y(zpr)))./(y(zpr)+y2(zpf)-y(zpf)-y2(zpr));
y0 = y(zpf)+(x0-i(zpf)).*(y(zpr)-y(zpf))./(i(zpr)-i(zpr)-i(zpf));
x0 = [x0 x0].';
y0 = [y0 y0].';
jie = unique(