美图祛斑算法实战——雀斑消除

美图祛斑算法实战——雀斑消除

本文主要根据这篇博文的思路,由于原博文没有放出完整代码,我这里尝试根据作者的思路实现人脸祛斑算法的代码完整版,本代码针对特定图像使用了一些trick,不是通用算法,仅做参考。
算法流程主要为:

  1. 灰度化
  2. 对比度增强
  3. 阈值处理
  4. 梯度极大值查找
  5. 连通域分析
  6. 皮肤排除
  7. 图像修复 inpaint

本代码用到的图片如下,从这篇博文直接下载得到,我们的目标是去除任务颈肩部位的祛斑。

导入用到的库

import cv2
import matplotlib.pyplot as plt
import numpy as np
import skimage
from skimage import morphology
from skimage.io import imread

读取图像,转为灰度图,然后进行对比度增强

img = cv2.imread('./face.png')
src = img.copy()
src = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY) # 转为灰度图
con = skimage.exposure.adjust_sigmoid(src,0.4) # 0.4这个阈值就比较trick了。。。

使用sobel算子进行边缘检测

x_gray = cv2.Sobel(con, cv2.CV_32F, 1, 0, ksize=3)
y_gray = cv2.Sobel(con, cv2.CV_32F, 0, 1, ksize=3)
x_gray = cv2.convertScaleAbs(x_gray)
y_gray = cv2.convertScaleAbs(y_gray)
dst = cv2.add(x_gray, y_gray, dtype=cv2.CV_16S)
dst = cv2.convertScaleAbs(dst)

plt.imshow(dst)

可视化dst后发现边缘都已经被成功识别了,包括雀斑和人脸的边缘。接着对梯度做二值处理,选取一个阈值,大于阈值的设为255,小于阈值的设为0

a = dst.copy()
thres = 40
a[a>thres]=255
a[a<=thres]=0
plt.show(a)

到了这一步,雀斑的轮廓已经很清晰的展示在我们面前了,然而左边脸部有一些很多阴影也被提取进来了,要想办法去掉它们。

为了能用连通域去掉脸部的阴影,先用闭运算处理一下二值图,把阴影散点连成一片,在用连通域分析,去掉面积大于某个阈值的连通域

labels = ((morphology.closing(a, skimage.morphology.disk(7))>0)*255).astype(np.uint8)
num_labels,labels,stats,centers = cv2.connectedComponentsWithStats(labels, connectivity=4,ltype=cv2.CV_32S)
for t in range(1, num_labels, 1):
        x, y, w, h, area = stats[t]
        if area>300:
            index = np.where(labels==t)
            labels[index[0], index[1]] = 0

mask = (labels>0).astype(np.uint8)*255
plt.imshow(mask)

利用闭运算+连通域处理,成功把大部分人体边缘去除,留下了雀斑的mask,如下图

有时候祛斑比较大,轮廓中间有空洞,这里用一个函数填充雀斑轮廓的空洞,使它变成实心mask

def remove_holes_in_region(mask_scar):
    cnts, _ = cv2.findContours(mask_scar.astype(np.uint8), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
    for cnt in cnts:
        cnt = cnt.transpose(1,0,2) # (1,N,2) N:points number
        cv2.fillPoly(mask_scar, cnt, 1)
    return mask_scar
mask = remove_holes_in_region(mask)

最后利用 cv2.inpaint 函数,输入原始图像img和我们得到的雀斑mask,修补图像

dst_TELEA = cv2.inpaint(img,mask,3,cv2.INPAINT_TELEA)
plt.imshow(dst)

效果还蛮不错的!大概现实了祛斑的功能

总结

不能说这个算法不好,可以说是完全没用

引用

思路来源博客
美图专利


注:如要转载,请联系作者

猜你喜欢

转载自blog.csdn.net/baoxin1100/article/details/112627991