<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          用 Python 為人臉照片添加口罩

          共 8433字,需瀏覽 17分鐘

           ·

          2022-04-25 00:05

          效果展示

          數(shù)據(jù)集展示

          數(shù)據(jù)集來(lái)源:使用了開源數(shù)據(jù)集 FaceMask_CelebA

          github 地址:https://github.com/sevenHsu/FaceMask_CelebA.git

          部分人臉數(shù)據(jù)集:

          口罩樣本數(shù)據(jù)集:

          為人臉照片添加口罩代碼

          這部分有個(gè)庫(kù) face_recognition 需要安裝,如果之前沒有用過的小伙伴可能得費(fèi)點(diǎn)功夫。

          Face Recognition 庫(kù)主要封裝了 dlib 這一 C++ 圖形庫(kù),通過 Python 語(yǔ)言將它封裝為一個(gè)非常簡(jiǎn)單就可以實(shí)現(xiàn)人臉識(shí)別的 API 庫(kù),屏蔽了人臉識(shí)別的算法細(xì)節(jié),大大降低了人臉識(shí)別功能的開發(fā)難度。

          #!/usr/bin/env?python
          #?-*-?coding:?utf-8?-*-
          #?@Author??:?2014Vee
          import?os
          import?numpy?as?np
          from?PIL?import?Image,?ImageFile

          __version__?=?'0.3.0'

          IMAGE_DIR?=?os.path.dirname('E:/play/FaceMask_CelebA-master/facemask_image/')
          WHITE_IMAGE_PATH?=?os.path.join(IMAGE_DIR,?'front_14.png')
          BLUE_IMAGE_PATH?=?os.path.join(IMAGE_DIR,?'front_14.png')
          SAVE_PATH?=?os.path.dirname('E:/play/FaceMask_CelebA-master/save/synthesis/')
          SAVE_PATH2?=?os.path.dirname('E:/play/FaceMask_CelebA-master/save/masks/')


          class?FaceMasker:
          ????KEY_FACIAL_FEATURES?=?('nose_bridge',?'chin')

          ????def?__init__(self,?face_path,?mask_path,?white_mask_path,?save_path,?save_path2,?model='hog'):
          ????????self.face_path?=?face_path
          ????????self.mask_path?=?mask_path
          ????????self.save_path?=?save_path
          ????????self.save_path2?=?save_path2
          ????????self.white_mask_path?=?white_mask_path
          ????????self.model?=?model
          ????????self._face_img:?ImageFile?=?None
          ????????self._black_face_img?=?None
          ????????self._mask_img:?ImageFile?=?None
          ????????self._white_mask_img?=?None

          ????def?mask(self):
          ????????import?face_recognition

          ????????face_image_np?=?face_recognition.load_image_file(self.face_path)
          ????????face_locations?=?face_recognition.face_locations(face_image_np,?model=self.model)
          ????????face_landmarks?=?face_recognition.face_landmarks(face_image_np,?face_locations)
          ????????self._face_img?=?Image.fromarray(face_image_np)
          ????????self._mask_img?=?Image.open(self.mask_path)
          ????????self._white_mask_img?=?Image.open(self.white_mask_path)
          ????????self._black_face_img?=?Image.new('RGB',?self._face_img.size,?0)

          ????????found_face?=?False
          ????????for?face_landmark?in?face_landmarks:
          ????????????#?check?whether?facial?features?meet?requirement
          ????????????skip?=?False
          ????????????for?facial_feature?in?self.KEY_FACIAL_FEATURES:
          ????????????????if?facial_feature?not?in?face_landmark:
          ????????????????????skip?=?True
          ????????????????????break
          ????????????if?skip:
          ????????????????continue

          ????????????#?mask?face
          ????????????found_face?=?True
          ????????????self._mask_face(face_landmark)

          ????????if?found_face:
          ????????????#?save
          ????????????self._save()
          ????????else:
          ????????????print('Found?no?face.')

          ????def?_mask_face(self,?face_landmark:?dict):
          ????????nose_bridge?=?face_landmark['nose_bridge']
          ????????nose_point?=?nose_bridge[len(nose_bridge)?*?1?//?4]
          ????????nose_v?=?np.array(nose_point)

          ????????chin?=?face_landmark['chin']
          ????????chin_len?=?len(chin)
          ????????chin_bottom_point?=?chin[chin_len?//?2]
          ????????chin_bottom_v?=?np.array(chin_bottom_point)
          ????????chin_left_point?=?chin[chin_len?//?8]
          ????????chin_right_point?=?chin[chin_len?*?7?//?8]

          ????????#?split?mask?and?resize
          ????????width?=?self._mask_img.width
          ????????height?=?self._mask_img.height
          ????????width_ratio?=?1.2
          ????????new_height?=?int(np.linalg.norm(nose_v?-?chin_bottom_v))

          ????????#?left
          ????????mask_left_img?=?self._mask_img.crop((0,?0,?width?//?2,?height))
          ????????mask_left_width?=?self.get_distance_from_point_to_line(chin_left_point,?nose_point,?chin_bottom_point)
          ????????mask_left_width?=?int(mask_left_width?*?width_ratio)
          ????????mask_left_img?=?mask_left_img.resize((mask_left_width,?new_height))

          ????????#?right
          ????????mask_right_img?=?self._mask_img.crop((width?//?2,?0,?width,?height))
          ????????mask_right_width?=?self.get_distance_from_point_to_line(chin_right_point,?nose_point,?chin_bottom_point)
          ????????mask_right_width?=?int(mask_right_width?*?width_ratio)
          ????????mask_right_img?=?mask_right_img.resize((mask_right_width,?new_height))

          ????????#?merge?mask
          ????????size?=?(mask_left_img.width?+?mask_right_img.width,?new_height)
          ????????mask_img?=?Image.new('RGBA',?size)
          ????????mask_img.paste(mask_left_img,?(0,?0),?mask_left_img)
          ????????mask_img.paste(mask_right_img,?(mask_left_img.width,?0),?mask_right_img)

          ????????#?rotate?mask
          ????????angle?=?np.arctan2(chin_bottom_point[1]?-?nose_point[1],?chin_bottom_point[0]?-?nose_point[0])
          ????????rotated_mask_img?=?mask_img.rotate(angle,?expand=True)

          ????????#?calculate?mask?location
          ????????center_x?=?(nose_point[0]?+?chin_bottom_point[0])?//?2
          ????????center_y?=?(nose_point[1]?+?chin_bottom_point[1])?//?2

          ????????offset?=?mask_img.width?//?2?-?mask_left_img.width
          ????????radian?=?angle?*?np.pi?/?180
          ????????box_x?=?center_x?+?int(offset?*?np.cos(radian))?-?rotated_mask_img.width?//?2
          ????????box_y?=?center_y?+?int(offset?*?np.sin(radian))?-?rotated_mask_img.height?//?2

          ????????#?add?mask
          ????????self._face_img.paste(mask_img,?(box_x,?box_y),?mask_img)

          ????????#?split?mask?and?resize
          ????????width?=?self._white_mask_img.width
          ????????height?=?self._white_mask_img.height
          ????????width_ratio?=?1.2
          ????????new_height?=?int(np.linalg.norm(nose_v?-?chin_bottom_v))

          ????????#?left
          ????????mask_left_img?=?self._white_mask_img.crop((0,?0,?width?//?2,?height))
          ????????mask_left_width?=?self.get_distance_from_point_to_line(chin_left_point,?nose_point,?chin_bottom_point)
          ????????mask_left_width?=?int(mask_left_width?*?width_ratio)
          ????????mask_left_img?=?mask_left_img.resize((mask_left_width,?new_height))

          ????????#?right
          ????????mask_right_img?=?self._white_mask_img.crop((width?//?2,?0,?width,?height))
          ????????mask_right_width?=?self.get_distance_from_point_to_line(chin_right_point,?nose_point,?chin_bottom_point)
          ????????mask_right_width?=?int(mask_right_width?*?width_ratio)
          ????????mask_right_img?=?mask_right_img.resize((mask_right_width,?new_height))

          ????????#?merge?mask
          ????????size?=?(mask_left_img.width?+?mask_right_img.width,?new_height)
          ????????mask_img?=?Image.new('RGBA',?size)
          ????????mask_img.paste(mask_left_img,?(0,?0),?mask_left_img)
          ????????mask_img.paste(mask_right_img,?(mask_left_img.width,?0),?mask_right_img)

          ????????#?rotate?mask
          ????????angle?=?np.arctan2(chin_bottom_point[1]?-?nose_point[1],?chin_bottom_point[0]?-?nose_point[0])
          ????????rotated_mask_img?=?mask_img.rotate(angle,?expand=True)

          ????????#?calculate?mask?location
          ????????center_x?=?(nose_point[0]?+?chin_bottom_point[0])?//?2
          ????????center_y?=?(nose_point[1]?+?chin_bottom_point[1])?//?2

          ????????offset?=?mask_img.width?//?2?-?mask_left_img.width
          ????????radian?=?angle?*?np.pi?/?180
          ????????box_x?=?center_x?+?int(offset?*?np.cos(radian))?-?rotated_mask_img.width?//?2
          ????????box_y?=?center_y?+?int(offset?*?np.sin(radian))?-?rotated_mask_img.height?//?2

          ????????#?add?mask
          ????????self._black_face_img.paste(mask_img,?(box_x,?box_y),?mask_img)

          ????def?_save(self):
          ????????path_splits?=?os.path.splitext(self.face_path)
          ????????#?new_face_path?=?self.save_path?+?'/'?+?os.path.basename(self.face_path)?+?'-with-mask'?+?path_splits[1]
          ????????#?new_face_path2?=?self.save_path2?+?'/'?+?os.path.basename(self.face_path)?+?'-binary'?+?path_splits[1]
          ????????new_face_path?=?self.save_path?+?'/'?+?os.path.basename(self.face_path)?+?'-with-mask'?+?path_splits[1]
          ????????new_face_path2?=?self.save_path2?+?'/'??+?os.path.basename(self.face_path)?+?'-binary'?+?path_splits[1]
          ????????self._face_img.save(new_face_path)
          ????????self._black_face_img.save(new_face_path2)

          ????#?????????print(f'Save?to?{new_face_path}')

          ????@staticmethod
          ????def?get_distance_from_point_to_line(point,?line_point1,?line_point2):
          ????????distance?=?np.abs((line_point2[1]?-?line_point1[1])?*?point[0]?+
          ??????????????????????????(line_point1[0]?-?line_point2[0])?*?point[1]?+
          ??????????????????????????(line_point2[0]?-?line_point1[0])?*?line_point1[1]?+
          ??????????????????????????(line_point1[1]?-?line_point2[1])?*?line_point1[0])?/?\
          ???????????????????np.sqrt((line_point2[1]?-?line_point1[1])?*?(line_point2[1]?-?line_point1[1])?+
          ???????????????????????????(line_point1[0]?-?line_point2[0])?*?(line_point1[0]?-?line_point2[0]))
          ????????return?int(distance)

          ????#?FaceMasker("/home/aistudio/data/人臉.png",?WHITE_IMAGE_PATH,?True,?'hog').mask()


          from?pathlib?import?Path

          images?=?Path("E:/play/FaceMask_CelebA-master/bbox_align_celeba").glob("*")
          cnt?=?0
          for?image?in?images:
          ????if?cnt?1:
          ????????cnt?+=?1
          ????????continue
          ????FaceMasker(image,?BLUE_IMAGE_PATH,?WHITE_IMAGE_PATH,?SAVE_PATH,?SAVE_PATH2,?'hog').mask()
          ????cnt?+=?1
          ????print(f"正在處理第{cnt}張圖片,還有{99?-?cnt}張圖片")

          掩膜生成代碼

          這部分其實(shí)就是對(duì)使用的口罩樣本的二值化,因?yàn)楹罄m(xù)要相關(guān)模型會(huì)用到

          import?os
          from?PIL?import?Image

          #?源目錄
          #?MyPath?=?'E:/play/FaceMask_CelebA-master/facemask_image/'
          MyPath?=?'E:/play/FaceMask_CelebA-master/save/masks/'
          #?輸出目錄
          OutPath?=?'E:/play/FaceMask_CelebA-master/save/Binarization/'


          def?processImage(filesoure,?destsoure,?name,?imgtype):
          ????'''
          ????filesoure是存放待轉(zhuǎn)換圖片的目錄
          ????destsoure是存在輸出轉(zhuǎn)換后圖片的目錄
          ????name是文件名
          ????imgtype是文件類型
          ????'''

          ????imgtype?=?'bmp'?if?imgtype?==?'.bmp'?else?'png'
          ????#?打開圖片
          ????im?=?Image.open(filesoure?+?name)
          ????#?=============================================================================
          ????#?????#縮放比例
          ????#?????rate?=max(im.size[0]/640.0?if?im.size[0]?>?60?else?0,?im.size[1]/1136.0?if?im.size[1]?>?1136?else?0)
          ????#?????if?rate:
          ????#?????????im.thumbnail((im.size[0]/rate,?im.size[1]/rate))
          ????#?=============================================================================

          ????img?=?im.convert("RGBA")
          ????pixdata?=?img.load()
          ????#?二值化
          ????for?y?in?range(img.size[1]):
          ????????for?x?in?range(img.size[0]):
          ????????????if?pixdata[x,?y][0]?90:
          ????????????????pixdata[x,?y]?=?(0,?0,?0,?255)

          ????for?y?in?range(img.size[1]):
          ????????for?x?in?range(img.size[0]):
          ????????????if?pixdata[x,?y][1]?136:
          ????????????????pixdata[x,?y]?=?(0,?0,?0,?255)

          ????for?y?in?range(img.size[1]):
          ????????for?x?in?range(img.size[0]):
          ????????????if?pixdata[x,?y][2]?>?0:
          ????????????????pixdata[x,?y]?=?(255,?255,?255,?255)
          ????img.save(destsoure?+?name,?imgtype)


          def?run():
          ????#?切換到源目錄,遍歷源目錄下所有圖片
          ????os.chdir(MyPath)
          ????for?i?in?os.listdir(os.getcwd()):
          ????????#?檢查后綴
          ????????postfix?=?os.path.splitext(i)[1]
          ????????name?=?os.path.splitext(i)[0]
          ????????name2?=?name.split('.')
          ????????if?name2[1]?==?'jpg-binary'?or?name2[1]?==?'png-binary':
          ????????????processImage(MyPath,?OutPath,?i,?postfix)


          if?__name__?==?'__main__':
          ????run()

          鏈接:https://blog.csdn.net/qq_52118067/article/details/124334872

          (版權(quán)歸原作者所有,侵刪)


          瀏覽 41
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日韩激情成人网 | 中文字幕直接干 | 青草视频在线观看视频 | 黄在线观看网站 | 欧美成人精品一二三区欧美风情 |