主要尝试的方法,双边滤波,高斯滤波,导向滤波,表面模糊,加权小二乘滤波器(WLS滤波器),美颜1,美颜2,这些算法。
代码:
import cv2
import numpy as np
import numpy.matlib
import os
from scipy.sparse import spdiags
class Dermabrasion():
def __init__(self,):
pass
def bilateralFilter(self,image,d=-1,sigmaColor=50,sigmaSpace=10):
#双边滤波
blurred = cv2.bilateralFilter(image,d,sigmaColor,sigmaSpace)
return blurred
def GaussianBlur(self,image,ksize=81,rate=0.5):
#高斯滤波
#im=rate*new+(1-rate)*src
#https://github.com/QuantumLiu/AIMakeup/blob/master/AIMakeup.py
if ksize==None:
ksize=self.get_ksize(81)
patch_new=cv2.GaussianBlur(self.bilateralFilter(image),(5,5),0)
blurred = np.minimum(rate*patch_new+(1-rate)*image,255).astype('uint8')
return blurred
def guideFilter(self, I, p, winSize=(3,3), eps=0.01, s=3):
#导向滤波
##https://blog.csdn.net/wsp_1138886114/article/details/84228939
# 输入图像的高、宽
I = I/255.0
h, w = I.shape[:2]
# 缩小图像
size = (int(round(w * s)), int(round(h * s)))
small_I = cv2.resize(I, size, interpolation=cv2.INTER_CUBIC)
small_p = cv2.resize(I, size, interpolation=cv2.INTER_CUBIC)
# 缩小滑动窗口
X = winSize[0]
small_winSize = (int(round(X * s)), int(round(X * s)))
# I的均值平滑 p的均值平滑
mean_small_I = cv2.blur(small_I, small_winSize)
mean_small_p = cv2.blur(small_p, small_winSize)
# I*I和I*p的均值平滑
mean_small_II = cv2.blur(small_I * small_I, small_winSize)
mean_small_Ip = cv2.blur(small_I * small_p, small_winSize)
# 方差、协方差
var_small_I = mean_small_II - mean_small_I * mean_small_I
cov_small_Ip = mean_small_Ip - mean_small_I * mean_small_p
small_a = cov_small_Ip / (var_small_I + eps)
small_b = mean_small_p - small_a * mean_small_I
# 对a、b进行均值平滑
mean_small_a = cv2.blur(small_a, small_winSize)
mean_small_b = cv2.blur(small_b, small_winSize)
# 放大
size1 = (w, h)
mean_a = cv2.resize(mean_small_a, size1, interpolation=cv2.INTER_LINEAR)
mean_b = cv2.resize(mean_small_b, size1, interpolation=cv2.INTER_LINEAR)
q = mean_a * I + mean_b
# 保存导向滤波结果
guideFilter_img = q * 255 #(0,1)->(0,255)
guideFilter_img[guideFilter_img > 255] = 255 #防止像素溢出
guideFilter_img = np.round(guideFilter_img )
guideFilter_img = guideFilter_img.astype(np.uint8)
return guideFilter_img
def Sur_blur (self,I_in, thre=20, half_size=10):
#表面模糊Surface Blur
#references:https://blog.csdn.net/shinian1987/article/details/78345408
I_out = np.array(I_in, np.float32)
row, col,channel = I_in.shape
w_size = half_size * 2 + 1
for kk in range(channel):
I_in_tmp = I_in[:,:,kk]
I_out_tmp = I_out[:,:,kk]
for ii in range (half_size, row-1-half_size):
for jj in range (half_size, col-1-half_size):
aa = I_in_tmp [ii-half_size:ii+half_size+1, jj-half_size : jj+half_size+1]
p0 = I_in_tmp [ii, jj]
mask_1 = numpy.matlib.repmat(p0, w_size, w_size)
mask_2 = 1-abs(aa-mask_1)/(2.5*thre);
mask_3 = mask_2 * (mask_2 > 0)
t1 = aa * mask_3
I_out_tmp[ii, jj] = t1.sum()/mask_3.sum()
I_out[:,:,kk]=I_out_tmp
return np.asarray(I_out,np.uint8)
def wlsFilter(self,img):
#加权小二乘滤波器(WLS滤波器)
#https://blog.csdn.net/qq_40755643/article/details/84632592
def wls(img, Lambda=1, alpha=1.2, eps=0.0001):
L = np.log(img+0.0001)
row, cols = img.shape[:2]
k = row * cols
#对L矩阵的第一维度上做差分,也就是下面的行减去上面的行,得到(N-1)xM维的矩阵
dy = np.diff(L, 1, 0)
dy = -Lambda/(np.power(np.abs(dy),alpha)+eps)
#在最后一行的后面补上一行0
dy = np.pad(dy, ((0,1),(0,0)), 'constant')
#按列生成向量,对应上面Ay的对角线元素
dy = dy.T
dy = dy.reshape(-1,1)
#对L矩阵的第二维度上做差分,也就是右边的列减去左边的列,得到Nx(M-1)的矩阵
dx = np.diff(L, 1, 1)
dx = -Lambda/(np.power(np.abs(dx),alpha)+eps)
#在最后一列的后面补上一行0
dx = np.pad(dx, ((0,0),(0,1)), 'constant')
#按列生成向量,对应上面Ay的对角线元素
dx = dx.T
dx = dy.reshape(-1,1)
#构造五点空间非齐次拉普拉斯矩阵
B = np.hstack((dx,dy))
B = B.T
diags = np.array([-row, -1])
#把dx放在-row对应的对角线上,把dy放在-1对应的对角线上
A = spdiags(B, diags, k, k).toarray()
e = dx
w = np.pad(dx, ((row,0),(0,0)), 'constant')
w = w[0:-row]
s = dy
n = np.pad(dy, ((1,0),(0,0)), 'constant')
n = n[0:-1]
D = 1-(e+w+s+n)
D = D.T
#A只有五个对角线上有非0元素
diags1 = np.array([0])
A = A + np.array(A).T + spdiags(D, diags1, k, k).toarray()
im = np.array(img)
p,q = im.shape[:2]
g = p*q
im = np.reshape(im,(g,1))
a = np.linalg.inv(A)
out = np.dot(a,im)
out = np.reshape(out,(row, cols))
return out
m = np.double(img)
b, g, r = cv2.split(m)
ib = np.array(b)
p1,q1 = ib.shape[:2]
h1 = p1*q1
ib = np.reshape(ib,(h1,1))
b = b/np.max(ib)
ig = np.array(g)
p2,q2 = ig.shape[:2]
h2 = p2*q2
ig = np.reshape(ig,(h2,1))
g = g/np.max(ig)
ir = np.array(r)
p3,q3 = ir.shape[:2]
h3 = p3*q3
ir = np.reshape(ir,(h3,1))
r = r/np.max(ir)
wls1 = wls(b,1)
wls2 = wls(g,1)
wls3 = wls(r,1)
wls = cv2.merge([wls1, wls2, wls3])
return wls
def beauty_face(self,img):
#https://www.icode9.com/content-1-608228.html
#Dest =(Src * (100 - Opacity) + (Src + 2 * GuassBlur(EPFFilter(Src) - Src + 128) - 256) * Opacity) /100 ;
#https://my.oschina.net/wujux/blog/1563461
dst = np.zeros_like(img)
#int value1 = 3, value2 = 1; 磨皮程度与细节程度的确定
v1 = 3
v2 = 1
dx = v1 * 5 # 双边滤波参数之一
fc = v1 * 12.5 # 双边滤波参数之一
p = 0.1
temp4 = np.zeros_like(img)
temp1 = cv2.bilateralFilter(img,dx,fc,fc)
temp2 = cv2.subtract(temp1,img)
temp2 = cv2.add(temp2,(10,10,10,128))
temp3 = cv2.GaussianBlur(temp2,(2*v2 - 1,2*v2-1),0)
temp4 = cv2.add(img,temp3)
dst = cv2.addWeighted(img,p,temp4,1-p,0.0)
dst = cv2.add(dst,(10, 10, 10,255))
return dst
def beauty_face2(self,src):
#https://www.icode9.com/content-1-608228.html
#https://blog.csdn.net/csyhhb/article/details/47334383
#Dest =(Src * (100 - Opacity) + (Src + 2 * GuassBlur(EPFFilter(Src) - Src + 128) - 256) * Opacity) /100 ;
dst = np.zeros_like(src)
#int value1 = 3, value2 = 1; 磨皮程度与细节程度的确定
v1 = 3
v2 = 1
dx = v1 * 5 # 双边滤波参数之一
fc = v1 * 12.5 # 双边滤波参数之一
p = 0.1
temp4 = np.zeros_like(src)
temp1 = cv2.bilateralFilter(src,dx,fc,fc)
temp2 = cv2.subtract(temp1,src)
temp2 = cv2.add(temp2, (10,10,10,128))
temp3 = cv2.GaussianBlur(temp2,(2*v2 - 1,2*v2-1),0)
temp4 = cv2.subtract(cv2.add(cv2.add(temp3, temp3), src), (10, 10, 10, 255))
dst = cv2.addWeighted(src,p,temp4,1-p,0.0)
dst = cv2.add(dst, (10, 10, 10,255))
return dst
if __name__ == '__main__':
image = cv2.imread(r'./062234378776177.png', cv2.IMREAD_ANYCOLOR)
dermabrasion =Dermabrasion()
cv2.imshow("image",image)
cv2.imshow("bilateralFilter", dermabrasion.bilateralFilter(image) )
cv2.imshow("GaussianBlur", dermabrasion.GaussianBlur(image) )
cv2.imshow("guideFilter", dermabrasion.guideFilter(image,image) )
cv2.imshow("Sur_blur", dermabrasion.Sur_blur(image) )
cv2.imshow("wlsFilter",dermabrasion.wlsFilter(image) )
cv2.imshow("beauty_face",dermabrasion.beauty_face(image) )
cv2.imshow("beauty_face2",dermabrasion.beauty_face2(image) )
cv2.waitKey(0)
cv2.destroyAllWindows()
效果对比: