一、啰嗦兩句
本文是圣誕節凌晨寫的,才發過來,我懶得改那些,所以時間方面就別糾結了..
這不圣誕節了,看著大家都說怎么做圣誕樹,我尋思,這玩意做出來你也只能放到電腦上撒,不開機那不就看不到了,送物件也不行啊,萬一物件不玩電腦呢,對吧,

但是圣誕節又要到了,那必須安排,高低得整兩手~

于是靈機一動,圣誕老頭不是還有頂帽子嗎? 這不得給物件也來一頂圣誕帽,
啊這…這顏色不太對勁
喔 不對,圣誕帽咱應該是紅色的
那這個就送給你們吧…
普通人都是PS批圖,咱們不一樣,作為技術人員,咱們得自己寫程式實作,這不比P圖有意思?

那今天就探索一下用 Python 來自動給女朋友照片添加圣誕帽吧~
什么?只想要軟體?可真刑,直接翻到最后吧,就再講講怎么打包成人人都能用的軟體,打包好的軟體我也放到最后,拿完記得點個贊,點完贊腰好腿好腎也好,女朋友也更愛你了~
二、流程思路
既然是要做成一個軟體,那么首先要寫界面才能操作,
然后準備一張女朋友和一頂圣誕帽子的圖片~
什么 沒有女朋友?emmmm…
那用你兄弟的吧,嘿嘿~
要把帽子給女朋友戴上,首先得識別她的面部五官,再把帽子給女朋友戴上,
差不多就這么幾個意思吧~
我們主要通過制作影像→界面開發→打包exe可執行檔案三部分,附帶一下人臉識別啥的~
三、要準備這些
這是咱們要用到的模塊和包,安裝方法寫在注釋了,
cv2 # pip install opencv-python dlib # pip install dlib numpy # pip install pandas PySimpleGUI # pip install PySimpleGui os # 系統自帶的,不用安裝
安裝模塊慢就加上國內的鏡像源,對照我下面的方法即可,
安裝這個dlib模塊的時候注意下,直接安裝是不成功的,不然很坑,首先它缺少Cmake和CBoot這兩個包,需要先安裝一下,
安裝 Cmake
# 正常下載方法 pip install cmake # 使用鏡像源下載方法,這樣更快, pip install cmake -i https://mirror.baidu.com/pypi/simple
安裝CBoot
# 正常下載方法 pip install boost # 使用鏡像源下載方法 pip install boost -i https://mirror.baidu.com/pypi/simple
然后再安裝dlib ,一般來說正常安裝即可,但不一般的是,可能會失敗,我這里都列舉出來,
# 1、直接pip安裝 pip install dlib # 2、使用鏡像源安裝 pip install dlib -i https://mirror.baidu.com/pypi/simple # 3、使用下載好的.whl包安裝 # 你下載好的檔案放在哪里,就在命令提示符視窗進入到你的那個檔案夾下操作,比如下載到C盤了,使用C:命令進入C盤后再執行, # python3.7 的包安裝 pip install dlib-19.17.99-cp37-cp37m-win_amd64.whl # python3.8 的包安裝 pip install dlib-19.19.0-cp38-cp38-win_amd64.whl # 這兩個包左側掃一下碼領,文章拉到最上面左側就看到了, # 4、如果還是失敗,就試試這個方法,我就是這樣安裝成功的, pip instal1 dlib==19.6.1
四、影像制作
關于圣誕帽的設定準備
準備一個PNG格式的圣誕帽圖片,png 圖片可以直接用 Alpha通道 作為掩膜使用,就算你是 jpg 格式,也要先轉換成 png 格式,不要直接重命名改格式,要么你找個圖片,截圖保存的格式改成png,要么找個軟體,比如PS去改一下,
找個差不多這樣的
為了能夠與 RGB 通道的頭像圖片進行運算,這里要將帽子影像分離成 RGB 通道影像和 alpha通道影像,
r,g,b,a = cv2.split(hat_img) rgb_hat = cv2.merge((r,g,b)) cv2.imwrite("hat_alpha.jpg",a)
分離后得到的 alpha通道影像長這樣:
然后來實作人臉識別
為了你們學習,我真的是嘔心瀝血,都把女朋友照騙用來測驗了~
來 ,上照騙…

既然是要做人臉識別,那么照騙就必須要真人正面照,不然你整個側面的也識別不了撒~
識別不了,那帽子它就會自動變色,越來越綠,飛到了你的頭頂…
接下來用 dlib 的正臉檢測器進行人臉檢測,用 dlib 提供的模型提取人臉的五個關鍵點,
# 人臉關鍵點檢測器 predictor_path = "shape_predictor_5_face_landmarks.dat" predictor = dlib.shape_predictor(predictor_path) # 正臉檢測器 detector = dlib.get_frontal_face_detector() # 正臉檢測 dets = detector(img, 1) # 如果檢測到人臉 if len(dets)>0: for d in dets: x,y,w,h = d.left(),d.top(), d.right()-d.left(), d.bottom()-d.top() # x,y,w,h = faceRect cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2,8,0) # 關鍵點檢測,5個關鍵點, shape = predictor(img, d) for point in shape.parts(): cv2.circle(img,(point.x,point.y),3,color=(0,255,0)) cv2.imshow("image",img) cv2.waitKey()
圖片列印效果
自動調節帽子大小
選取兩個眼角的點,求中心作為放置帽子的x方向的參考坐標,y 方向的坐標用人臉框上線的 y 坐標表示,
根據人臉檢測得到的人臉的大小調整帽子的大小,使得帽子大小合適,
所以啊,女朋友照片的臉有多正面做出來的效果就有多好,
# 選取左右眼眼角的點 point1 = shape.part(0) point2 = shape.part(2) # 求兩點中心 eyes_center = ((point1.x+point2.x)//2,(point1.y+point2.y)//2) # 根據人臉大小調整帽子大小 factor = 1.5 resized_hat_h = int(round(rgb_hat.shape[0]*w/rgb_hat.shape[1]*factor)) resized_hat_w = int(round(rgb_hat.shape[1]*w/rgb_hat.shape[1]*factor)) if resized_hat_h > y: resized_hat_h = y-1 # 根據人臉大小調整帽子大小 resized_hat = cv2.resize(rgb_hat,(resized_hat_w,resized_hat_h))
# 我還給大家準備了這些資料,直接在群里就可以免費領取了, # 一群:872937351 (群滿了的話加二群) # 二群:924040232 # python學習路線匯總 # 精品Python學習書籍100本 # Python入門視頻合集 # Python實戰案例 # Python面試題 # Python相關軟體工具/pycharm永久激活
帽子區域處理
首先把帽子的 alpha通道 作為 mask掩膜:
mask = cv2.resize(a,(resized_hat_w,resized_hat_h))
mask_inv = cv2.bitwise_not(mask)
然后從人像圖中去除需要添加帽子的區域:
# 帽子相對與人臉框上線的偏移量 dh = 0 dw = 0 # 原圖ROI # bg_roi = img[y+dh-resized_hat_h:y+dh, x+dw:x+dw+resized_hat_w] bg_roi = img[y+dh-resized_hat_h:y+dh,(eyes_center[0]-resized_hat_w//3):(eyes_center[0]+resized_hat_w//3*2)] # 原圖ROI中提取放帽子的區域 bg_roi = bg_roi.astype(float) mask_inv = cv2.merge((mask_inv,mask_inv,mask_inv)) alpha = mask_inv.astype(float)/255 # 相乘之前保證兩者大小一致(可能會由于四舍五入原因不一致) alpha = cv2.resize(alpha,(bg_roi.shape[1],bg_roi.shape[0])) # print("alpha size: ",alpha.shape) # print("bg_roi size: ",bg_roi.shape) bg = cv2.multiply(alpha, bg_roi) bg = bg.astype('uint8')
提取后效果圖
再提取帽子區域
hat = cv2.bitwise_and(resized_hat,resized_hat,mask = mask)
效果圖
給女朋友戴帽子
帽子處理好了就該給她戴上去了,把提取的圣誕帽區域和圖片中提取的區域相加后放到原圖中去,
注意:相加之前resize一下保證兩者大小一致,
# 相加之前保證兩者大小一致(可能會由于四舍五入原因不一致) hat = cv2.resize(hat,(bg_roi.shape[1],bg_roi.shape[0])) # 兩個ROI區域相加 add_hat = cv2.add(bg,hat) # cv2.imshow("add_hat",add_hat) # 把添加好帽子的區域放回原圖 img[y+dh-resized_hat_h:y+dh,(eyes_center[0]-resized_hat_w//3):(eyes_center[0]+resized_hat_w//3*2)] = add_hat
最后的效果圖
五、軟體界面
效果展示
女朋友太多了,這里就選用現女友了,免得這些前女友又回來找我,
GUI界面實作代碼
import PySimpleGUI as sg import os.path import cv2 file_list_column = [ [sg.Submit('立即戴帽', key='Go', size=(15, 1)), sg.Cancel('溜了溜了', key='Cancel', size=(15, 1))], [ sg.Text("圖片存放位置"), sg.In(size=(25, 1), enable_events=True, key="-FOLDER-"), sg.FolderBrowse('選擇'), ], [ sg.Listbox( values=[], enable_events=True, size=(40, 20), key="-FILE LIST-" ) ] ] image_viewer_column = [ [sg.Text("從左邊女朋友中選擇一個:")], [sg.Image(key="-IMAGE-")] ] layout = [ [ sg.Column(file_list_column), sg.VSeperator(), sg.Column(image_viewer_column), ] ] window = sg.Window("給女朋友添加一個圣誕帽", layout) filename = '' while True: event, values = window.read() if event == "Cancel" or event == sg.WIN_CLOSED: break if event == "-FOLDER-": folder = values["-FOLDER-"] try: file_list = os.listdir(folder) except: file_list = [] fnames = [ f for f in file_list if os.path.isfile(os.path.join(folder, f)) and f.lower().endswith((".jpg", ".png")) ] window["-FILE LIST-"].update(fnames) elif event == "-FILE LIST-": try: filename = os.path.join(values["-FOLDER-"], values["-FILE LIST-"][0]) if filename.endswith('.jpg'): im = cv2.imread(filename) cv2.imwrite(filename.replace('jpg', 'png'), im) window["-IMAGE-"].update(filename=filename.replace('jpg', 'png')) except Exception as e: print(e) elif event == "Go": try: # output = add_hat(filename) # 展示效果 # cv2.imshow("output",output) # cv2.waitKey(0) # cv2.imwrite("output.png",output) # print(output) window["-IMAGE-"].update(filename='output.png') except: print('OMG!添加失敗了!') cv2.destroyAllWindows()
界面是用 PySimpleGUI 框架做的,分為左右兩部分,左邊是確定/取消/檔案夾選擇/圖片檔案串列,右邊是圖片展示欄,
選擇好存放照片的檔案夾后,你準備好的女朋友照片會在圖片檔案串列顯示出來,這里圖片是沒限制的,JPG/PNG格式的都可以用,
選擇串列里的女朋友點一下,就可以在右邊顯示出來照片,
你選中哪張,后面就給誰帶上了帽子…

那么為什么這里就不限制圖片格式了呢?
因為 PySimpleGUI 的圖片展示默認只支持 png 格式的,這部分我加了一個判斷,如果是 jpg 格式的圖片,就用 cv2 轉換成 png 格式再進行展示,
關鍵步驟到這里已經完成了,然后將兩部分代碼整合,
在 GUI 界面上點一下 “立即戴帽” 按鈕時,后臺接收到圖片的路徑,傳遞給我們的圖片處理函式,在處理完后將圖片保存在檔案夾下,并更新在 GUI 界面右邊的展示的圖片即可,
最終效果展示

六、打包為exe軟體
依然是用常用的 pyinstaller 打包,模塊安裝我就不講了吧,前面裝了好幾個了,再不會拉出去關禁閉~
那我說快點
win+r打開搜索,輸入cmd,點擊確定打開命令提示符視窗,輸入pip install pyinstaller 即可安裝模塊,
安裝成功后不要關閉命令提示符視窗,輸入代碼存放的盤,比如C盤,輸入C: ,把目錄切換到你的代碼所在的盤,
在輸入cd 加上存放代碼的檔案夾名字
然后在命令提示符視窗輸入 pyinstaller + 空格 + -F -w + 你的代碼檔案名字.py
-F打包程式,-w解決打包運行軟體閃黑框,-F一定要用大寫F,否則可能會出錯,
程式運行有圣誕帽圖片和人臉識別訓練集這兩個依賴檔案,需要將這兩個檔案放入這個 EXE 檔案所在的檔案夾下,
七、寫在后面
不僅僅是圣誕帽,你們想換啥都可以去嘗試一下,搞不出來的話,拉到最上面左側二維碼了解一下,
還有軟體、包、等等都在那了,
兄弟們,你們看看時間,為了你們趕在女朋友起床之前做出來,我起早貪黑的寫出來了,這不得點個贊再走!


轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/394928.html
標籤:Python
