1.OpenCV安裝
說到OpenCV的安裝,我想做人臉識別,網上找了很多教程,都涉及到OpenCV,而很多教程是基於Adrian Rosebrock的這篇教材Raspbian Stretch: Install OpenCV 3 + Python on your Raspberry Pi
剛剛看到這篇教程的時候,着實被它的流程嚇到了,步驟確實很多,以前裝P4開發環境的經歷告訴我,這個過程一定不會很順利。
於是我想按照這個教程復現一遍。
(1)安裝依賴
$ sudo apt-get update && sudo apt-get upgrade
$ sudo apt-get install build-essential cmake pkg-config
$ sudo apt-get install libjpeg-dev libtiff5-dev libjasper-dev libpng12-dev
$ sudo apt-get install libavcodec-dev libavformat-dev libswscale-dev libv4l-dev
$ sudo apt-get install libxvidcore-dev libx264-dev
$ sudo apt-get install libgtk2.0-dev libgtk-3-dev
$ sudo apt-get install libatlas-base-dev gfortran
$ sudo apt-get install python2.7-dev python3-dev
剛開始我是在現有的Raspberry Pi系統上直接安裝的,這之前已經配好了網站服務器、FTP服務器等前序博客所做的事情,系統已經不是那么“干凈”了。於是我運行上面第三條命令時就報錯了,提示要安裝的xxx依賴於xxx,但是xxx不會被安裝。百度了很多方法,都沒有辦法解決。差點就想放棄了,第二天決定重新燒錄一個干凈的系統,並且做好系統備份(很重要!!)
重新燒錄的系統果然“干凈”,一路順利,完成依賴的安裝。
(2)下載OpenCV源碼
$ cd ~
$ wget -O opencv.zip https://github.com/Itseez/opencv/archive/3.3.0.zip
$ unzip opencv.zip
$ wget -O opencv_contrib.zip https://github.com/Itseez/opencv_contrib/archive/3.3.0.zip
$ unzip opencv_contrib.zip
對網速要求比較高,所幸學校的網絡比較快。但是下載完畢,運行unzip解壓時報錯:Archive: opencv.zip End-of-central-directory signature not found. Either this file is not a zipfile, or it constitutes one disk of a multi-part archive. In the latter case the central directory and zipfile comment will be found on the last disk(s) of this archive.
按照網上的方法試着用jar解壓,可以成功,暫時沒有什么問題了。
(3)安裝pip
$ wget https://bootstrap.pypa.io/get-pip.py
$ sudo python get-pip.py
$ sudo python3 get-pip.py
(4)安裝Python虛擬機
$ sudo pip install virtualenv virtualenvwrapper
$ sudo rm -rf ~/.cache/pip
配置~/.profile,添加內容:
# virtualenv and virtualenvwrapper
export WORKON_HOME=$HOME/.virtualenvs
export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3
source /usr/local/bin/virtualenvwrapper.sh
使之生效
source ~/.profile
使用Python3 安裝虛擬機
$ mkvirtualenv cv -p python3
虛擬機完成安裝之后,后續的所有操作全部在虛擬機中進行。按照教程的說明,一定要看清楚命令行前面是否有(cv),以此作為是否在虛擬機的判斷!
以后要重新進入虛擬機,可運行下面的命令
$ source ~/.profile
$ workon cv
再次提醒:后續所有操作均在虛擬機中
安裝numpy
$ pip install numpy
(5)編譯OpenCV
$ cd ~/opencv-3.3.0/
$ mkdir build
$ cd build
$ cmake -D CMAKE_BUILD_TYPE=RELEASE \
-D CMAKE_INSTALL_PREFIX=/usr/local \
-D INSTALL_PYTHON_EXAMPLES=ON \
-D OPENCV_EXTRA_MODULES_PATH=~/opencv_contrib-3.3.0/modules \
-D BUILD_EXAMPLES=ON ..
按照教程提示,編譯前檢查Python相關配置,結果發現除了Interpreter,其他信息都沒有。。。
我按照教程的建議,再三確認了的確在虛擬環境中,然而無濟於事。。。
又想放棄了。
第三天,我突然想也許是OpenCV版本太久了,我到Github上看,最新的版本已經到了4.1.2,而且教程中也說了可以把3.3.0改成最新的版本。那既然其他環節都是最新的,那這個相應的也最新吧。於是我重新下載了4.1.2,這次unzip也十分順利!
再次運行編譯前的檢查,這次沒有問題了。
編譯前,按照教程,增大了交換空間CONF_SWAPSIZE=1024
$ sudo nano /etc/dphys-swapfile #虛擬機中sudo才可以修改
$ sudo /etc/init.d/dphys-swapfile stop
$ sudo /etc/init.d/dphys-swapfile start
$ make -j4 #開始編譯(耗時1個多小時)
安裝OpenCV
$ sudo make install
$ sudo ldconfig
之后按照教程,檢查OpenCV的安裝位置,然而按照教程的命令輸入,發現是空的!於是我去核對了一下編譯前檢查的結果,發現我的Python是3.7而不是教程用的3.5,問題解決!同時,我裝好的文件名只有cv,沒有后面的so
$ ls -l /usr/local/lib/python3.7/site-packages/
$ cd ~/.virtualenvs/cv/lib/python3.7/site-packages/
$ ln -s /usr/local/lib/python3.7/site-packages/cv2 cv2
(6)驗證安裝
$ source ~/.profile
$ workon cv
$ python
>>> import cv2
>>> cv2.__version__
'4.1.2'
>>>
成功了!記得備份系統!
2.使用OpenCV和Python控制攝像頭模塊
(1)picamera模塊安裝
之后繼續按照作者的另一個教程Accessing the Raspberry Pi Camera with OpenCV and Python完成攝像頭模塊picamera安裝,攝像頭的初始配置之前已經完成,再此不再贅述。
開啟虛擬機
$ source ~/.profile
$ workon cv
再次提醒:后續所有操作均在虛擬機中
安裝picamera
$ pip install "picamera[array]"
(2)在Python代碼中導入OpenCV控制攝像頭
按照教程給的示例代碼,驗證了Python控制攝像頭拍照的效果,發現照片完全是黑的,經過分析,調高了示例代碼中sleep的時間,讓攝像頭曝光時間增加,效果明顯。
# import the necessary packages
from picamera.array import PiRGBArray
from picamera import PiCamera
import time
import cv2
# initialize the camera and grab a reference to the raw camera capture
camera = PiCamera()
rawCapture = PiRGBArray(camera)
# allow the camera to warmup
time.sleep(3) #此處把0.1改成了3
# grab an image from the camera
camera.capture(rawCapture, format="bgr")
image = rawCapture.array
# display the image on screen and wait for a keypress
cv2.imshow("Image", image)
cv2.waitKey(0)
不得不說,這個大神寫的教程確實很贊。建議用“干凈”的系統安裝,可以適當提高OpenCV的版本。編譯過程很長,萬一失敗了,真的很打擊積極性,所幸成功了。
3.Raspberry Pi 的人臉識別
-
到此為止,我們已經完成在Raspberry Pi上安裝OpenCV和攝像頭模塊picamera,並且成功用導入了opencv的python代碼控制picamera,實現了拍攝一張照片的demo。在此基礎上,還可以做的事很多,比如人臉識別。
-
人臉識別可以用face_recogniztion這個開源模塊。
-
在前面創建的python虛擬環境cv中安裝dlib和face_recognition,使得能夠在cv中運行face_recognition。之后如果不進入虛擬環境cv,那么就無法運行face_recognition。
$ pip install dlib
$ pip install face_recognition
-
運行GitHub上face_recognition倉庫下的代碼
該示例是一個簡單的程序,僅調用了picamera,未用到opencv模塊。將代碼保存在py文件中,在虛擬機cv中運行,並保證代碼中的預先加載的人臉信息和代碼py文件在同一目錄。程序先獲取特定臉部信息,之后不斷讀取攝像頭當前捕獲的人像,顯示人像數,並和已有臉部信息進行比對,如果沒有匹配就是unknown person,如果匹配,就顯示人名。
運行結果:
-
同一個代碼倉庫下的另一個示例
該示例引入opencv來處理圖像信息,可以實時顯示當前攝像頭識別到的人臉信息
4.使用OpenCV的Docker容器運行運行人臉識別代碼
OpenCV安裝過於復雜,使用OpenCV容器直接省去了安裝步驟。
- Docker鏡像: sixsq/opencv-python,支持ARM
- 拉取基礎鏡像后,進入容器,安裝picamera[array]、dlib和face_recognition,commit更新容器建立新的鏡像
- 以上述新的鏡像為基礎,編寫Dockerfile,設置啟動時執行的命令:ENTRYPOINT["python3"],重新build最終的鏡像
- 啟動容器
$ docker run -it -v [本地代碼目錄]:[容器工作目錄] --device=/dev/vchiq --device=/dev/video0 --name [容器名] [鏡像名] [人臉識別python代碼]
- 運行結果:
雖然容器省去了費時費力的安裝配置,但是也會遇到新的問題:
- 直接以sixsq/opencv-python做Dockerfile,RUN安裝face_recognition報錯了,於是選擇直接進到容器內安裝再更新
- 運行容器報錯fail to open vchiq instance,討論后發現需要在啟動容器時使用參數--device=/dev/vchiq解決,具體見上述命令,讓容器使用Raspberry Pi的攝像頭
- 如果希望通過容器運行人臉識別相關的GUI圖形化程序,即上面的第二個例子,直接使用之前的方法是會報錯VIDEOIO ERROR: V4L: can't open camera by index 0,這可以通過--device=/dev/video0解決,另一個報錯關鍵的報錯是: cannot connect to X server
經過和學生探討,得到解決方法:參考Docker運行GUI軟件的方法,添加/tmp/.X11-unix掛載以及DISPLAY環境變量,並且用xhost命令允許所有用戶訪問X11服務,之后出錯X Error:BadDrawable (individ Pixmap or Window parameter 9),還要添加QT_X11_NO_MITSHM=1環境變量,最終修改容器啟動shell腳本如下:
(1)VNC訪問Raspberry Pi,在樹莓派上直接啟動
#sudo apt-get install x11-xserver-utils
xhost +
docker run -it \
-v [本地代碼目錄]:[容器工作目錄] \
-v /tmp/.X11-unix:/tmp/.X11-unix \
-e DISPLAY=$DISPLAY \
-e QT_X11_NO_MITSHM=1 \
--device=/dev/vchiq \
--device=/dev/video0 \
--name [容器名] \
[鏡像名] \
[人臉識別python代碼]
(2)ssh訪問Raspberry Pi,在pc上遠程啟動
#sudo apt-get install x11-xserver-utils
xhost +
docker run -it \
-v [本地代碼目錄]:[容器工作目錄] \
--net=host \
-v $HOME/.Xauthority:/root/.Xauthority \
-e DISPLAY=:10.0 \
-e QT_X11_NO_MITSHM=1 \
--device=/dev/vchiq \
--device=/dev/video0 \
--name [容器名] \
[鏡像名] \
[人臉識別python代碼]
VNC訪問Raspberry Pi的運行結果:
SSH訪問Raspberry Pi的運行結果: