我是如何用樹莓派 + Docker 輕鬆實現人臉識別應用的?

  • 2019 年 10 月 25 日
  • 筆記

人臉識別技術已經被廣泛應用在眾多場景中。今天我們將利用Docker容器在樹莓派上快速打造一個人臉識別應用。

本文使用

https://github.com/ageitgey/facerecognition 開源框架,基於 dlib(Deep Metric Learning)支援人臉識別功能。dlib 在Labeled Faces in the Wild 測試基準上的準確率達到 99.38%。facerecognition的應用開發極為簡單,只用幾行 Python 命令行就可以輕鬆實現人臉識別應用,而且也提供了樹莓派的支援。

在Raspberry Pi 2+ 平台安裝face_recognition的指南如下:

https://gist.github.com/ageitgey/1ac8dbe8572f3f533df6269dab35df65

樹莓派是Geek們最愛的開發板,其原因就在於成熟的軟體生態和豐富的I/O介面,然而在樹莓派上搞深度學習應用開發並非易事。

  1. 很多包需要下載編譯,以孱弱的Raspberry Pi編譯應用,需要極大的耐心。
  2. 然而開源的深度學習框架很多,不同類庫的依賴不同,有些會互相衝突,比如有些需要Python 2.7,有些則依賴 3.x。雖然我們可以用virtualenv對Python環境進行隔離,但是對於一些系統級的依賴衝突就不好辦了。在漫長構建中遇到依賴導致編譯失敗,讓人非常有挫敗感。
  3. 如果需要在另外一塊板上部署相同應用,整個過程需要重新來過。

下面我們將利用Docker來構建打包應用鏡像,這樣可以一次構建到處運行,也可以充分利用Dockerfile自帶的分層能力,可以方便地調整依賴包,這樣在開發部署過程中格外高效。

樹莓派上部署人臉識別應用

得益於樹莓派和Docker安裝部署人臉識別開發環境非常簡單:

1、在 Raspberry PI 3 安裝最新的 Raspbian。

2、執行如下命令安裝最新的 Docker Engine 社區版。

# Install Docker  curl -sSL https://get.docker.com | sh  # Add pi to Docker group  sudo usermod pi -aG docker  # config cgroup for Docker  echo Adding " cgroup_enable=cpuset cgroup_enable=memory" to /boot/cmdline.txt  sudo cp /boot/cmdline.txt /boot/cmdline_backup.txt  # if you encounter problems, try changing cgroup_memory=1 to cgroup_enable=memory.  orig="$(head -n1 /boot/cmdline.txt) cgroup_enable=cpuset cgroup_memory=1"  echo $orig | sudo tee /boot/cmdline.txt  sudo reboot  

3、安裝 Raspberry Camera ,我用的是Camera Module2 注意藍色膠帶對著乙太網介面方向。並通過 raspi-config 命令來開啟 camera 模組。

4、在容器中開發、運行facerecognition應用,我們可以利用如下的命令來啟動容器。其包含了facerecognition 的完整開發環境和示例應用。下文會介紹鏡像的具體資訊。

docker run -it       --name face_recognition       --device /dev/vchiq         registry.cn-hangzhou.aliyuncs.com/denverdino/face_recognition         bash  

其中關鍵之處就在於將攝影機設備/dev/vchiq掛載到容器內部,這樣就可以讓容器中的應用來拍攝照片和影片。

大家可以利用 docker cp 命令,向容器中拷貝文件,比如照片,或者在容器中利用 nano 等命令來編輯程式碼。

人臉識別應用解析

基於 examples/facereconraspberry_pi.py 我修改了一個面部識別應用供參考,其實現如下:

# This is a demo of running face recognition on a Raspberry Pi. # This program will print out the names of anyone it recognizes to the console. # To run this, you need a Raspberry Pi 2 (or greater) with face_recognition and # the picamera[array] module installed. # You can follow this installation instructions to get your RPi set up: # https://gist.github.com/ageitgey/1ac8dbe8572f3f533df6269dab35df65 import face_recognition import picamera import numpy as np known_face_encodings = [] names = [] def load_face_encoding(name, file_name): image = face_recognition.load_image_file(file_name) face_encoding = face_recognition.face_encodings(image)[0] known_face_encodings.append(face_encoding) names.append(name) # Get a reference to the Raspberry Pi camera. # If this fails, make sure you have a camera connected to the RPi and that you # enabled your camera in raspi-config and rebooted first. camera = picamera.PiCamera() camera.resolution = (320, 240) output = np.empty((240, 320, 3), dtype=np.uint8) # Load a sample picture and learn how to recognize it. print("Loading known face image(s)") load_face_encoding("Yi Li", "yili.jpg") load_face_encoding("Zhang Kai", "zhangkai.jpg") load_face_encoding("Che Yang", "cheyang.jpg") # Initialize some variables face_locations = [] face_encodings = [] while True: print("Capturing image.") # Grab a single frame of video from the RPi camera as a numpy array camera.capture(output, format="rgb") # Find all the faces and face encodings in the current frame of video face_locations = face_recognition.face_locations(output) print("Found {} faces in image.".format(len(face_locations))) face_encodings = face_recognition.face_encodings(output, face_locations) # Loop over each face found in the frame to see if it's someone we know. for face_encoding in face_encodings: # See if the face is a match for the known face(s) matches = face_recognition.face_distance(known_face_encodings, face_encoding) name = "<Unknown Person>" min_distance = min(matches) if min_distance < 0.6: i = matches.argmin() name = names[i] print("I see someone named {}!".format(name))

首先,程式碼中通過如下方法,載入指定人名的頭像照片,您可以把自己、好基友的照片加入人臉庫。

load_face_encoding("Yi Li", "yili.jpg")  

然後,攝影機持續拍攝照片,如下方法會檢測到照片中的面部資訊。

face_locations = face_recognition.face_locations(output)  ...  face_encodings = face_recognition.face_encodings(output, face_locations)  

然後,對比面部資訊和已知人臉資訊的相似度,如果超過一個閾值,返回最為相近的同學名稱,這樣一個簡單的人臉識別應用就完成了,是不是非常簡單?

matches = face_recognition.face_distance(known_face_encodings, face_encoding)  

運行的結果如下:

# python3 facerec_on_raspberry_pi.py  Loading known face image(s)  Found 0 faces in image.  Capturing image.  Found 0 faces in image.  Capturing image.  Found 1 faces in image.  I see someone named Yi Li!  ...  

效果符合預期,但是受限於樹莓派的處理能力,還遠遠達不到實時的效果,識別出人臉需要幾秒的延遲。但是已經可以應用於一些簡單的場景了,大家自己去開腦洞自己開發吧。

大家如果需要訂製自己的人臉識別應用,可以從 https://github.com/denverdino/facerecognitionpi 獲得相關的Dockerfile,來根據自己的需要構建一個完整的應用。

FROM resin/raspberry-pi-python:3  COPY pip.conf /root/.pip/pip.conf  RUN apt-get -y update  RUN apt-get install -y --fix-missing       build-essential       cmake       gfortran       git       wget       curl       graphicsmagick       libgraphicsmagick1-dev       libatlas-dev       libavcodec-dev       libavformat-dev       libboost-all-dev       libgtk2.0-dev       libjpeg-dev       liblapack-dev       libswscale-dev       pkg-config       python3-dev       zip       && apt-get clean && rm -rf /tmp/* /var/tmp/*  RUN python3 -m ensurepip --upgrade && pip3 install --upgrade picamera[array] dlib  # The rest of this file just runs an example script.  # If you wanted to use this Dockerfile to run your own app instead, maybe you would do this:  # COPY . /root/your_app_or_whatever  # RUN cd /root/your_app_or_whatever &&   #     pip3 install -r requirements.txt  # RUN whatever_command_you_run_to_start_your_app  RUN git clone --single-branch https://github.com/ageitgey/face_recognition.git  RUN cd /face_recognition &&       pip3 install -r requirements.txt &&       python3 setup.py install  CMD cd /face_recognition/examples &&       python3 recognize_faces_in_pictures.py  

大家如果希望將自己應用打包到Docker鏡像中,可以添加修改Dockerfile,我就不多說了。

最後來曬一下我的樹莓派3配置,除了Camera之外還加裝了一個液晶顯示器,通過GPIO驅動,可以方便地通過編程來顯示CPU/Memory/溫度等各種資訊。

總結

容器技術已經越來越多運用於IoT、邊緣計算等場景,利用容器可以極大地簡化智慧設備的應用生命周期管理。今天我們演示了一個運行在樹莓派上的人臉識別應用。本文實例程式碼可以從 https://github.com/denverdino/facerecognitionpi 獲取。

2017我們見證了容器技術的快速發展,Kubernetes,Containerd/OCI等容器技術標準得到了生態的共識,這也將催生更多的應用創新。2018我們不但可以看見容器在企業用戶的生產環境中被廣泛應用,容器技術也將無處不在,給我們更多的驚喜。

作者 | 易立

原文 | https://yq.aliyun.com/articles/346459