原文地址:http://blog.youkuaiyun.com/xiamentingtao/article/details/47307017
SDM For Face Alignment 流程介绍及Matlab代码实现之训练篇
SDM 训练阶段的任务如下:
- 载入标准化的数据(包括400*400的正脸及特征点)
- 对每一张标准化的图片,模拟人脸检测仪,产生10个扰动的人脸框及相应的初始特征点 x0 。
- 求解 Δx , Φ ,其中 Δx=x∗−x0 , x∗ 表示true shape, Φ 表示每个特征点的特征向量
- 求解最小二乘问题,得到一系列 {Rk}
下面分别来说明:
载入数据
载入811个训练数据,按照上一章预备篇关于第一幅图片的裁剪方法裁剪这811张图片。
matlab代码如下:
function
[Data] = load_single_data2 ( dbpath_img, dbpath_pts,image_index, options )%% output format%{DATA.- width_orig: the width of the original image.- height_orig: the height of the original image.- img_gray: the crop image.- height: the height of crop image.- wdith: the width of crop image.- shape_gt: ground-truth landmark.- bbox_gt: bounding box of ground-truth.%}slash = options.slash;dbname = options.datasetName;imlist = dir([dbpath_img slash
'*.*g'
]); %% load images img = im2uint8(imread([dbpath_img slash imlist(image_index).name])); Data.width_orig = size(img,
2
); Data.height_orig = size(img,
1
); %% load shape Data.shape_gt = double(annotation_load(
...
[dbpath_pts slash imlist(image_index).name(
1
:end-
3
)
'pts'
] , dbname));
if
0
figure(
1
); imshow(img); hold on; draw_shape(Data.shape_gt(:,
1
),
...
Data.shape_gt(:,
2
),
'y'
); hold off; pause; end %% get bounding box Data.bbox_gt = getbbox(Data.shape_gt); %% enlarge region of face region = enlargingbbox(Data.bbox_gt,
2.0
); region(
2
) = double(max(region(
2
),
1
));%这里主要是为了防止求出的包围盒超过图像,因此一旦超过,则region(
2
)必然小于
0
,因此此时取
1
即可。 region(
1
) = double(max(region(
1
),
1
)); bottom_y = double(min(region(
2
) + region(
4
) -
1
,
...
Data.height_orig)); right_x = double(min(region(
1
) + region(
3
) -
1
,
...
Data.width_orig));%防止长和宽超过图片大小,因此取二者最小值 img_region = img(region(
2
):bottom_y, region(
1
):right_x, :);%取人脸区域 %% recalculate(重新计算) the location of groundtruth shape and bounding box Data.shape_gt = bsxfun(@minus, Data.shape_gt,
...
double([region(
1
) region(
2
)]));%等价于Data{iimgs}.shape_gt-
repeat
( double([region(
1
) region(
2
)]),size(Data{iimgs}.shape_gt,
1
),
1
) %将图像的坐标原点移到人脸包围盒的左上角,并因此得以重新计算新的特征点 Data.bbox_gt = getbbox(Data.shape_gt);%新的特征点的包围盒的左上角坐标发生了改变,但是宽和高没有变化
if
size(img_region,
3
) ==
1
Data.img_gray = img_region;
else
Data.img_gray = rgb2gray(img_region); end Data.width = size(img_region,
2
); Data.height = size(img_region,
1
);
if
0
figure(
2
); imshow(Data.img_gray); hold on; draw_shape(Data.shape_gt(:,
1
),
...
Data.shape_gt(:,
2
),
'y'
); hold off; pause; end %% normalized the image to the mean-shape sr = options.canvasSize(
1
)/Data.width; sc = options.canvasSize(
2
)/Data.height; Data.img_gray = imresize(Data.img_gray,options.canvasSize); Data.width = options.canvasSize(
1
); Data.height = options.canvasSize(
2
); Data.shape_gt = bsxfun(@times, Data.shape_gt, [sr sc]); Data.bbox_gt(
1
:
2
) = bsxfun(@times, Data.bbox_gt(
1
:
2
), [sr sc]);%补充 Data.bbox_gt(
3
:
4
) = bsxfun(@times, Data.bbox_gt(
3
:
4
), [sr sc]);%补充
if
0
figure(
3
); imshow(Data.img_gray); hold on; draw_shape(Data.shape_gt(:,
1
),
...
Data.shape_gt(:,
2
),
'r'
); hold on; rectangle(
'Position'
, Data.bbox_gt,
'EdgeColor'
,
'k'
); pause; end end
function
region = enlargingbbox(bbox, scale)%同前面一样,初始时刻这里得到仅仅是特征点盒子,而我们如果想要包住整个人脸,就必须先将原始盒子的左上角平移一半的宽高,然后再放大两倍。这个在前面求解%rect = get_correct_region( boxes, shape,Dataa(i).img,
1
);中也用到过%因此这里得到的盒子是包住全部人脸的盒子。 region(
1
) = floor(bbox(
1
) - (scale -
1
)/
2
*bbox(
3
));region(
2
) = floor(bbox(
2
) - (scale -
1
)/
2
*bbox(
4
));region(
3
) = floor(scale*bbox(
3
));region(
4
) = floor(scale*bbox(
4
));end