人脸crop

转载自:http://jasonding1354.github.io/2014/12/02/Machine%20Learning/【计算机视觉】对检测的人脸进行剪切和归一化/

人脸剪切的策略

这里我设想的最基本的人脸剪切方法是根据人眼的位置进行人脸的旋转和校正的。
基本思路如下:

  1. 根据两眼的倾斜角度对图像进行旋转校正
  2. 根据两眼在图片中的实际距离和自定义的偏移量进行图片的缩放

下面是剪切的效果图,最终的图片是100*100像素,偏移量是0.3
Detecting Face
Cropping Result
其代码为:

     
     
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
     
     
cv::Mat FaceClassifer::cropFacesBasedOnEye(cv::Rect faceRect,
cv::Point leftEye,cv::Point rightEye,
float offset, int outputWidth, int outputHeight)
{
int offset_h = floor(offset * outputWidth);
int offset_v = floor(offset * outputHeight);
int eyegap_h = rightEye.x-leftEye.x;
int eyegap_v = rightEye.y-leftEye.y;
float eye_distance = sqrt( pow(eyegap_h, 2)+ pow(eyegap_v, 2));
float eye_reference = outputWidth - 2*offset_h;
float scale = eye_distance/eye_reference;
//rotate original around the left eye
cv::Mat rotatedImage;
if(eyegap_v != 0)
{
double rotation = atan2f(( float)eyegap_v,( float)eyegap_h);
double degree = rotation* 180/CV_PI;
rotateFace(_image, leftEye, degree, rotatedImage);
}
//crop the rotated image
cv::Point crop_xy(leftEye.x-scale*offset_h,leftEye.y-scale*offset_v);
cv::Size crop_size(outputWidth*scale, outputHeight*scale);
cv::Rect crop_area(crop_xy, crop_size);
cv::Mat cropFace;
if(eyegap_v == 0)
cropFace = _image(crop_area);
else
cropFace = rotatedImage(crop_area);
//resize the face
cv::resize(cropFace,cropFace,cv::Size(outputWidth,outputHeight));
cv::Mat croppedGray;
cv::cvtColor(cropFace,croppedGray,CV_BGR2GRAY);
cv::equalizeHist(croppedGray, croppedGray);
return croppedGray;
}

解释一下代码:

  • 偏移量是指眼睛到图片上边界和左右边界的距离比例,比如0.3的偏移量,那么左眼到左边界,右眼到右边界的长度占所剪切的人脸图片宽度为0.3,同理到上边界的距离也占图片高度的0.3。
  • 根据两眼的实际距离和两眼依偏移量所应占据图片宽度的比例对图片进行缩放,比如实际距离是求一个欧式距离eye_distance,参考的距离eye_reference是输出的宽度outputWidth减去左眼到左边界的0.3 outputWidth,再减去右眼到右边界的0.3 outputWidth。
  • 由于最终要做人脸识别,需要输出灰度图,所以,最后的返回值是经过灰度化并且直方图均衡化了的图片

图片旋转的API

这里图片旋转用到了OpenCV的函数,warpAffine()。
这里涉及到了仿射变换,可以参考OpenCV官方文档,放射变换

     
     
1
2
3
4
5
     
     
void FaceClassifer::rotateFace(cv::Mat& src,cv::Point& pt, double angle,cv::Mat& dst)
{
cv::Mat r = cv::getRotationMatrix2D(pt, angle, 1.0);
cv::warpAffine(src, dst, r, cv::Size(src.cols,src.rows));
}

这里我以左眼的中心点作为旋转的输入原点,cv::getRotationMatrix2D()生成了表示仿射变换的2 * 3矩阵。


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值