基于Docker的交互式人脸识别应用
本文將介紹如何開發一個交互式應用程序,利用Adam Geitgey的人臉識別框架,從攝像頭或網絡攝像頭設備識別人臉。
為了創建一個交互式應用程序,我們將使用Tkinter,Docker將用于確保一個包含所有必要依賴項的隔離環境。本文可以作為你自己項目的起點,因為使用哪些框架和庫并不重要。
了解如何通過Docker創建一個利用攝像頭設備、GPU加速和深度學習框架的交互式應用程序有很多可能性。
如果只希望通過Docker運行GUI,我創建了本文,你可以按照以下內容進行操作:
https://towardsdatascience.com/empowering-docker-using-tkinter-gui-bf076d9e4974
如果你想立即運行應用程序,可以下載我的Github存儲庫,并按照本文末尾的“運行應用程序”部分進行操作。
閱讀教程
在本文中,將介紹應用程序中的腳本,之后將介紹運行應用程序的教程。文章將按照以下順序進行。
目錄
環境
應用程序概述
Docker
編程
攝像設備
計算機視覺
Shell腳本
運行應用程序
結論
環境
此應用程序僅使用Linux進行了測試,但是,它的工作原理應該與其他操作系統類似,其中一些參數可能不同,例如在運行Docker時。
對于先決條件,你應該安裝攝像頭或網絡攝像頭、Docker、CUDA和CuDNN。我已使用以下方法測試了應用程序:
Docker 20.10.8
CUDA 11.4
CuDNN 8.2.2
OS:Manjaro 21.1.2 Phavo
GPU:NVIDIA GeForce GTX 1080 Ti
攝像頭設備:羅技網絡攝像頭C930e
目錄結構
本項目的目錄結構如下所示。你可以事先創建這些文件,或者直接從我的Github存儲庫下載所有文件。
此外,你需要在dataset目錄中創建自己的目錄,并插入所需的圖像。在我的例子中,如下所示,我在Kasper目錄中添加了四個圖像。你在不同場景中為同一個人添加的圖像越多,你的預測就越可靠。關于腳本,本文將介紹它們的內容。
注意:encodings.pkl將在以后自動生成。
應用程序的目錄結構:
應用程序概述
該應用程序包含一個GUI,其中有一個用于顯示相機設備輸出的面板。此外,還有一個用于激活/禁用人臉識別的按鈕。
當前打開人臉識別的應用程序。
Docker
為了創建一個安裝人臉識別、OpenCV、Dlib、Python等的隔離環境,使用了以下Docker代碼。
Dockerfile創建隔離環境:
FROM?nvidia/cuda:11.4.1-cudnn8-devel-ubuntu20.04ARG?DEBIAN_FRONTEND=noninteractive#?Install?dependencies RUN?apt-get?update?-y RUN?apt-get?install?-y?\git?\cmake?\libsm6?\libxext6?\libxrender-dev?\python3?\python3-pip?\gcc?\python3-tk?\ffmpeg?\libopenblas-dev?\?liblapack-dev#?Install?dlib RUN?git?clone?https://github.com/davisking/dlib.git?&&?\cd?dlib?&&?\mkdir?build?&&?\cd?build?&&?\cmake?..?-DDLIB_USE_CUDA=1?-DUSE_AVX_INSTRUCTIONS=1?&&?\cmake?--build?.?&&?\cd?..?&&?\python3?setup.py?install?#?Install?Face?Recognition?and?OpenCV RUN?pip3?install?face_recognition?opencv-pythonWORKDIR?/face_recognition/appTkinter
為了創建一個可由用戶控制的交互式GUI以啟用和禁用人臉識別,使用Tkinter庫。下面的代碼創建了先前顯示的GUI。
主腳本,用于創建GUI并允許人臉識別。
import?tkinter?as?tk from?src.facevision?import?FaceVision from?src.videostream?import?VideoStreamif?__name__?==?'__main__':#?Tkinter窗口root_window?=?tk.Tk()#?Window設置root_window.title('Face?Recognition')root_window.geometry('500x540')??#?widthxheight+x+yroot_window.configure(background='#353535')#?攝像頭可視化面板panel?=?tk.Label(root_window)panel.pack(side='top',?fill='none')#?FaceVision初始化face_vision?=?FaceVision()#?Webcam初始化vs?=?VideoStream(panel=panel,?face_vision=face_vision)vs.stream()#?人臉識別按鈕button_face_recognition?=?tk.Button(root_window,?text='Activate?Face?Recognition',?command=lambda:?face_vision.change_facerec_state(button_face_recognition))button_face_recognition.pack()#?主循環root_window.mainloop()攝像設備
為了從相機設備獲取圖像并更新Tkinter GUI,可以使用以下腳本。
在第7行中,它使用函數VideoCapture by OpenCV,其中的參數應與你的設備相對應。默認相機id通常為0,但是,如果不起作用,可以嘗試使用1或-1。
如果你希望使用視頻,你應該能夠用視頻路徑替換設備id,但可能需要進行一些其他調整。在第26行,它在一毫秒后再次調用函數本身。
import?cv2 from?PIL?import?Image,?ImageTkclass?VideoStream():def?__init__(self,?panel,?face_vision):self.cap?=?cv2.VideoCapture(0)?#?參數應該對應于你的設備self.panel?=?panelself.face_vision?=?face_visiondef?stream(self):#?從相機獲取圖像_,?frame?=?self.cap.read()img?=?cv2.cvtColor(frame,?cv2.COLOR_BGR2RGB)#?人臉識別img?=?self.face_vision.process_image(img=img)#?Tkinterimg?=?Image.fromarray(img)tk_img?=?ImageTk.PhotoImage(img)self.panel.imgtk?=?tk_imgself.panel.configure(image=tk_img)#?再次運行self.panel.after(ms=1,?func=self.stream)計算機視覺
與大多數計算機視覺應用程序相反,在大多數計算機視覺應用程序中,你通過展示數百個類的示例來訓練模型以對所需類進行分類,而在人臉識別中,你可以使用深度度量學習。
通過深度度量學習,你可以訓練模型來描述所需對象,而不是預測它是哪個類。在我們的例子中,我們使用它來提供一個特征向量,一種128維編碼,它使用實數來描述每個人臉。教授一個模型來描述人臉而不是預測一個特定的人是一個優勢,因為如果想要識別一個新的人,就不需要對模型進行再訓練。
相反,我們應該簡單地保存模型可以訪問的新人的編碼。我們將在本文后面獲得這些編碼。使用框架人臉識別,我們不必從頭開始訓練模型,而是使用通過人臉識別提供的已經訓練過的模型。如果想要進一步探索人臉識別領域,《人臉識別框架》詳細闡述了這一主題:
https://medium.com/@ageitgey/machine-learning-is-fun-part-4-modern-face-recognition-with-deep-learning-c3cffc121d78
數據集與編碼器
為了使模型能夠識別人臉,需要一個包含人臉編碼的pickle文件。要實現這一點,正如前面在“目錄結構”一節中提到的,你必須在目錄數據集中創建一個包含所需人員姓名的目錄。之后,編碼器應包含以下代碼。
在這段代碼中,我們遞歸地獲取dataset目錄中每個人的所有圖像。通過使用人臉識別框架,我們定位人臉并為每幅圖像提取編碼。
構造包含數據集編碼的pickle文件:
import?face_recognition import?cv2 from?pathlib?import?Path import?pickleif?__name__?==?'__main__':print('Starting?Encoding..')data?=?{'names':?[],?'encodings':?[]}#?數據集路徑path?=?Path.cwd()?/?'./data/dataset/'#?瀏覽每一張圖片for?file_name?in?path.rglob('*.jpg'):#?從數據集讀取圖像img?=?cv2.imread(str(file_name))img?=?cv2.cvtColor(img,?cv2.COLOR_BGR2RGB)#?定位人臉face_location?=?face_recognition.face_locations(img,?number_of_times_to_upsample=1,?model='cnn')#?編碼的人臉encoding?=?face_recognition.face_encodings(face_image=img,?known_face_locations=face_location,?model='small')#?保存信息data['names'].append(file_name.parent.name)data['encodings'].append(encoding)#?在pickle文件中保存編碼with?open('./data/encodings.pkl',?'wb')?as?f:pickle.dump(data,?f)print('Completed?Encoding!')人臉識別
為了識別人臉,將使用以下代碼。為了總結代碼,它使用來自我們的相機設備的圖像,檢測人臉,為每個人臉提取128維編碼,然后將新編碼與我們的編碼數據集進行比較。
為了進行比較,它會檢查新編碼的特征與我們編碼的數據集之間的距離,如果特征的距離小于閾值參數,則該特征將獲得投票。為了找到最佳匹配,我們只需選擇得票最多的人。如果簡單的解決方案不夠,你可以實現更強大的分類器。
更具體地說,視頻流為每一幀調用函數process_image,該函數完成了實現人臉識別所需的所有工作。在第43–45行中,可以調整比較的閾值參數。閾值越低,比較就越嚴格。此外,在第48-51行中,最高投票數也可以調整,以增加或減少嚴格程度。
計算機視覺部分,基于人臉識別框架:
Shell腳本(警告)
為了簡化操作,請創建一個shell腳本,該腳本使用以下參數運行xhost和Docker。
對于xhost,啟用對所有人的訪問,然后在卸載Docker容器后禁用它。在這個Docker命令中,我們共享GPU,顯示GUI。
警告:如果在本地運行,則使用xhost和這些Docker參數不應成為問題。但是,如果在生產中使用,則應增強安全性,這在此處是推薦的。
自動啟用/禁用xhost并運行Docker容器:
#!/bin/bash xhost?+ docker?run?--gpus?all?--device?/dev/nvidia0?--device?/dev/nvidia-uvm?--device?/dev/nvidia-uvm-tools?\--device?/dev/nvidiactl?\-it?\--rm?\-e?DISPLAY=$DISPLAY?\-v?/tmp/.X11-unix:/tmp/.X11-unix:rw?\-v?$(pwd):/face_recognition?\--device=/dev/video0:/dev/video0?\face_recognition xhost?-運行應用程序
構建Docker鏡像:docker build -t facerecognition_gui
使shell腳本可執行:chmod +x ./run.sh
運行shell腳本:./run.sh
在Docker容器中,創建編碼的數據集(確保圖像位于數據集目錄中的目錄中):python3 encoder.py
運行應用程序:python3 gui.py
現在可以啟用人臉識別。
注意:要分離/退出Docker容器,請按ctrl-D
結論
在本文中,你已經了解了如何將GUI、攝像頭設備、GPU與Docker一起使用。了解如何結合這些,提供了許多可用于學術和商業目的的可能性。
此外,使用相同的策略,通過Docker共享etc設備,你應該能夠利用其他庫和框架,而不必經歷環境問題。
☆ END ☆
如果看到這里,說明你喜歡這篇文章,請轉發、點贊。微信搜索「uncle_pn」,歡迎添加小編微信「 woshicver」,每日朋友圈更新一篇高質量博文。
↓掃描二維碼添加小編↓
總結
以上是生活随笔為你收集整理的基于Docker的交互式人脸识别应用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《Python程序设计(第3版)》[美]
- 下一篇: #Objective - C - UI-