图像局部缩放算法
// - 公式 :
// - 按照公式代码实现
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;
}