人臉美顏磨皮Dermabrasion

主要嘗試的方法,雙邊濾波,高斯濾波,導向濾波,表面模糊,加權小二乘濾波器(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()

效果對比:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章