基于opencv的人脸美颜 比图上新增大眼瘦脸功能 含40页算法讲解 送代码讲解(python语言)ppt讲解15页

最近在OpenCV项目里折腾人脸美颜,发现大眼瘦脸功能比想象中好玩。直接上干货——核心思路就是用面部关键点定位+局部形变。先来个人脸检测热热身:

import cv2
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
eye_cascade = cv2.CascadeClassifier('haarcascade_eye.xml')

img = cv2.imread('selfie.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)

for (x,y,w,h) in faces:
    roi_gray = gray[y:y+h, x:x+w]
    eyes = eye_cascade.detectMultiScale(roi_gray)
    # 在图上画出眼睛框(调试用)
    for (ex,ey,ew,eh) in eyes:
        cv2.rectangle(img,(x+ex,y+ey),(x+ex+ew,y+ey+eh),(0,255,0),2)

这段经典代码用哈尔特征做初步定位,但实际项目中建议换用Dlib的68点检测,精度更高(后文代码会展示)。关键点准了,后面形变才自然。

大眼魔法的核心代码:

def big_eyes(img, eye_points, scale=1.5):
    left_eye = eye_points[0]
    right_eye = eye_points[1]
    
    # 计算眼睛中心与半径
    radius_left = int(np.linalg.norm(left_eye[3] - left_eye[0])/2)
    radius_right = int(np.linalg.norm(right_eye[3] - right_eye[0])/2)
    
    # 创建局部放大蒙版
    mask = np.zeros_like(img)
    cv2.circle(mask, left_eye[0], radius_left, (255,255,255), -1)
    cv2.circle(mask, right_eye[0], radius_right, (255,255,255), -1)
    
    # 用径向基函数做变形(这里简化用缩放代替)
    center_left = left_eye[0]
    expanded_roi = cv2.resize(img[center_left[1]-radius:center_left[1]+radius, 
                                center_left[0]-radius:center_left[0]+radius], 
                            (0,0), fx=scale, fy=scale)
    # 把放大后的区域贴回原图(需要处理边缘融合)
    img = seamless_clone(expanded_roi, img, mask)
    return img

参数scale控制放大程度,1.5已经是比较明显的效果。重点在于边缘融合——直接贴图会有明显接缝,用OpenCV的泊松融合(seamlessClone)能解决这个问题。

基于opencv的人脸美颜 比图上新增大眼瘦脸功能 含40页算法讲解 送代码讲解(python语言)ppt讲解15页

瘦脸的流体模拟:

这里用保距变换+网格变形实现,原理类似液化滤镜:

def slim_face(img, face_points):
    # 选取脸颊关键点(假设points是Dlib的68点坐标)
    left_cheek = face_points[3]
    right_cheek = face_points[13]
    
    # 计算向内收缩的位移向量
    dx = int((left_cheek[0] - right_cheek[0])*0.15)
    
    # 创建位移场
    mesh = np.zeros(img.shape[:2], np.float32)
    for y in range(img.shape[0]):
        for x in range(img.shape[1]):
            # 计算当前点到脸颊线的距离作为权重
            dist = distance_to_face_line(x,y)
            mesh[y,x] = dx * (1 - dist/100) if dist <100 else 0
            
    # 应用remap
    map_x = np.zeros_like(mesh)
    map_y = np.zeros_like(mesh)
    for y in range(img.shape[0]):
        for y in range(img.shape[1]):
            map_x[y,x] = x + mesh[y,x]
            map_y[y,x] = y
    return cv2.remap(img, map_x, map_y, cv2.INTER_LINEAR)

实际项目会优化网格计算速度,比如用稀疏关键点插值代替逐像素计算。参数0.15控制瘦脸强度,超过0.2可能导致背景扭曲。

避坑指南:

  1. 关键点抖动问题:用卡尔曼滤波做帧间平滑
  2. 美颜过度失真:在形变区域外保留5-10像素的过渡区
  3. 性能优化:把for循环换成NumPy矩阵运算,速度提升10倍不是梦

完整项目包含肤色调整、磨皮等模块(篇幅限制不展开),代码包里已经处理好各模块的权重融合。想要算法详解文档和调试工具的朋友,老规矩在评论区戳源码链接。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐