AidLux“人像抠图”案例源码详解 (Python)
生活随笔
收集整理的這篇文章主要介紹了
AidLux“人像抠图”案例源码详解 (Python)
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
“人像摳圖”案例源碼詳解 (Python)
seg_gui_meet.py用于人像摳圖
打開testpose人像姿態(tài)檢測案例
在VScode中進(jìn)入代碼編輯狀態(tài)。
導(dǎo)入相關(guān)庫
'''seg_gui_meet.py用于examples中的人體摳圖'''''' 導(dǎo)入基礎(chǔ)包作用詳解 ''' #導(dǎo)入包介紹開始#cvs包是Aid內(nèi)置的代替cv2的包,基本上cv2支持的函數(shù)cvs一樣支持,cvs包在X模式下和非X模式下一樣執(zhí)行 #cvs更多詳細(xì)介紹查看官網(wǎng)文檔OpenCVhttps://www.aidlearning.net/showdoc/web/#/5?page_id=45 from cvs import *#NumPy(Numerical Python) 是 Python 語言的一個(gè)擴(kuò)展程序庫, #支持大量的維度數(shù)組與矩陣運(yùn)算, #此外也針對數(shù)組運(yùn)算提供大量的數(shù)學(xué)函數(shù)庫。 #在機(jī)器學(xué)習(xí)算法中大部分都是調(diào)用Numpy庫來完成基礎(chǔ)數(shù)值計(jì)算的。 import numpy as np# tflite_gpu,GPU加速代碼由AID提供,TensorFlow Lite 支持多種硬件加速器。GPU 是設(shè)計(jì)用來完成高吞吐量的大規(guī)模并行工作的。 # 因此,它們非常適合用在包含大量運(yùn)算符的神經(jīng)網(wǎng)絡(luò)上,一些輸入張量可以容易的被劃分為更小的工作負(fù)載且可以同時(shí)執(zhí)行,通常這會(huì)導(dǎo)致更低的延遲。 # 在最佳情況下,用 GPU 在實(shí)時(shí)應(yīng)用程序上做推理運(yùn)算已經(jīng)可以運(yùn)行的足夠快,而這在以前是不可能的 import tflite_gpu #導(dǎo)入包介紹結(jié)束 ##############################################################################tflite=tflite_gpu.tflite() back_img_path=('res/dock_vbig.jpeg','res/taj_vbig.jpg','res/sunset_vbig.jpg','res/test.jpg','res/bg1.jpg','res/bg2.jpg','res/bg3.jpg','res/bg4.jpg')bgnd_mat=cv2.imread('res/dock_vbig.jpeg') mod=0構(gòu)建程序圖形化類
''' MyApp類用于構(gòu)建程序的圖形化 ''' class MyApp(App):#初始化函數(shù),self表示創(chuàng)建實(shí)例本身, *args傳遞可變參數(shù),__init__()的第一個(gè)參數(shù)永遠(yuǎn)是selfdef __init__(self, *args):#這是對繼承自父類的屬性進(jìn)行初始化。而且是用父類的初始化方法來初始化繼承的屬性。#也就是說,子類繼承了父類的所有屬性和方法,父類屬性自然會(huì)用父類方法來進(jìn)行初始化。#super() 函數(shù)是用于調(diào)用父類(超類)的一個(gè)方法。#super() 是用來解決多重繼承問題的,直接用類名調(diào)用父類方法在使用單繼承的時(shí)候沒問題,#但是如果使用多繼承,會(huì)涉及到查找順序(MRO)、重復(fù)調(diào)用(鉆石繼承)等種種問題。#MRO 就是類的方法解析順序表, 其實(shí)也就是繼承父類方法時(shí)的順序表super(MyApp, self).__init__(*args)def idle(self):#在每次更新循環(huán)中idle函數(shù)都會(huì)被調(diào)用self.aidcam.update()def main(self):#創(chuàng)建一個(gè)VBox容器,使用垂直方式(還有HBox水平盒子,以及widget)#定義變量main_container,它是整個(gè)圖形界面的主框架,用于包含其他APP中的控件,相當(dāng)于容器#gui.VBox這段代碼是在手機(jī)上畫出一個(gè)寬度為360px,高度為680px的程序主框架范圍。#style是它的樣式,margin:0 auto;相當(dāng)于margin:0 auto 0 auto;即上下是0,左右是自動(dòng)。#這時(shí)main_container中的元素會(huì)水平居中main_container = VBox(width=360, height=680, style={'margin':'0px auto'})main_container.css_width = "98%"#添加攝像頭控件#OpencvVideoWidget函數(shù)是在手機(jī) 畫一個(gè)用于顯示調(diào)用手機(jī)攝像頭拍攝圖像的框,寬度350px,高度400px,#將它賦值給self.aidcam,aidcam表示攝像頭控件。self.aidcam = OpencvVideoWidget(self, width=350, height=400)#設(shè)置main_container的寬度為手機(jī)屏幕的寬度的98%self.aidcam.css_width = "98%"self.aidcam.style['margin'] = '10px'#給aidcam控件一個(gè)標(biāo)記self.aidcam.identifier="myimage_receiver"main_container.append(self.aidcam)self.lbl = Label('點(diǎn)擊圖片選擇你喜歡的虛擬背景:')main_container.append(self.lbl)#創(chuàng)建一個(gè)HBox容器,使用水平方式#定義變量m_container,用于包含圖.寬度為360px,高度為130px#style是它的樣式,margin:0 auto;相當(dāng)于margin:0 auto 0 auto;即上下是0,左右是自動(dòng)。#這時(shí)m_container中的元素會(huì)水平居中m_container = HBox(width=360, height=130, style={'margin':'0px auto'})m_container.css_width = "98%"self.img11 = Image('/res:'+os.getcwd()+'/'+back_img_path[4], width=80,height=80, margin='10px')#被點(diǎn)擊則調(diào)用on_img11_clicked方法self.img11.onclick.do(self.on_img11_clicked)m_container.append(self.img11)self.img12 = Image('/res:'+os.getcwd()+'/'+back_img_path[5], width=80,height=80, margin='10px')self.img12.onclick.do(self.on_img12_clicked)m_container.append(self.img12)self.img13 = Image('/res:'+os.getcwd()+'/'+back_img_path[6],width=80, height=80, margin='10px')self.img13.onclick.do(self.on_img13_clicked)m_container.append(self.img13)self.img14 = Image('/res:'+os.getcwd()+'/'+back_img_path[7], width=80,height=80,margin='10px')self.img14.onclick.do(self.on_img14_clicked)m_container.append(self.img14)bottom_container = HBox(width=360, height=130, style={'margin':'0px auto'})bottom_container.css_width = "98%"self.img1 = Image('/res:'+os.getcwd()+'/'+back_img_path[0], width=80,height=80, margin='10px')self.img1.onclick.do(self.on_img1_clicked)bottom_container.append(self.img1)self.img2 = Image('/res:'+os.getcwd()+'/'+back_img_path[1], width=80,height=80, margin='10px')self.img2.onclick.do(self.on_img2_clicked)bottom_container.append(self.img2)self.img3 = Image('/res:'+os.getcwd()+'/'+back_img_path[2], width=80,height=80, margin='10px')self.img3.onclick.do(self.on_img3_clicked)bottom_container.append(self.img3)self.img4 = Image('/res:'+os.getcwd()+'/'+back_img_path[3], height=80, width=80,margin='10px')self.img4.onclick.do(self.on_img4_clicked)bottom_container.append(self.img4)#創(chuàng)建一個(gè)HBox容器,使用水平方式#定義變量b_container,用于包含按鈕.寬度為360px,高度為100px#style是它的樣式,margin:0 auto;相當(dāng)于margin:0 auto 0 auto;即上下是0,左右是自動(dòng)。#這時(shí)m_container中的元素會(huì)水平居中b_container = HBox(width=360, height=100, style={'margin':'0px auto'})b_container.css_width = "98%"#按鈕1,'摳圖穿越',self.bt1 = Button('摳圖穿越', width=100, height=30, margin='10px')#被點(diǎn)擊則調(diào)用on_button_pressed1方法self.bt1.onclick.do(self.on_button_pressed1)self.bt3 = Button('背景虛化', width=100, height=30, margin='10px')self.bt3.onclick.do(self.on_button_pressed3) #將m_container、bottom_container裝入main_containermain_container.append(m_container)main_container.append(bottom_container)#將bt1、bt3裝入b_containerb_container.append(self.bt1)b_container.append(self.bt3)#將b_container裝入main_containermain_container.append(b_container)return main_container'''各圖的受擊響應(yīng)方法'''def on_img1_clicked(self, widget):global bgnd_matbgnd=cv2.imread(back_img_path[0])bgnd_mat=cv2.resize(bgnd,(512, 512))def on_img2_clicked(self, widget):global bgnd_matbgnd=cv2.imread(back_img_path[1])bgnd_mat=cv2.resize(bgnd,(512, 512))def on_img3_clicked(self, widget):global bgnd_matbgnd=cv2.imread(back_img_path[2]) bgnd_mat=cv2.resize(bgnd,(512, 512))def on_img4_clicked(self, widget):global bgnd_matbgnd=cv2.imread(back_img_path[3]) bgnd_mat=cv2.resize(bgnd,(512, 512)) def on_img11_clicked(self, widget):global bgnd_matbgnd=cv2.imread(back_img_path[4])bgnd_mat=cv2.resize(bgnd,(512, 512))def on_img12_clicked(self, widget):global bgnd_matbgnd=cv2.imread(back_img_path[5])bgnd_mat=cv2.resize(bgnd,(512, 512))def on_img13_clicked(self, widget):global bgnd_matbgnd=cv2.imread(back_img_path[6]) bgnd_mat=cv2.resize(bgnd,(512, 512))def on_img14_clicked(self, widget):global bgnd_matbgnd=cv2.imread(back_img_path[7]) bgnd_mat=cv2.resize(bgnd,(512, 512)) '''各按鈕的受擊響應(yīng)方法'''#用于切換moddef on_button_pressed1(self, widget):global modmod=0def on_button_pressed3(self, widget):global modmod=2初始化處理函數(shù)(人體摳圖應(yīng)用啟動(dòng)時(shí)首先被調(diào)用)
''' 用于初始化處理,人體摳圖應(yīng)用啟動(dòng)時(shí)首先被調(diào)用 ''' def process():#設(shè)置自制UIcvs.setCustomUI()#輸入圖的shape寬高均為512(像素)#深度學(xué)習(xí)的圖片尺寸不用那么大,這里使用512*512w=512h=512input_shape=[w,h]#rgb3通道 1個(gè)float是32位也就是4字節(jié),每個(gè)數(shù)據(jù)4個(gè)字節(jié)#輸入數(shù)據(jù)數(shù)量 單位是字節(jié)inShape =[1 * w * h *3*4,]#4代表4個(gè)字節(jié),outShape就是輸出數(shù)據(jù)的數(shù)據(jù)量 單位是字節(jié)outShape= [1 * w*h*2*4,]#指定人像分割模型路徑model_path="res/portrait_segmentation.tflite"#4表示4個(gè)線程,0表示gpu,-1表示cpu,1表示NNAPIprint('gpu0:',tflite.NNModel(model_path,inShape,outShape,4,0))# cvs.VideoCapture(1)是調(diào)用手機(jī)前置攝像頭,如果是cvs.VideoCapture(0)就是調(diào)用手機(jī)后置攝像頭。camid=1cap=cvs.VideoCapture(camid)tgt_size=512global bgnd_matbgnd_mat=cv2.resize(bgnd_mat,(tgt_size, tgt_size))fcounts=0fframes=[None,None,None,None]fmax=[0,0,0,0]while True:#循環(huán)讀取攝像頭捕捉到的幀frame=cvs.read()#如果沒讀取到幀,就進(jìn)入下一次讀取循環(huán),直到讀取到幀if frame is None:continue#flip()的作用是使圖像進(jìn)行翻轉(zhuǎn),cv2.flip(filename, flipcode) #filename:需要操作的圖像,flipcode:翻轉(zhuǎn)方式,1水平翻轉(zhuǎn),0垂直翻轉(zhuǎn),-1水平垂直翻轉(zhuǎn)#如果是前置攝像頭,需要翻轉(zhuǎn)圖片,想象照鏡子的原理if camid==1:frame=cv2.flip(frame,1)#cv2.resize函數(shù)重定義大小img =cv2.resize(frame,(input_shape[0],input_shape[1]))frame=img# cv2.cvtColor(p1,p2) 是顏色空間轉(zhuǎn)換函數(shù),p1是需要轉(zhuǎn)換的圖片,p2是轉(zhuǎn)換成何種格式。# cv2.COLOR_BGR2RGB 將BGR格式轉(zhuǎn)換成RGB格式 # cv2.COLOR_BGR2GRAY 將BGR格式轉(zhuǎn)換成灰度圖片img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB).astype(np.float32)#歸一化img = img / 255# 由于fp16的值區(qū)間比fp32的值區(qū)間小很多,所以在計(jì)算過程中很容易出現(xiàn)上溢出(Overflow,>65504 )和下溢出(Underflow,<6x10^-8 )的錯(cuò)誤,# 溢出之后就會(huì)出現(xiàn)“Nan”的問題# 所以我們選擇fp32# 分配內(nèi)存并傳入數(shù)據(jù)tflite.setTensor_Fp32(img,input_shape[1],input_shape[1])# 啟動(dòng)tensorflow模型,使之開始運(yùn)行tflite.invoke()#參數(shù)0切換tflite模型pred = tflite.getTensor_Fp32(0)pred0=(pred[::2 ]).reshape(w,h)pred1=(pred[1::2]).reshape(w,h)back=((pred0))front=((pred1))mask=front-backmask[mask>0.0]=255mask[mask<=0.0]=0 # out1 = np.invert((back > 0.5) * 255)out2 = np.invert((front > 0.5) * 255)# out1 = np.uint8(out1)out2 = np.uint8(out2)mask=np.uint8(mask)out2=cv2.resize(out2,(256,256))mask = cv2.resize(mask,(256,256))out3 = cv2.ximgproc.jointBilateralFilter(out2, mask, 8, 100, 100) out3 = cv2.resize(out3,(512,512))# out3=mask.copy()out3=cv2.GaussianBlur(out3,(7,7),1) out3 = out3/255masksmall=cv2.erode(mask, (3,3),iterations=1);out3=cv2.merge([out3,out3,out3])# out3 = (cv2.cvtColor(out3, cv2.COLOR_GRAY2RGB))# out3 = out3/255# dst = frame*out3+(1-out3)*bgnd_mat# frame = cv2.resize(frame,(256,256))# bgnd_mat = cv2.resize(bgnd_mat,(256,256))if mod==0:dst = frame*out3+(1-out3)*bgnd_matelse :blur= cv2.GaussianBlur(frame, (27,27), 15) dst = frame*out3+(1-out3)*blur#顯示圖像cvs.imshow(dst)#讓程序休眠#time.sleep(秒數(shù)),其中“秒數(shù)”以秒為單位,可以是小數(shù),0.1秒則代表休眠100毫秒。sleep(1)程序入口
''' 入口 ''' if __name__ == '__main__':#initcv用于初始化initcv(process)startcv(MyApp) import apkneed import apkneed import apkneed總結(jié)
以上是生活随笔為你收集整理的AidLux“人像抠图”案例源码详解 (Python)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 水果店开在哪位置最好,水果店应开到什么位
- 下一篇: 打靶归来 - 详解upload-labs