【计算机视觉】检测面切断和规范化
2015-10-10 20:09
295 查看
引子
要进行人脸的识别,尤其是复杂环境下的人脸识别,就要在捕获人脸图像之后对图像进行预处理的工作,如图像的大小和灰度的归一化,头部姿态的矫正,图像切割等。这样做的目的是改善图像质量,消除噪声,统一图像灰度值及尺寸,为后序特征提取和分类识别打好基础。该文将就人脸的剪切和归一化操作进行学习探讨。并做一笔记备用。
详细步骤
因为opencv的人脸识别须要输入图片具有同样的尺寸和灰度级。所以识别之前还要进行非常重要的一步工作。就是针对人脸识别的须要调整人脸图片,详细能够分为下面步骤:图片去噪
图片灰度化
人脸的剪切(crop)
调整图片大小(resize)
姿态旋转(rotate)
人脸剪切的策略
这里我设想的最主要的人脸剪切方法是依据人眼的位置进行人脸的旋转和校正的。基本思路例如以下:
依据两眼的倾斜角度对图像进行旋转校正
依据两眼在图片中的实际距离和自己定义的偏移量进行图片的缩放
以下是剪切的效果图,终于的图片是100*100像素,偏移量是0.3
Detecting Face
Cropping Result
其代码为:
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.3outputWidth,再减去右眼到右边界的0.3 outputWidth。
因为终于要做人脸识别。须要输出灰度图,所以。最后的返回值是经过灰度化而且直方图均衡化了的图片
图片旋转的API
这里图片旋转用到了OpenCV的函数。warpAffine()。这里涉及到了仿射变换,能够參考OpenCV官方文档,放射变换。
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矩阵。
转载请注明作者Jason Ding及其出处
Github主页(http://jasonding1354.github.io/)
CSDN博客(http://blog.csdn.net/jasonding1354)
简书主页(http://www.jianshu.com/users/2bd9b48f6ea8/latest_articles)
相关文章推荐
- Java基础知识强化之集合框架笔记72:集合特点和数据结构总结
- 4:虚幻引擎网络架构:技术要点总结篇
- Xocde7 https 问题
- 计算机基础知识(计算机概述)
- Linux网络编程---ICMP协议分析及ping程序实现
- TreeSet底层数据结构是二叉树
- 第5章 TCP服务器-客服端程序例子
- C语言数据结构-双链表
- DICOM:DICOM3.0网络通信协议(延续)
- The absolute uri: http://java.sun.com/jsp/jstl/core cannot be resolved in either web.xml or the jar
- 网络传输知识总结及AFNetworking使用心得
- 网络小白的自言自语
- spawn-fcgi 源码分析
- 网络攻击技术开篇——SQL Injection
- 网络编程
- 由于系统缓冲区空间不足或队列已满,不能执行套接字上的操作(MaxUserPort,TcpTimedWaitDelay)
- 站上历史浪潮的计算机(二)——图灵
- xcode7+ios9 访问网络提示错误解决办法
- Kubernetes用户指南(二)--部署组合型的应用、连接应用到网络中
- Kubernetes用户指南(二)--部署组合型的应用、连接应用到网络中