亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

基于Python的人工智能美顏系統(tǒng)

系統(tǒng) 1522 0

?基于Python的人工智能美顏系統(tǒng)使用PyQt5模塊搭建可視化界面,Dlib模型(shape_predictor_68_face_landmarks.dat)實(shí)現(xiàn)人臉關(guān)鍵點(diǎn)檢測(cè)和定位,人臉美顏(美白、磨皮、亮眼、紅唇等操作)均是在檢測(cè)到相對(duì)應(yīng)人臉器官后,使用OpenCv模塊實(shí)現(xiàn)調(diào)節(jié)亮度、銳化等操作。

效果圖如下所示:

項(xiàng)目代碼及所需配置文件見(jiàn)網(wǎng)址:https://download.csdn.net/download/m0_38106923/11253733。?

GUI代碼如下:

            
              import sys,os
import numpy as np
import cv2
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtGui import QImage,QIcon,QPixmap
from PyQt5.QtWidgets import QFileDialog,QMessageBox
from AIMakeup import Makeup,Face,Organ,NoFace

class Ui_MainWindow(object):
    def __init__(self, MainWindow):
        self.window=MainWindow
        self._setupUi()
        #控件分組
        self.bg_edit=[self.bt_brightening,self.bt_whitening,self.bt_sharpen,self.bt_smooth]
        self.bg_op=[self.bt_confirm,self.bt_cancel,self.bt_reset]
        self.bg_result=[self.bt_view_compare,self.bt_save,self.bt_save_compare]
        self.sls=[self.sl_brightening,self.sl_sharpen,self.sl_whitening,self.sl_smooth]
        #用于顯示圖片的標(biāo)簽
        self.label=QtWidgets.QLabel(self.window)
        self.sa.setWidget(self.label)
        #批量設(shè)置狀態(tài)
        self._set_statu(self.bg_edit,False)
        self._set_statu(self.bg_op,False)
        self._set_statu(self.bg_result,False)
        self._set_statu(self.sls,False)
        #導(dǎo)入dlib模型文件
        if os.path.exists("./data/shape_predictor_68_face_landmarks.dat"):
            self.path_predictor=os.path.abspath("./data/shape_predictor_68_face_landmarks.dat")
        else:
            QMessageBox.warning(self.centralWidget,'警告','默認(rèn)的dlib模型文件路徑不存在,請(qǐng)指定文件位置。\
                                \n或從http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2下載')
            self.path_predictor,_=QFileDialog.getOpenFileName(self.centralWidget,'選擇dlib模型文件','./','Data Files(*.dat)')
        #實(shí)例化化妝器
        self.mu=Makeup(self.path_predictor)
        
        self.path_img=''
        self._set_connect()
    def _set_connect(self):
        '''
        設(shè)置程序邏輯
        '''
        self.bt_open.clicked.connect(self._open_img)
        for op in ['sharpen','whitening','smooth','brightening','cancel','confirm','reset','save','save_compare','view_compare']:
            self.__getattribute__('bt_'+op).clicked.connect(self.__getattribute__('_'+op))
            
    def _open_img(self):
        '''
        打開圖片
        '''
        self.path_img,_=QFileDialog.getOpenFileName(self.centralWidget,'打開圖片文件','./','Image Files(*.png *.jpg *.bmp)')
        if self.path_img and os.path.exists(self.path_img):
            print(self.path_img)
            self.im_bgr,self.temp_bgr,self.faces=self.mu.read_and_mark(self.path_img)
            self.im_ori,self.previous_bgr=self.im_bgr.copy(),self.im_bgr.copy()
            self._set_statu(self.bg_edit,True)
            self._set_statu(self.bg_op,True)
            self._set_statu(self.bg_result,True)
            self._set_statu(self.sls,True)
            self._set_img()
        else:
            QMessageBox.warning(self.centralWidget,'無(wú)效路徑','無(wú)效路徑,請(qǐng)重新選擇!')
            
    def _cv2qimg(self,cvImg):
        '''
        將opencv的圖片轉(zhuǎn)換為QImage
        '''
        height, width, channel = cvImg.shape
        bytesPerLine = 3 * width
        return QImage(cv2.cvtColor(cvImg,cv2.COLOR_BGR2RGB).data, width, height, bytesPerLine, QImage.Format_RGB888)
        
    def _set_img(self):
        '''
        顯示pixmap
        '''
        self.label.setPixmap(QPixmap.fromImage(self._cv2qimg(self.temp_bgr)))

    def _set_statu(self,group,value):
        '''
        批量設(shè)置狀態(tài)
        '''
        [item.setEnabled(value) for item in group]
        
    def _confirm(self):
        '''
        確認(rèn)操作
        '''
        self.im_bgr[:]=self.temp_bgr[:]
        
    def _cancel(self):
        '''
        還原到上一步
        '''
        self.temp_bgr[:]=self.previous_bgr[:]
        self._set_img()
        
    def _reset(self):
        '''
        重置為原始圖片
        '''
        self.temp_bgr[:]=self.im_ori[:]
        self._set_img()
        
    def _mapfaces(self,fun,value):
        '''
        對(duì)每張臉進(jìn)行迭代操作
        '''
        self.previous_bgr[:]=self.temp_bgr[:]
        for face in self.faces[self.path_img]:
            fun(face,value)
        self._set_img()
        
    def _sharpen(self):
        value=min(1,max(self.sl_sharpen.value()/200,0))
        print(value)
        def fun(face,value):
            face.organs['left eye'].sharpen(value,confirm=False)
            face.organs['right eye'].sharpen(value,confirm=False)
        self._mapfaces(fun,value)
        
    def _whitening(self):
        value=min(1,max(self.sl_whitening.value()/200,0))
        print(value)
        def fun(face,v):
            face.organs['left eye'].whitening(value,confirm=False)
            face.organs['right eye'].whitening(value,confirm=False)
            face.organs['left brow'].whitening(value,confirm=False)
            face.organs['right brow'].whitening(value,confirm=False)
            face.organs['nose'].whitening(value,confirm=False)
            face.organs['forehead'].whitening(value,confirm=False)
            face.organs['mouth'].whitening(value,confirm=False)
            face.whitening(value,confirm=False)
        self._mapfaces(fun,value)

    def _brightening(self):
        value=min(1,max(self.sl_brightening.value()/200,0))
        print(value)
        def fun(face,value):
            face.organs['mouth'].brightening(value,confirm=False)
        self._mapfaces(fun,value)
        
    def _smooth(self):
        value=min(1,max(self.sl_smooth.value()/100,0))
        def fun(face,value):
            face.smooth(value,confirm=False)
            face.organs['left eye'].smooth(value*2/3,confirm=False)
            face.organs['right eye'].smooth(value*2/3,confirm=False)
            face.organs['left brow'].smooth(value*2/3,confirm=False)
            face.organs['right brow'].smooth(value*2/3,confirm=False)
            face.organs['nose'].smooth(value*2/3,confirm=False)
            face.organs['forehead'].smooth(value*3/2,confirm=False)
            face.organs['mouth'].smooth(value,confirm=False)
        self._mapfaces(fun,value)
    
    def _save(self):
        output_path,_=QFileDialog.getSaveFileName(self.centralWidget,'選擇保存位置','./','Image Files(*.png *.jpg *.bmp)')
        if output_path:
            self.save(output_path,self.im_bgr)
        else:
            QMessageBox.warning(self.centralWidget,'無(wú)效路徑','無(wú)效路徑,請(qǐng)重新選擇!')
        
    def _save_compare(self):
        output_path,_=QFileDialog.getSaveFileName(self.centralWidget,'選擇保存位置','./','Image Files(*.png *.jpg *.bmp)')
        if output_path:
            self.save(output_path,np.concatenate([self.im_ori,self.im_bgr],1))
        else:
            QMessageBox.warning(self.centralWidget,'無(wú)效路徑','無(wú)效路徑,請(qǐng)重新選擇!')
        
    def _view_compare(self):
        cv2.imshow('Compare',np.concatenate([self.im_ori,self.im_bgr],1))
        cv2.waitKey()
        
    def _setupUi(self):
        self.window.setObjectName("MainWindow")
        self.window.resize(837, 838)
        self.centralWidget = QtWidgets.QWidget(self.window)
        self.centralWidget.setObjectName("centralWidget")
        self.verticalLayout = QtWidgets.QVBoxLayout(self.centralWidget)
        self.verticalLayout.setObjectName("verticalLayout")
        self.sa = QtWidgets.QScrollArea(self.centralWidget)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.sa.sizePolicy().hasHeightForWidth())
        self.sa.setSizePolicy(sizePolicy)
        self.sa.setWidgetResizable(True)
        self.sa.setObjectName("sa")
        self.scrollAreaWidgetContents = QtWidgets.QWidget()
        self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 813, 532))
        self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
        self.sa.setWidget(self.scrollAreaWidgetContents)
        self.verticalLayout.addWidget(self.sa)
        self.gridLayout = QtWidgets.QGridLayout()
        self.gridLayout.setObjectName("gridLayout")
        self.bt_whitening = QtWidgets.QPushButton(self.centralWidget)
        self.bt_whitening.setObjectName("bt_whitening")
        self.gridLayout.addWidget(self.bt_whitening, 0, 0, 1, 1)
        self.sl_whitening = QtWidgets.QSlider(self.centralWidget)
        self.sl_whitening.setOrientation(QtCore.Qt.Horizontal)
        self.sl_whitening.setObjectName("sl_whitening")
        self.gridLayout.addWidget(self.sl_whitening, 0, 1, 1, 1)
        spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.gridLayout.addItem(spacerItem, 0, 2, 1, 1)
        self.bt_smooth = QtWidgets.QPushButton(self.centralWidget)
        self.bt_smooth.setObjectName("bt_smooth")
        self.gridLayout.addWidget(self.bt_smooth, 1, 0, 1, 1)
        self.sl_smooth = QtWidgets.QSlider(self.centralWidget)
        self.sl_smooth.setOrientation(QtCore.Qt.Horizontal)
        self.sl_smooth.setObjectName("sl_smooth")
        self.gridLayout.addWidget(self.sl_smooth, 1, 1, 1, 1)
        spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.gridLayout.addItem(spacerItem1, 1, 2, 1, 1)
        self.bt_sharpen = QtWidgets.QPushButton(self.centralWidget)
        self.bt_sharpen.setObjectName("bt_sharpen")
        self.gridLayout.addWidget(self.bt_sharpen, 2, 0, 1, 1)
        self.sl_sharpen = QtWidgets.QSlider(self.centralWidget)
        self.sl_sharpen.setOrientation(QtCore.Qt.Horizontal)
        self.sl_sharpen.setObjectName("sl_sharpen")
        self.gridLayout.addWidget(self.sl_sharpen, 2, 1, 1, 1)
        spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.gridLayout.addItem(spacerItem2, 2, 2, 1, 1)
        self.bt_brightening = QtWidgets.QPushButton(self.centralWidget)
        self.bt_brightening.setObjectName("bt_brightening")
        self.gridLayout.addWidget(self.bt_brightening, 3, 0, 1, 1)
        self.sl_brightening = QtWidgets.QSlider(self.centralWidget)
        self.sl_brightening.setOrientation(QtCore.Qt.Horizontal)
        self.sl_brightening.setObjectName("sl_brightening")
        self.gridLayout.addWidget(self.sl_brightening, 3, 1, 1, 1)
        spacerItem3 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.gridLayout.addItem(spacerItem3, 3, 2, 1, 1)
        self.bt_open = QtWidgets.QPushButton(self.centralWidget)
        self.bt_open.setObjectName("bt_open")
        self.gridLayout.addWidget(self.bt_open, 4, 0, 1, 1)
        self.bt_confirm = QtWidgets.QPushButton(self.centralWidget)
        self.bt_confirm.setObjectName("bt_confirm")
        self.gridLayout.addWidget(self.bt_confirm, 5, 0, 1, 1)
        self.bt_cancel = QtWidgets.QPushButton(self.centralWidget)
        self.bt_cancel.setObjectName("bt_cancel")
        self.gridLayout.addWidget(self.bt_cancel, 5, 1, 1, 1)
        self.bt_reset = QtWidgets.QPushButton(self.centralWidget)
        self.bt_reset.setObjectName("bt_reset")
        self.gridLayout.addWidget(self.bt_reset, 5, 2, 1, 1)
        self.bt_view_compare = QtWidgets.QPushButton(self.centralWidget)
        self.bt_view_compare.setObjectName("bt_view_compare")
        self.gridLayout.addWidget(self.bt_view_compare, 6, 0, 1, 1)
        self.bt_save = QtWidgets.QPushButton(self.centralWidget)
        self.bt_save.setObjectName("bt_save")
        self.gridLayout.addWidget(self.bt_save, 7, 1, 1, 1)
        self.bt_save_compare = QtWidgets.QPushButton(self.centralWidget)
        self.bt_save_compare.setObjectName("bt_save_compare")
        self.gridLayout.addWidget(self.bt_save_compare, 7, 2, 1, 1)
        self.verticalLayout.addLayout(self.gridLayout)
        self.window.setCentralWidget(self.centralWidget)

        self.retranslateUi()
        QtCore.QMetaObject.connectSlotsByName(self.window)

    def save(self,output_path,output_im):
        '''
        保存圖片
        '''
        cv2.imencode('.jpg',output_im)[1].tofile(output_path)

    def retranslateUi(self):
        _translate = QtCore.QCoreApplication.translate
        self.window.setWindowTitle(_translate("MainWindow", "AI美顏"))
        self.bt_whitening.setText(_translate("MainWindow", "美白"))
        self.bt_smooth.setText(_translate("MainWindow", "磨皮"))
        self.bt_sharpen.setText(_translate("MainWindow", "亮眼"))
        self.bt_brightening.setText(_translate("MainWindow", "紅唇"))
        self.bt_open.setText(_translate("MainWindow", "打開文件"))
        self.bt_confirm.setText(_translate("MainWindow", "確認(rèn)更改"))
        self.bt_cancel.setText(_translate("MainWindow", "撤銷更改"))
        self.bt_reset.setText(_translate("MainWindow", "還原"))
        self.bt_view_compare.setText(_translate("MainWindow", "查看對(duì)比"))
        self.bt_save.setText(_translate("MainWindow", "保存"))
        self.bt_save_compare.setText(_translate("MainWindow", "保存對(duì)比圖"))


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow(MainWindow)
    ui.window.show()
    sys.exit(app.exec_())
            
          

算法實(shí)現(xiàn)代碼如下:

            
              import sys,os,traceback
import cv2
import dlib
import numpy as np

class NoFace(Exception):
    '''
    沒(méi)臉
    '''
    pass

class Organ():
    def __init__(self,im_bgr,im_hsv,temp_bgr,temp_hsv,landmark,name,ksize=None):
        '''
        五官部位類
        arguments:
            im_bgr:uint8 array, inference of BGR image
            im_hsv:uint8 array, inference of HSV image
            temp_bgr/hsv:global temp image
            landmark:array(x,2), landmarks
            name:string
        '''
        self.im_bgr,self.im_hsv,self.landmark,self.name=im_bgr,im_hsv,landmark,name
        self.get_rect()
        self.shape=(int(self.bottom-self.top),int(self.right-self.left))
        self.size=self.shape[0]*self.shape[1]*3
        self.move=int(np.sqrt(self.size/3)/20)
        self.ksize=self.get_ksize()
        self.patch_bgr,self.patch_hsv=self.get_patch(self.im_bgr),self.get_patch(self.im_hsv)
        self.set_temp(temp_bgr,temp_hsv)
        self.patch_mask=self.get_mask_re()
        pass
    
    def set_temp(self,temp_bgr,temp_hsv):
        self.im_bgr_temp,self.im_hsv_temp=temp_bgr,temp_hsv
        self.patch_bgr_temp,self.patch_hsv_temp=self.get_patch(self.im_bgr_temp),self.get_patch(self.im_hsv_temp)

    def confirm(self):
        '''
        確認(rèn)操作
        '''
        self.im_bgr[:],self.im_hsv[:]=self.im_bgr_temp[:],self.im_hsv_temp[:]
    
    def update_temp(self):
        '''
        更新臨時(shí)圖片
        '''
        self.im_bgr_temp[:],self.im_hsv_temp[:]=self.im_bgr[:],self.im_hsv[:]
        
    def get_ksize(self,rate=15):
        size=max([int(np.sqrt(self.size/3)/rate),1])
        size=(size if size%2==1 else size+1)
        return (size,size)
        
    def get_rect(self):
        '''
        獲得定位方框
        '''
        ys,xs=self.landmark[:,1],self.landmark[:,0]
        self.top,self.bottom,self.left,self.right=np.min(ys),np.max(ys),np.min(xs),np.max(xs)

    def get_patch(self,im):
        '''
        截取局部切片
        '''
        shape=im.shape
        return im[np.max([self.top-self.move,0]):np.min([self.bottom+self.move,shape[0]]),np.max([self.left-self.move,0]):np.min([self.right+self.move,shape[1]])]

    def _draw_convex_hull(self,im, points, color):
        '''
        勾畫多凸邊形
        '''
        points = cv2.convexHull(points)
        cv2.fillConvexPoly(im, points, color=color)
        
    def get_mask_re(self,ksize=None):
        '''
        獲得局部相對(duì)坐標(biāo)遮罩
        '''
        if ksize==None:
            ksize=self.ksize
        landmark_re=self.landmark.copy()
        landmark_re[:,1]-=np.max([self.top-self.move,0])
        landmark_re[:,0]-=np.max([self.left-self.move,0])
        mask = np.zeros(self.patch_bgr.shape[:2], dtype=np.float64)
    
        self._draw_convex_hull(mask,
                         landmark_re,
                         color=1)
    
        mask = np.array([mask, mask, mask]).transpose((1, 2, 0))
    
        mask = (cv2.GaussianBlur(mask, ksize, 0) > 0) * 1.0
        return cv2.GaussianBlur(mask, ksize, 0)[:]
        
    def get_mask_abs(self,ksize=None):
        '''
        獲得全局絕對(duì)坐標(biāo)遮罩
        '''
        if ksize==None:
            ksize=self.ksize
        mask = np.zeros(self.im_bgr.shape, dtype=np.float64)
        patch=self.get_patch(mask)
        patch[:]=self.patch_mask[:]
        return mask
        
    def whitening(self,rate=0.15,confirm=True):
        '''
        提亮美白
        arguments:
            rate:float,-1~1,new_V=min(255,V*(1+rate))
            confirm:wether confirm this option
        '''
        if confirm:
            self.confirm()
            self.patch_hsv[:,:,-1]=np.minimum(self.patch_hsv[:,:,-1]+self.patch_hsv[:,:,-1]*self.patch_mask[:,:,-1]*rate,255).astype('uint8')
            self.im_bgr[:]=cv2.cvtColor(self.im_hsv, cv2.COLOR_HSV2BGR)[:]
            self.update_temp()
        else:
            self.patch_hsv_temp[:]=cv2.cvtColor(self.patch_bgr_temp, cv2.COLOR_BGR2HSV)[:]
            self.patch_hsv_temp[:,:,-1]=np.minimum(self.patch_hsv_temp[:,:,-1]+self.patch_hsv_temp[:,:,-1]*self.patch_mask[:,:,-1]*rate,255).astype('uint8')
            self.patch_bgr_temp[:]=cv2.cvtColor(self.patch_hsv_temp, cv2.COLOR_HSV2BGR)[:]
            
    def brightening(self,rate=0.3,confirm=True):
        '''
        提升鮮艷度
        arguments:
            rate:float,-1~1,new_S=min(255,S*(1+rate))
            confirm:wether confirm this option
        '''
        patch_mask=self.get_mask_re((1,1))
        if confirm:
            self.confirm()
            patch_new=self.patch_hsv[:,:,1]*patch_mask[:,:,1]*rate
            patch_new=cv2.GaussianBlur(patch_new,(3,3),0)
            self.patch_hsv[:,:,1]=np.minimum(self.patch_hsv[:,:,1]+patch_new,255).astype('uint8')
            self.im_bgr[:]=cv2.cvtColor(self.im_hsv, cv2.COLOR_HSV2BGR)[:]
            self.update_temp()
        else:
            self.patch_hsv_temp[:]=cv2.cvtColor(self.patch_bgr_temp, cv2.COLOR_BGR2HSV)[:]
            patch_new=self.patch_hsv_temp[:,:,1]*patch_mask[:,:,1]*rate
            patch_new=cv2.GaussianBlur(patch_new,(3,3),0)
            self.patch_hsv_temp[:,:,1]=np.minimum(self.patch_hsv[:,:,1]+patch_new,255).astype('uint8')
            self.patch_bgr_temp[:]=cv2.cvtColor(self.patch_hsv_temp, cv2.COLOR_HSV2BGR)[:]
        
    def smooth(self,rate=0.6,ksize=None,confirm=True):
        '''
        磨皮
        arguments:
            rate:float,0~1,im=rate*new+(1-rate)*src
            confirm:wether confirm this option
        '''
        if ksize==None:
            ksize=self.get_ksize(80)
        index=self.patch_mask>0
        if confirm:
            self.confirm()
            patch_new=cv2.GaussianBlur(cv2.bilateralFilter(self.patch_bgr,3,*ksize),ksize,0)
            self.patch_bgr[index]=np.minimum(rate*patch_new[index]+(1-rate)*self.patch_bgr[index],255).astype('uint8')
            self.im_hsv[:]=cv2.cvtColor(self.im_bgr, cv2.COLOR_BGR2HSV)[:]
            self.update_temp()
        else:
            patch_new=cv2.GaussianBlur(cv2.bilateralFilter(self.patch_bgr_temp,3,*ksize),ksize,0)
            self.patch_bgr_temp[index]=np.minimum(rate*patch_new[index]+(1-rate)*self.patch_bgr_temp[index],255).astype('uint8')
            self.patch_hsv_temp[:]=cv2.cvtColor(self.patch_bgr_temp, cv2.COLOR_BGR2HSV)[:]
        
    def sharpen(self,rate=0.3,confirm=True):
        '''
        銳化
        '''
        patch_mask=self.get_mask_re((3,3))
        kernel = np.zeros( (9,9), np.float32)
        kernel[4,4] = 2.0   #Identity, times two! 
        #Create a box filter:
        boxFilter = np.ones( (9,9), np.float32) / 81.0
        
        #Subtract the two:
        kernel = kernel - boxFilter
        index=patch_mask>0
        if confirm:
            self.confirm()
            sharp=cv2.filter2D(self.patch_bgr,-1,kernel)
            self.patch_bgr[index]=np.minimum(((1-rate)*self.patch_bgr)[index]+sharp[index]*rate,255).astype('uint8')
            self.update_temp()
        else:
            sharp=cv2.filter2D(self.patch_bgr_temp,-1,kernel)
            self.patch_bgr_temp[:]=np.minimum(self.patch_bgr_temp+self.patch_mask*sharp*rate,255).astype('uint8')
            self.patch_hsv_temp[:]=cv2.cvtColor(self.patch_bgr_temp, cv2.COLOR_BGR2HSV)[:]

class Forehead(Organ):
    def __init__(self,im_bgr,im_hsv,temp_bgr,temp_hsv,landmark,mask_organs,name,ksize=None):
        self.mask_organs=mask_organs
        super(Forehead,self).__init__(im_bgr,im_hsv,temp_bgr,temp_hsv,landmark,name,ksize)
    
    def get_mask_re(self,ksize=None):
        '''
        獲得局部相對(duì)坐標(biāo)遮罩
        '''
        if ksize==None:
            ksize=self.ksize
        landmark_re=self.landmark.copy()
        landmark_re[:,1]-=np.max([self.top-self.move,0])
        landmark_re[:,0]-=np.max([self.left-self.move,0])
        mask = np.zeros(self.patch_bgr.shape[:2], dtype=np.float64)
    
        self._draw_convex_hull(mask,
                         landmark_re,
                         color=1)
        
        mask = np.array([mask, mask, mask]).transpose((1, 2, 0))
    
        mask = (cv2.GaussianBlur(mask, ksize, 0) > 0) * 1.0
        patch_organs=self.get_patch(self.mask_organs)
        mask= cv2.GaussianBlur(mask, ksize, 0)[:]
        mask[patch_organs>0]=(1-patch_organs[patch_organs>0])
        return mask
        
class Face(Organ):
    '''
    臉類
    arguments:
        im_bgr:uint8 array, inference of BGR image
        im_hsv:uint8 array, inference of HSV image
        temp_bgr/hsv:global temp image
        landmarks:list, landmark groups
        index:int, index of face in the image
    '''
    def __init__(self,im_bgr,img_hsv,temp_bgr,temp_hsv,landmarks,index):
        self.index=index
        #五官名稱
        self.organs_name=['jaw','mouth','nose','left eye','right eye','left brow','right brow']
        
        #五官等標(biāo)記點(diǎn)
        self.organs_points=[list(range(0, 17)),list(range(48, 61)),list(range(27, 35)),list(range(42, 48)),list(range(36, 42)),list(range(22, 27)),list(range(17, 22))]

        #實(shí)例化臉對(duì)象和五官對(duì)象
        self.organs={name:Organ(im_bgr,img_hsv,temp_bgr,temp_hsv,landmarks[points],name) for name,points in zip(self.organs_name,self.organs_points)}

        #獲得額頭坐標(biāo),實(shí)例化額頭
        mask_nose=self.organs['nose'].get_mask_abs()
        mask_organs=(self.organs['mouth'].get_mask_abs()+mask_nose+self.organs['left eye'].get_mask_abs()+self.organs['right eye'].get_mask_abs()+self.organs['left brow'].get_mask_abs()+self.organs['right brow'].get_mask_abs())
        forehead_landmark=self.get_forehead_landmark(im_bgr,landmarks,mask_organs,mask_nose)
        self.organs['forehead']=Forehead(im_bgr,img_hsv,temp_bgr,temp_hsv,forehead_landmark,mask_organs,'forehead')
        mask_organs+=self.organs['forehead'].get_mask_abs()

        # 人臉的完整標(biāo)記點(diǎn)
        self.FACE_POINTS = np.concatenate([landmarks,forehead_landmark])
        super(Face,self).__init__(im_bgr,img_hsv,temp_bgr,temp_hsv,self.FACE_POINTS,'face')

        mask_face=self.get_mask_abs()-mask_organs
        self.patch_mask=self.get_patch(mask_face)
        pass
        
    
    def get_forehead_landmark(self,im_bgr,face_landmark,mask_organs,mask_nose):
        '''
        計(jì)算額頭坐標(biāo)
        '''
        #畫橢圓
        radius=(np.linalg.norm(face_landmark[0]-face_landmark[16])/2).astype('int32')
        center_abs=tuple(((face_landmark[0]+face_landmark[16])/2).astype('int32'))
        
        angle=np.degrees(np.arctan((lambda l:l[1]/l[0])(face_landmark[16]-face_landmark[0]))).astype('int32')
        mask=np.zeros(mask_organs.shape[:2], dtype=np.float64)
        cv2.ellipse(mask,center_abs,(radius,radius),angle,180,360,1,-1)
        #剔除與五官重合部分
        mask[mask_organs[:,:,0]>0]=0
        #根據(jù)鼻子的膚色判斷真正的額頭面積
        index_bool=[]
        for ch in range(3):
            mean,std=np.mean(im_bgr[:,:,ch][mask_nose[:,:,ch]>0]),np.std(im_bgr[:,:,ch][mask_nose[:,:,ch]>0])
            up,down=mean+0.5*std,mean-0.5*std
            index_bool.append((im_bgr[:,:,ch]
              
                up))
        index_zero=((mask>0)&index_bool[0]&index_bool[1]&index_bool[2])
        mask[index_zero]=0
        index_abs=np.array(np.where(mask>0)[::-1]).transpose()
        landmark=cv2.convexHull(index_abs).squeeze()
        return landmark
    
class Makeup():
    '''
    化妝器
    '''
    def __init__(self,predictor_path="./data/shape_predictor_68_face_landmarks.dat"):
        self.photo_path=[]
        self.PREDICTOR_PATH = predictor_path
        self.faces={}
        
        #人臉定位、特征提取器,來(lái)自dlib
        self.detector = dlib.get_frontal_face_detector()
        self.predictor = dlib.shape_predictor(self.PREDICTOR_PATH)

    def get_faces(self,im_bgr,im_hsv,temp_bgr,temp_hsv,name,n=1):
        '''
        人臉定位和特征提取,定位到兩張及以上臉或者沒(méi)有人臉將拋出異常
        im:
            照片的numpy數(shù)組
        fname:
            照片名字的字符串
        返回值:
            人臉特征(x,y)坐標(biāo)的矩陣
        '''
        rects = self.detector(im_bgr, 1)
        
        if len(rects) <1:
            raise NoFace('Too many faces in '+name)
        return {name:[Face(im_bgr,im_hsv,temp_bgr,temp_hsv,np.array([[p.x, p.y] for p in self.predictor(im_bgr, rect).parts()]),i) for i,rect in enumerate(rects)]}

    def read_im(self,fname,scale=1):
        '''
        讀取圖片
        '''
        im = cv2.imdecode(np.fromfile(fname,dtype=np.uint8),-1)
        if type(im)==type(None):
            print(fname)
            raise ValueError('Opencv error reading image "{}" , got None'.format(fname))
        return im

    def read_and_mark(self,fname):
        im_bgr=self.read_im(fname)
        im_hsv=cv2.cvtColor(im_bgr, cv2.COLOR_BGR2HSV)
        temp_bgr,temp_hsv=im_bgr.copy(),im_hsv.copy()
        return im_bgr,temp_bgr,self.get_faces(im_bgr,im_hsv,temp_bgr,temp_hsv,fname)

if __name__=='__main__':
    path='./heads/5.jpg'
    mu=Makeup()
    im,temp_bgr,faces=mu.read_and_mark(path)
    imc=im.copy()
    cv2.imshow('ori',imc)
    for face in faces[path]:
        face.whitening()
        face.smooth(0.7)
        face.organs['forehead'].whitening()
        face.organs['forehead'].smooth(0.7)
        face.organs['mouth'].brightening()
        face.organs['mouth'].smooth(0.7)
        face.organs['mouth'].whitening()
        face.organs['left eye'].whitening()
        face.organs['right eye'].whitening()
        face.organs['left eye'].sharpen()
        face.organs['right eye'].sharpen()
        face.organs['left eye'].smooth()
        face.organs['right eye'].smooth()
        face.organs['left brow'].whitening()
        face.organs['right brow'].whitening()
        face.organs['left brow'].sharpen()
        face.organs['right brow'].sharpen()
        face.organs['nose'].whitening()
        face.organs['nose'].smooth(0.7)
        face.organs['nose'].sharpen()
        face.sharpen()
    cv2.imshow('new',im.copy())
    cv2.waitKey()
    print('Quiting')
              
            
          

?


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 免费女人18a级毛片视频 | 在线观看免费情网站大全 | 伊人中文字幕在线观看 | 爱爱爱久久久久久久 | 日韩欧美视频在线播放 | 精品国产一区二区三区香蕉沈先生 | aaa级大片| 久久综合性| 羞羞色男人的天堂伊人久久 | a级毛片在线视频免费观看 a级免费网站 | 日韩亚洲一区中文字幕 | 中文字幕在线视频精品 | 99re8热精品免费视频 | 久久久久久久久免费影院 | 午夜亚洲国产理论秋霞 | 女人与zzzooooxxx| 亚洲片在线观看 | 不卡午夜视频 | 高清不卡| 欧美成在线视频 | 91亚洲精品福利在线播放 | 久久久成人影院 | 俄罗斯色视频 | 亚洲综合久久久久久中文字幕 | 久久精品小视频 | 九九毛片 | 欧美成人免费全网站大片 | 涩涩在线 | 日韩 欧美 中文字幕 不卡 | 成人在线播放 | 欧美wwwxxx| 亚洲一区二区三区高清 不卡 | 亚洲精品久久久久中文字小说 | 久久99蜜桃精品久久久久小说 | 亚洲码在线中文在线观看 | 91中文字幕yellow字幕网 | 国产在线精品香蕉麻豆 | 狠狠狠地在啪线香蕉 | 欧美色爱综合 | 成年女人毛片免费观看中文w | 欧美αv在线 |