图像算法

这篇博客探讨了两种图像处理算法:局部缩放和局部平移,用于实现人脸美化,特别是大眼和瘦脸效果。通过数学公式和GLSL着色器代码,详细解释了如何在图像的特定区域(如眼睛周围)进行局部调整,以达到放大眼睛和瘦脸的目的。这些算法基于关键点检测和距离权重函数,实现了自然且细腻的图像变换效果。
摘要由CSDN通过智能技术生成

图像局部缩放算法

// - 公式 :
在这里插入图片描述
// - 按照公式代码实现

precision mediump float;

varying vec2 aCoord; // - 纹理坐标
uniform sampler2D vTexture; // - 纹理采样器

uniform float a; // - 缩放系数

uniform vec2 left_eye_center; // - 左眼中心
uniform vec2 right_eye_center; // - 右眼中心

// - 图像局部缩放算法实现
// - coord : 改变前的纹理坐标; eye : 眼睛的中心点坐标;
vec2 newCoord(vec2 coord, vec2 eye, float rmax){

	// - 采样的点
	vec2 newCoord = coord;

	// - 点到眼睛的距离
	float r = distacne(coord, eye);

	if(r < rmax){// - 在缩放半径内
		
		// - 局部缩放算法公式 如图
		float fsr = (1 - pow(r / ramx - 1.0, 2.0) * a);

		// - 公式转换 (newCoord - eye) / (coord - eye) = fsr / r;
		newCoord = fsr * (coord - eye) + eye;
	}
	return newCoord;
}

// - 函数入口
void main(){

	// - 最大作用半径
	float rmax = distance(left_eye_center, right_eye_center) / 2.0;

	// - 坐标转换
	vec2 p = newCoord(aCoord, left_eye_center, rmax);
	p = newCoord(p, right_eye_center, rmax);

	// - 输出的颜色
	gl_FragmentColor = texture2D(vTexture, p);
}

// - 项目中代码实现

  // - 局部缩放
  vec2 enlargeEye(vec2 textureCoord, vec2 originPosition, float radius, float delta) {
      
     float weight = distance(vec2(textureCoord.x, textureCoord.y / aspectRatio), vec2(originPosition.x, originPosition.y / aspectRatio)) / radius;

     weight = 1.0 - (1.0 - (weight * weight)) * delta;
     weight = clamp(weight,0.0,1.0);
     textureCoord = originPosition + (textureCoord - originPosition) * weight;
     return textureCoord;
  }

// - 代码实现
  vec2 bigEye(vec2 currentCoordinate) {
     
     // - 眼睛的关键点序号, 左眼 : left_eye_top -> 72 和  left_eye_center -> 74; 右眼 : right_eye_top -> 75 和 right_eye_center -> 77;
     int left_eye_top = 68;
     int left_eye_center = 74;
     int right_eye_top = 77;
     int right_eye_center = 83;
     
     // - left_eye_top 的坐标
     vec2 left_eye_top_point = vec2(facePoints[left_eye_top * 2], facePoints[left_eye_top * 2 + 1]);
     
     // - left_eye_center 的坐标
     vec2 left_eye_center_point = vec2(facePoints[left_eye_center * 2], facePoints[left_eye_center * 2 + 1]);

     // - right_eye_top 的坐标
     vec2 right_eye_top_point = vec2(facePoints[right_eye_top * 2], facePoints[right_eye_top * 2 + 1]);
     
     // - right_eye_center 的坐标
     vec2 right_eye_center_point = vec2(facePoints[right_eye_center * 2], facePoints[right_eye_center * 2 + 1]);
     
     // - 左眼的放大半径
     float left_radius = distance(vec2(left_eye_top_point.x, left_eye_top_point.y / aspectRatio), vec2(left_eye_center_point.x, left_eye_center_point.y / aspectRatio));
     
     // - 右眼的放大的半径
     float right_radius = distance(vec2(right_eye_top_point.x, right_eye_top_point.y / aspectRatio), vec2(right_eye_center_point.x, right_eye_center_point.y / aspectRatio));
     
     // - 扩大半径, 否则大眼的半径就只有眼睛的位置, 应该是眼睛周边都放大一点
    float multiple = 4.5;
     
     // - 使用圆内放大的算法 放大左眼和右眼
     currentCoordinate = enlargeEye(currentCoordinate, left_eye_center_point, left_radius * multiple, bigEyeDelta);
     currentCoordinate = enlargeEye(currentCoordinate, right_eye_center_point, right_radius * multiple, bigEyeDelta);

     return currentCoordinate;
  }

图像局部平移算法

// - 公式 :
在这里插入图片描述

// - 公式中的代码实现 :

precision mediump float;

varying vec2 aCoord; // - 纹理坐标
uniform sampler2D vTexture; // - 纹理采样器

uniform vec2 start; // - 缩放系数
uniform vec2 end; // - 缩放系数
uniform float rmax; // - 缩放系数

// - 图像局部平移算法实现
// - coord : 改变前的纹理坐标; start : 开始拉伸的点的坐标; end : 停止拉伸时候点的坐标;
vec2 translation(vec2 coord, vec2 start, vec2 end, float rmax){

	// - 采样的点
	vec2 newCoord = coord;

	// - 点间距
	float r = distance(coord, start);

	if(r < rmax){ // - 在最大作用半径内

		// - 局部平移算法
		float rmax2 = pow(rmax, 2.0);
		float num = rmax2 - pow(r, 2.0);
		float den = num + pow(distance(end, start), 2.0);
		newCoord = coord - pow(num / den, 2.0) * (end - start);
	}

	return newCoord;
}

// - 函数入口
void main(){

	// - 最大作用半径
	vec2 p = translation(aCoord, start, end, rmax);

	// - 输出的颜色
	gl_FragmentColor = texture2D(vTexture, p);
}

// - 项目中的代码实现

  // - 局部平移
  vec2 curveWarp(vec2 textureCoord, vec2 originPosition, vec2 targetPosition, float delta) {
      
      vec2 offset = vec2(0.0);
      vec2 result = vec2(0.0);
      vec2 direction = (targetPosition - originPosition) * delta;

      float radius = distance(vec2(targetPosition.x, targetPosition.y / aspectRatio), vec2(originPosition.x, originPosition.y / aspectRatio));
      float ratio = distance(vec2(textureCoord.x, textureCoord.y / aspectRatio), vec2(originPosition.x, originPosition.y / aspectRatio)) / radius;

      ratio = 1.0 - ratio;
      ratio = clamp(ratio, 0.0, 1.0);
      offset = direction * ratio;
      
      result = textureCoord - offset;
      
      return result;
  }

// - 函数入口
  vec2 thinFace(vec2 currentCoordinate) {

     // - 关键点数据 1 组
     int left_face_1 = 3;
     int right_face_1 = 29;
     int center_nose_1 = 52;
     
     // - 关键点数据 2 组
     int left_face_2 = 7;
     int right_face_2 = 25;
     int center_nose_2 = 53;
     
     // - 关键点数据 3 组
     int left_face_3 = 10;
     int right_face_3 = 22;
     int center_nose_3 = 54;
     
     // - 关键点数据 4 组
     int left_face_4 = 14;
     int right_face_4 = 18;
     int bottom_face_4 = 16;
     int center_nose_4 = 60;

     // - 关键点 1 组的坐标
     vec2 left_face_1_point = vec2(facePoints[left_face_1 * 2], facePoints[left_face_1 * 2 + 1]);
     vec2 right_face_1_point = vec2(facePoints[right_face_1 * 2], facePoints[right_face_1 * 2 + 1]);
     vec2 center_nose_1_point = vec2(facePoints[center_nose_1 * 2], facePoints[center_nose_1 * 2 + 1]);
     
     // - 关键点 2 组的坐标
     vec2 left_face_2_point = vec2(facePoints[left_face_2 * 2], facePoints[left_face_2 * 2 + 1]);
     vec2 right_face_2_point = vec2(facePoints[right_face_2 * 2], facePoints[right_face_2 * 2 + 1]);
     vec2 center_nose_2_point = vec2(facePoints[center_nose_2 * 2], facePoints[center_nose_2 * 2 + 1]);
     
     // - 关键点 3 组的坐标
     vec2 left_face_3_point = vec2(facePoints[left_face_3 * 2], facePoints[left_face_3 * 2 + 1]);
     vec2 right_face_3_point = vec2(facePoints[right_face_3 * 2], facePoints[right_face_3 * 2 + 1]);
     vec2 center_nose_3_point = vec2(facePoints[center_nose_3 * 2], facePoints[center_nose_3 * 2 + 1]);
     
     // - 关键点 4 组的坐标
     vec2 left_face_4_point = vec2(facePoints[left_face_4 * 2], facePoints[left_face_4 * 2 + 1]);
     vec2 right_face_4_point = vec2(facePoints[right_face_4 * 2], facePoints[right_face_4 * 2 + 1]);
     vec2 bottom_face_4_point = vec2(facePoints[bottom_face_4 * 2], facePoints[bottom_face_4 * 2 + 1]);
     vec2 center_nose_4_point = vec2(facePoints[center_nose_4 * 2], facePoints[center_nose_4 * 2 + 1]);
     
     // - 拉伸关键点 1 组
     currentCoordinate = curveWarp(currentCoordinate, left_face_1_point, center_nose_1_point, thinFaceDelta);
     currentCoordinate = curveWarp(currentCoordinate, right_face_1_point, center_nose_1_point, thinFaceDelta);

     // - 拉伸关键点 2 组
     currentCoordinate = curveWarp(currentCoordinate, left_face_2_point, center_nose_2_point, thinFaceDelta);
     currentCoordinate = curveWarp(currentCoordinate, right_face_2_point, center_nose_2_point, thinFaceDelta);

     // - 拉伸关键点 3 组
     currentCoordinate = curveWarp(currentCoordinate, left_face_3_point, center_nose_3_point, thinFaceDelta);
     currentCoordinate = curveWarp(currentCoordinate, right_face_3_point, center_nose_3_point, thinFaceDelta);

     // - 拉伸关键点 4 组
     currentCoordinate = curveWarp(currentCoordinate, left_face_4_point, center_nose_4_point, thinFaceDelta);
     currentCoordinate = curveWarp(currentCoordinate, right_face_4_point, center_nose_4_point, thinFaceDelta);
     currentCoordinate = curveWarp(currentCoordinate, bottom_face_4_point, center_nose_4_point, thinFaceDelta);
     
      return currentCoordinate;
  }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值