图像处理算法之瘦脸及放大眼睛

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013085897/article/details/70232797
       现在很多图像美颜app,处理后不但使人物皮肤变得平滑、白皙,还会稍微瘦下脸、放大眼睛,给人眼前一亮的感觉。这其中涉及人脸检测及特征点提取算法,一般提取68个特征点就足够了,同时也涉及图像局部变形算法。这也是两个研究方向,前者主要是计算机视觉,后者是图像处理。但随着深度学习的大热及在多个领域的成功应用,很多图像处理技术也开始采用深度学习算法实现突破,比如基于深度学习的降噪、超分辨率、非真实感绘制等等技术。深度学习大有在计算机视觉、图像处理一统之态势。言归正传,本文主要还是介绍瘦脸及放大眼睛所用到的图像局部变形算法。主要参考:交互式图像变形算法一文 。看过该文章后,自然了解瘦脸其实用的是图像局部平移变形,放大眼睛,用的是图像局部缩放变形。同时,文章还阐述了图像局部旋转变形的算法原理及思路。
       瘦脸及放大眼睛的前提是需要检测到人脸,并提取特征点。谈到图像变形,最基础的思路是:由变形前坐标,根据变形映射关系,得到变形后坐标。这其中变形映射关系是最关键的,不同的映射关系,将得到不同的变形效果。平移、缩放、旋转,对应的是不同的映射关系,即不同的变换公式。当然实际在计算过程中,用的是逆变换,即由变形后坐标,根据逆变换公式反算变形前坐标,然后插值得到该坐标rgb像素值,将该rgb值作为变形后坐标对应的像素值。这样才能保证变形后的图像是连续、完整的。

       下面简单讲一下图像局部平移变形,该变形稍微复杂一些,公式如下:

                                       

       公式中,由于主要是像素点位置计算,因此涉及一些矢量运算,不过比较简单。其实上面公式就是逆变换公式了,x是变换后的位置,u是原坐标位置。整个计算在以c为圆心,r为半径的圆内进行。因为是交互式图像局部变形,所以c也可以看做鼠标点下时的坐标,而m为鼠标移动一段距离后抬起时的坐标,这样c和m就决定了变形方向。下面是示例代码,公式结合代码一起看,应该很快能弄明白。
void LocalTranslationWarp(Mat &img, int warpX, int warpY, int warpW, int warpH, int directionX, int directionY, double warpCoef)
{
	RestrictBounds(warpX, warpY, warpW, warpH);

	Mat imgCopy;
	copyMakeBorder(img, imgCopy, 0, 1, 0, 1, BORDER_REPLICATE);

	Point center(warpX + (warpW>>1), warpY + (warpH>>1));
	double radius = (warpW < warpH) ? (warpW >> 1) : (warpH >> 1);
	radius = radius * radius;

	// 平移方向矢量/模
	double transVecX = directionX - center.x;
	double transVecY = directionY - center.y;
	double transVecModel = transVecX*transVecX + transVecY*transVecY;

	// 水平/垂直增量//映射后位置与原位置
	double dx = 0, dy = 0, posX = 0.0, posY = 0.0, posU = 0.0, posV = 0.0;
	// 点到圆心距离/平移比例
	double distance = 0.0, ratio = 0.0;
	// 插值位置
	int startU = 0, startV = 0;
	double alpha = 0.0, beta = 0.0;

	int maxRow = warpY + warpH;
	int maxCol = warpX + warpW;
	uchar* pImg = NULL;
	for (int i = warpY; i < maxRow; i++)
	{
		pImg = img.data + img.step * i;
		for (int j = warpX; j < maxCol; j++)
		{
			posX = j;
			posY = i;
			dx = posX - center.x;
			dy = posY - center.y;
			distance = dx*dx + dy*dy;
			if (distance < radius)
			{
				ratio = (radius - distance) / (radius - distance + transVecModel * warpCoef);
				posU = posX - ratio * ratio * transVecX;
				posV = posY - ratio * ratio * transVecY;

				startU = (int)posU;
				startV = (int)posV;
				alpha = posU - startU;
				beta  = posV - startV;
				BilinearInter(imgCopy, startU, startV, alpha, beta, pImg[3*j], pImg[3*j + 1], pImg[3*j + 2]);
			}
		}
	}
}
       可以看到,只有圆形选区内的图像才进行变形。越靠近圆心,变形越大,反之变形越小。对于图像缩放变形及旋转变形,公式比较简单,实现起来也容易一些,本文就不在详细讲解了。应用上面算法,简单的瘦脸效果如下:
    

       
       参考文献:



没有更多推荐了,返回首页

私密
私密原因:
请选择设置私密原因
  • 广告
  • 抄袭
  • 版权
  • 政治
  • 色情
  • 无意义
  • 其他
其他原因:
120
出错啦
系统繁忙,请稍后再试

关闭