### ex4-1 ### # 安裝 virtualenv 和 virtualenvwrapper 套件 $ sudo pip3 install virtualenv # 也可使用 sudo python3 -m pip install virtualenv $ sudo pip3 install virtualenvwrapper # 也可使用 sudo python3 -m pip install virtualenvwrapper # 使用 pip3 執行檢查目前安裝的 Python 3 模組,檢查是否有安裝 virtualenv 和 virtualenvwrapper $ pip3 list ### ex4-2 ### # 編輯 .bashrc 檔,新增路徑設定,以便可以執行 virtualenvwrapper $ sudo nano ~/.bashrc # 加入下列三行到 .bashrc export WORKON_HOME=$HOME/.virtualenvs export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3 source /usr/local/bin/virtualenvwrapper.sh # 重新載入更新的路徑設定 $ source ~/.bashrc ### ex4-3 ### # 建立一個新的 Python 3 虛擬環境 $ mkvirtualenv test -p python3 # 關閉目前虛擬環境 $ deactivate # 顯示已建立的虛擬環境 $ lsvirtualenv # 啟動虛擬環境 $ workon test # 移除虛擬環境 $ rmvirtualenv test # 複製虛擬環境 $ cpvirtualenv test (來源) test1 (目的) ### ex4-4 ### # 檢視虛擬環境安裝的 Python 套件清單 (test) $ pip list ### ex4-5 ### # 步驟一:更新與升級已安裝的套件 $ sudo apt-get update # 軟體資料庫同步,升級前都先做 $ sudo apt-get upgrade # 升級已安裝的軟體 ### ex4-6 ### # 步驟二:安裝 OpenCV 的相關支援套件 # 安裝 HDF (Hierarchical Data Format version 5) 資料集的套件 $ sudo apt-get install -y libhdf5-dev # 安裝矩陣運算和 JPEG-2000 圖片函式庫 $ sudo apt-get install -y libatlas-base-dev $ sudo apt-get install -y libjasper-dev # 安裝 QT GUI 圖形介面的套件 $ sudo apt-get install -y libqtgui4 $ sudo apt-get install -y libqt4-test $ sudo apt-get install -y python3-pyqt5 ### ex4-7 ### # 步驟三:新增名為 opencv 的 Python 3 虛擬環境 $ mkvirtualenv opencv -p python3 # 檢查目前安裝的 Python 模組 (opencv) $ pip list ### ex4-8 ### # 步驟四:在虛擬環境安裝支援的 Python 套件 (opencv) $ pip install numpy==1.21.4 (opencv) $ pip install matplotlib (opencv) $ pip install imutils ### ex4-9 ### # 步驟五:在 Python 的虛擬環境中,安裝 OpenCV (opencv) $ pip install opencv-python==4.5.4.60 (opencv) $ pip install opencv-contrib-python==4.5.4.60 # 輸入指令來檢視虛擬環境安裝的套件清單: (opencv) $ pip list ### ex4-10 ### # 更新當前安裝的軟件包。 $ sudo apt-get update $ sudo apt-get upgrade # 安裝編譯套件 $ sudo apt-get install build-essential cmake # 安裝圖片套件 $ sudo apt-get install libjpeg-dev libpng-dev libtiff5-dev libjasper-dev # 安裝影片套件 $ sudo apt-get install libavcodec-dev libavformat-dev libswscale-dev libv4l-dev $ sudo apt-get install libxvidcore-dev libx264-dev # 安裝 GTK 套件 $ sudo apt-get install libgtk-3-dev libcanberra-gtk* # 最佳化套件 $ sudo apt-get install libatlas-base-dev gfortran # 樹莓派加裝 $ sudo apt-get install at-spi2-core # 安裝 Python 開發套件 $ sudo apt-get install python-dev python3-dev # 安裝 numpy 函式庫,確認 Python 2 與 Python 3 可安裝並使用 OpnCV $ pip install numpy # 安裝 python2 的 numpy $ pip3 install numpy # 安裝 python3 的 numpy ### ex4-11 ### # 通過運行以下指令開始修改交換文件配置。 $ sudo nano /etc/dphys-swapfile # 更改 CONF_SWAPSIZE=2048,並存檔。 # 更改 swap 文件配置後,我們需要使用以下指令重新啟動其服務。 $ sudo systemctl restart dphys-swapfile ### ex4-12 ### # 讓我們將所需的兩個 OpenCV 儲存到 Raspberry Pi 中 $ mkdir opencv $ cd opencv $ wget https://github.com/opencv/opencv/archive/master.zip # 下載 opencv $ unzip master.zip && rm master.zip # 解壓縮並刪除檔案 $ wget https://github.com/opencv/opencv_contrib/archive/master.zip # 下載 opencv-contrib $ unzip master.zip && rm master.zip # 解壓縮並刪除檔案 ### ex4-13 ### # 首先,在剛剛解壓縮的檔案,在 opencv-master 資料夾中,創建一個名為 "build" 的目錄,然後將工作目錄更改為該目錄。 $ cd opencv-master $ mkdir build $ cd build # 在 build 中,以 cmake 用來準備 OpenCV,以便在 Pi 上進行編譯,運行以下指令以生成所需的 makefile。 $ cmake -D CMAKE_BUILD_TYPE=RELEASE \ -D CMAKE_INSTALL_PREFIX=/usr/local \ -D OPENCV_EXTRA_MODULES_PATH=../../opencv_contrib-master/modules \ -D ENABLE_NEON=ON \ -D ENABLE_VFPV3=ON \ -D WITH_TBB=ON \ -D WITH_OPENMP=ON \ -D BUILD_TESTS=OFF \ -D OPENCV_ENABLE_NONFREE=ON \ -D INSTALL_PYTHON_EXAMPLES=OFF \ -D BUILD_EXAMPLES=OFF \ -D OPENCV_EXTRA_EXE_LINKER_FLAGS=-latomic \ -D PYTHON3_EXECUTABLE=/usr/bin/python3 \ -D PYTHON_EXECUTABLE=/usr/bin/python \ .. # 所需的編譯文件生成後,繼續編譯 OpenCV。使用參數 -j4 使 Pi 上的每個內核都可以編譯 OpenCV,加快編譯過程。 $ make -j4 # 若編譯結果沒有錯誤發生,就可以安裝了 $ sudo make install # 我們還需要重新設定作業系統。 $ sudo ldconfig # 進入 python_loader $ cd python_loader # 設定 python (python2) 的執行環境 $ sudo python setup.py install # 設定 python3 的執行環境 $ sudo python3 setup.py install ### ex4-14 ### # 啟動 python3 終端: $ python3 # 通過匯入模組,我們可以首先檢查 OpenCV 是否匯入到 Pi 上: >>> import cv2 # 執行後沒有任何反應,代表匯入成功 # 查詢 OpenCV 版本: >>> cv2.__version__ ### ex4-15 ### # ch04 程式碼下載 $ cd ~/Lab $ wget https://max543.com/debugger/class/python02/PiCamera/Lab/code/ch04.zip $ unzip ch04.zip 進入 opencv 的虛擬環境,自行建立資料夾撰寫程式碼:(請確認你有建立 opencv 的虛擬環境) $ workon opencv (opencv) $ mkdir ~/Lab # 建立一個資料夾,存放範例程式 (opencv) $ cd Lab (opencv) $ mkdir ./ch04 # 建立一個資料夾,存放章節程式 (opencv) $ cd ch04 ### ex4-16 (4-1.py) ### import cv2 # 匯入 opencv img = cv2.imread("koala.jpg") # imread() 讀取圖檔。第 1 個參數:檔案路徑 (字串) cv2.imshow("Koala", img) # imshow() 顯示圖片。第 1 個參數:視窗的文字名稱 (字串),第 2 個參數:圖片內容 gray_img = cv2.imread("koala.jpg", cv2.IMREAD_GRAYSCALE) # imread() 讀取圖檔。第 2 個參數:可以指定 3 種的讀取格式 cv2.imshow("Koala:gray", gray_img) cv2.waitKey(0) # waitKey(0) 等待使用者按下任何鍵 cv2.destroyAllWindows() # 最後呼叫 destroyAllWindows() 方法關閉視窗 ### ex4-17 (4-1a.py) ### import cv2 img = cv2.imread("koala.jpg") img2 = cv2.imread("koala.jpg", cv2.IMREAD_GRAYSCALE) print(img.shape) # 使用 shape 屬性取得圖片的尺寸與色彩數,並顯示出來 print(img2.shape) h, w, c = img.shape # 宣告 3 個變數儲存回傳的 shape 屬性 print("圖片高:", h) print("圖片寬:", w) ### ex4-18 (4-1b.py) ### import cv2, imutils # 匯入 imutils 模組,來調整圖片的尺寸 img = cv2.imread("koala.jpg") print(img.shape) resized_img = imutils.resize(img, width = 300) # resize() 調整尺寸。第 1 個參數:圖片內容,第 2 個參數:指定 width 或 height 參數值來調整尺寸 (只需指定其中之一) print(resized_img.shape) cv2.imshow("Koala", img) cv2.imshow("Koala:resized", resized_img) cv2.waitKey(0) cv2.destroyAllWindows() ### ex4-19 (4-1c.py) ### import cv2 img = cv2.imread("koala.jpg") cv2.imshow("Koala", img) print(img.shape) x = 10; y = 10 w = 150; h= 200 crop_img = img[y:y + h, x:x + w] cv2.imshow("crop_Koala", crop_img) print(crop_img.shape) cv2.waitKey(0) cv2.destroyAllWindows() ### ex4-20 (4-1d.py) ### import cv2, imutils img = cv2.imread("koala.jpg") rotated_img = imutils.rotate(img, angle = 90) # rotate() 旋轉圖片。第 1 個參數:圖片內容,第 2 個參數:angle 參數是旋轉角度 fliped_img = cv2.flip(img, -1) # 使用 cv2.flip() 也可旋轉圖片。第 1 個參數:圖片內容,第 2 個參數:0 是沿 x 軸垂直翻轉;1 是沿 y 軸水平翻轉 (鏡射);-1 是沿水平和垂直都翻轉 translated_img = imutils.translate(img, 25, -75) # translate() 位移圖片。第 1 個參數:圖片內容,第 2 個參數:若是正值向右位移;負值向左位移,第 3 個參數:若是正值向下位移;負值向上位移 cv2.imshow("Koala:rotated", rotated_img) cv2.imshow("Koala:fliped", fliped_img) cv2.imshow("Koala:translated", translated_img) cv2.waitKey(0) cv2.destroyAllWindows() ### ex4-21 (4-1e.py) ### import cv2 img = cv2.imread("koala.jpg") gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # cvtColor() 轉換彩色圖片成為灰階圖片。第 1 個參數:圖片內容,第 2 個參數:cv2.COLOR_BGR2GRAY 將 BGR 格式轉成灰階 bgr_img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR) # cv2.COLOR_RGB2BGR 將 RGB 格式轉成 BGR cv2.imshow("Koala:gray", gray_img) cv2.imshow("Koala:bgr", bgr_img) cv2.waitKey(0) cv2.destroyAllWindows() ### ex4-22 (4-1f.py) ### import cv2, imutils url = "https://fchart.github.io/img/koala.png" # 宣告變數 url 儲存圖片的 URL 網址 img = imutils.url_to_image(url) # imutils.url_to_image() 讀取此網址的圖片 cv2.imshow("Koala", img) cv2.waitKey(0) cv2.destroyAllWindows() ### ex4-23 (4-1g.py) ### import cv2 img = cv2.imread("koala.jpg") cv2.line(img, (0,0), (200,200), (0,0,255), 5) # cv2.line(影像, 開始座標, 結束座標, 顏色, 線寬) cv2.rectangle(img, (20,70), (120,160), (0,255,0), 2) # cv2.rectangle(影像, 開始座標, 結束座標, 顏色, 線寬) cv2.rectangle(img, (40,80), (100,140), (255,0,0), -1) cv2.circle(img,(90,210), 30, (0,255,255), 3) # cv2.circle(影像, 圓心座標, 半徑, 顏色, 線寬) cv2.circle(img,(140,170), 15, (255,0,0), -1) cv2.putText(img, 'OpenCV', (10, 40), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,255,255), 5, cv2.LINE_AA) # cv2.putText(影像, 文字, 座標, 字型, 大小, 顏色, 線寬, 線條種類) cv2.imshow("Koala", img) cv2.waitKey(0) cv2.destroyAllWindows() ### ex4-24 (4-1h.py) ### import cv2 img = cv2.imread("koala.jpg") gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) cv2.imwrite("result_gray.jpg", gray_img) # imwrite() 將圖片內容寫入圖檔。第 1 個參數:欲儲存的圖檔名稱,第 2 個參數:圖片內容 cv2.imwrite("result.png", img) ### ex4-25 (4-2.py) ### import cv2 cap = cv2.VideoCapture("YouTube.mp4") # 第 1 個參數:影片檔路徑 while cap.isOpened(): # isOpened() 檢查影片是否開啟 ret, frame = cap.read() # read() 讀取每一個影格 (幀)。變數 ret:讀取成功 (1);讀取失敗 (0),frame:影格內容 if ret: # 如果 ret == True (1),則顯示影格 cv2.imshow("frame",frame) if cv2.waitKey(1) & 0xFF == ord('q'): # 如果顯示一幀,持續至少 1 ms,且使用者按下 q 鍵,則跳離迴圈 (ord()可以將字符轉化為對應的整數 ASCII碼) break cap.release() # 釋放 VideoCapture 物件 cv2.destroyAllWindows() # 關閉視窗 ### ex4-26 (4-2a.py) ### import cv2 cap = cv2.VideoCapture("YouTube.mp4") def decode_fourcc(v): # decode_fourcc() 將編碼轉成可閱讀的編碼名稱 v = int(v) return "".join([chr((v >> 8 * i) & 0xFF) for i in range(4)]) width = cap.get(cv2.CAP_PROP_FRAME_WIDTH) height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT) print("圖片尺寸:", width, 'x', height) fourcc = cap.get(cv2.CAP_PROP_FOURCC) # 取得影片編碼。參數用法:https://docs.opencv.org/4.5.3/d4/d15/group__videoio__flags__base.html#baeb8dd9c89c10a5c63c139bf7c4f5704d codec = decode_fourcc(fourcc) # 呼叫 decode_fourcc(),轉換可閱讀的編碼字串 print("Codec編碼:", codec) ### ex4-27 (4-2b.py) ### import cv2 cap = cv2.VideoCapture("YouTube.mp4") while cap.isOpened(): ret, frame = cap.read() if ret: gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # 圖片處理的 cv2.COLOR_BGR2GRAY,同樣適用於影片 cv2.imshow("frame", gray_frame) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows() ### ex4-28 (4-3.py) ### import cv2 cap = cv2.VideoCapture(0) # 代表第一支相機 while cap.isOpened(): ret, frame = cap.read() frame = cv2.rotate(frame, rotateCode = 1) # 垂直旋轉相機 180 度 (因為我們的相機安裝是反的) cv2.imshow("frame", frame) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows() ### ex4-29 (4-3a.py) ### import cv2 cap = cv2.VideoCapture(0) cap.set(cv2.CAP_PROP_FRAME_WIDTH, 320) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 180) cap.set(cv2.CAP_PROP_FPS, 25) while cap.isOpened(): ret, frame = cap.read() cv2.imshow("frame",frame) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows() ### ex4-30 (4-3b.py) ### import cv2 cap = cv2.VideoCapture(0) fourcc = cv2.VideoWriter_fourcc(*'XVID') # 首先建立影片編碼 fourcc,指定為 .avi 格式 out = cv2.VideoWriter('output.avi', fourcc, 20, (640, 480)) # 建立 VideoWriter 物件來寫入影片檔。第 1 個參數:欲儲存的影片檔案名稱,第 2 個參數:編碼,第 3 個參數:FPS,第 4 個參數:影格尺寸 while cap.isOpened(): ret, frame = cap.read() if ret == True: out.write(frame) # 呼叫 write() 將影格一一寫入影片檔 cv2.imshow('frame', frame) if cv2.waitKey(1) & 0xFF == ord('q'): break else: break cap.release() out.release() cv2.destroyAllWindows() ### ex4-31 (4-4.py) ### import cv2 face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_alt2.xml') # 載入正面較精準的 alt2 image = cv2.imread('demo.jpeg') # 載入圖檔 gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 轉成灰階 (影片辨識採灰階) faces = face_cascade.detectMultiScale(gray, 1.1, 3) # 利用 detectMultiScale(image, scaleFactor = 1.1, minNeighbors = 3) 尋找圖片中的人臉 # faces = face_cascade.detectMultiScale(gray, 1.05, 4) # scaleFactor 代表每次檢測窗口的放大級距,最小值為 1,minNeighbors 代表需通過幾次才算是人臉 # 找到人臉後,傳回左上角座標 (x, y),及長寬範圍,畫出一個矩形 for (x, y, w, h) in faces: frame = cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 3) cv2.namedWindow('frame', cv2.WINDOW_NORMAL) # 當圖片太大,使用 namedWindow() 得到的視窗就可以自行调整大小。WINDOW_NORMAL:視窗大小可改變 cv2.imshow('frame', frame) cv2.waitKey(0) # 按任何鍵結束程式 cv2.destroyAllWindows() ### ex4-32 (4-5.py) ### import cv2 face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_alt2.xml') eye_cascade = cv2.CascadeClassifier('haarcascade_eye.xml') # 載入眼睛分類器 frame = cv2.imread('demo.jpeg') gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # faces = face_cascade.detectMultiScale(gray, 1.1, 3) faces = face_cascade.detectMultiScale(gray, 1.05, 4) # 畫出辨識的人臉 for (x, y, w, h) in faces: frame = cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 3) face_rect = gray[y:y + h, x:x + w] eyes = eye_cascade.detectMultiScale(face_rect, 1.3, 8) # 辨識出人臉後,再辨識眼睛 # 畫出辨識的眼睛 for (ex, ey, ew, eh) in eyes: frame = cv2.rectangle(frame, (x + ex, y + ey), (x + ex + ew, y + ey + eh), (0, 255, 0), 2) cv2.namedWindow('frame', cv2.WINDOW_NORMAL) cv2.imshow('frame', frame) cv2.waitKey(0) cv2.destroyAllWindows() ### ex4-33 (4-6.py) #### import cv2 faceCascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml") # 載入全角度較精準的預設人臉分類器 cap = cv2.VideoCapture(0) cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480) while True: ret, frame = cap.read() frame = cv2.rotate(frame, rotateCode = 1) gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) faces = faceCascade.detectMultiScale(gray, scaleFactor = 1.1, minNeighbors = 5, minSize = (30, 30)) # minSize:低於 minSize 的話,不會被檢測出來 print("人臉數:", len(faces)) # 計算出現的人臉數 for (x, y, w, h) in faces: cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2) cv2.imshow("preview", frame) if cv2.waitKey(1) & 0xFF == ord("q"): break cap.release() cv2.destroyAllWindows() ### ex4-34 (4-7.py) #### import cv2 faceCascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml") eye_cascade = cv2.CascadeClassifier("haarcascade_eye.xml") cap = cv2.VideoCapture(0) cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480) while True: ret, frame = cap.read() frame = cv2.rotate(frame, rotateCode = 1) gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) faces = faceCascade.detectMultiScale(gray, scaleFactor = 1.1, minNeighbors = 5, minSize = (30, 30)) print("人臉數:", len(faces)) for (x, y, w, h) in faces: frame = cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 3) face_rect = gray[y:y + h, x:x + w] eyes = eye_cascade.detectMultiScale(face_rect, 1.3, 8) for (ex, ey, ew, eh) in eyes: cv2.rectangle(frame, (x + ex, y + ey), (x + ex + ew, y + ey + eh), (0, 255, 0), 2) cv2.imshow("preview", frame) if cv2.waitKey(1) & 0xFF == ord("q"): break cap.release() cv2.destroyAllWindows() ### ex4-35 #### # 字串容器 >>> string = "52python" # 字串容器:由字元組成 >>> string[0] # 字串以索引取值 # tuple 容器 >>> tuple = (1, '2', 3) # tuple 容器:由資料物件組成 >>> tuple[0] # tuple 以索引取值 # 串列容器 (list) >>> list = [1, '2', 3] # 串列容器:由資料物件組成 >>> list[2] # 串列以索引取值 # 集合容器 (set) >>> set = {1, '2', 3} # 集合容器:由資料物件組成,無序所以沒有索引取值 # 字典容器 (directory) >>> dick = {'A':1, 'B':'2', 'C':3} # 字典容器:由資料物件組成,以鍵:值表示 >>> dick['B'] # 字典以鍵取值 ### ex4-36 ### >>> import numpy as np # 匯入 numpy >>> a = np.array([10, 2, 45, 32, 24]) # 建立五個元素 >>> len(a) # 計算元素個數 >>> a[2:4] # 取出第 2、3 個元素 >>> a[:4] # 取出第 1 ~ 3 個元素 ### ex4-37 (4-8-1-capture.py) ### import cv2 ESC = 27 # 設定將以 ESC 鍵作為離開程式 n = 1 # 畫面數量計數 index = 0 # 存檔檔名用 total = 100 # 人臉取樣總數 # 自訂函數,images 與 h0 要自己先建立。若有第二個人就建立 h1 def saveImage(face_image, index): filename = 'images/h0/{:03d}.pgm'.format(index) cv2.imwrite(filename, face_image) print(filename) # 載入聯集分類器與開啟攝影機 face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml') cap = cv2.VideoCapture(0) ratio = cap.get(cv2.CAP_PROP_FRAME_WIDTH) / cap.get(cv2.CAP_PROP_FRAME_HEIGHT) WIDTH = 400 HEIGHT = int(WIDTH / ratio) cv2.namedWindow('video', cv2.WINDOW_NORMAL) # 讀取影像並轉成灰階 while n > 0: ret, frame = cap.read() frame = cv2.resize(frame, (WIDTH, HEIGHT)) frame = cv2.rotate(frame, rotateCode = 1) # 垂直旋轉相機 180 度 (因為我們的相機安裝是反的) frame = cv2.flip(frame, 1) # 水平翻轉 180 度 (鏡像) gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # 轉成灰階 # 偵測人臉,並且每 5 張人臉存檔一次 faces = face_cascade.detectMultiScale(gray, 1.1, 3) # 辨識人臉 for (x, y, w, h) in faces: frame = cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 3) if n % 5 == 0: # 每 5 張存檔一次,目的是要讓使用者變換姿勢 face_img = gray[y: y + h, x: x + w] face_img = cv2.resize(face_img, (400, 400)) # 訓練用圖片解析度為 400x400,最小為 50x50 saveImage(face_img, index) # 儲存訓練圖片 index += 1 if index >= total: # 若拍照滿 100 張,則跳離 for 迴圈 print('get training data done') n = -1 break n += 1 # 將攝影機拍到的影像顯示出來 cv2.imshow('video', frame) if cv2.waitKey(1) == ESC: cv2.destroyAllWindows() break ### ex4-38 (4-8-2-train.py) ### import cv2 import numpy as np images = [] # 空串列,儲存照片 labels = [] # 空串列,儲存人臉的標籤序號 for index in range(100): filename = 'images/h0/{:03d}.pgm'.format(index) print('read ' + filename) img = cv2.imread(filename, cv2.COLOR_BGR2GRAY) images.append(img) labels.append(0) # 第一張人臉的標籤為 0 print('training...') model = cv2.face.LBPHFaceRecognizer_create() # 建立模型,使用 LBPH 演算法 model.train(np.asarray(images), np.asarray(labels)) # train() 只能接收 numpy 格式的陣列,asarry() 方法將輸入的物件轉成陣列 model.save('faces.data') # 儲存訓練好的辨識檔 print('training done') ### ex4-39 (4-8-3-recognition.py) ### import cv2 model = cv2.face.LBPHFaceRecognizer_create() # 建立模型,使用 LBPH 演算法 model.read('faces.data') # 載入訓練好的辨識檔 print('load training data done') face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml') # 載入聯集分類器 (需與取樣時的分類器一致),並開啟攝影機 cap = cv2.VideoCapture(0) cv2.namedWindow('video', cv2.WINDOW_NORMAL) # 可識別化名稱,請自行更改 names = ['pllai'] # 讀取攝影機資料,並轉換成灰階影像 while True: ret, frame = cap.read() frame = cv2.resize(frame, (600, 336)) frame = cv2.flip(frame, 1) gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) faces = face_cascade.detectMultiScale(gray, 1.1, 3) # 偵測人臉,並與訓練資料比對 for (x, y, w, h) in faces: frame = cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 3) face_img = gray[y: y + h, x: x + w] face_img = cv2.resize(face_img, (400, 400)) val = model.predict(face_img) # predict() 會傳回標籤編號與信心值 print('label:{}, conf:{:.1f}'.format(val[0], val[1])) if val[1] < 50: # 若是 LBPH 演算法 < 50 是可接受的,信心值越低越好 cv2.putText(frame, names[val[0]], (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 1, (255,255,0), 3) cv2.imshow('video', frame) if cv2.waitKey(1) == 27: cv2.destroyAllWindows() break