### ex1-1:Anaconda 下載 ### https://www.anaconda.com/products/individual # 若安裝好的 Spyder 掛了,可先複製一個先使用 (在 Windows 開始選單中選擇 Anaconda Prompt,並輸入以下常用的指令) >>> conda create -n spyder-cf -c conda-forge spyder >>> conda activate spyder-cf # 手機當電腦鏡頭的步驟 https://bit.ly/3yEVgF9 ### ex1-2:用 conda 建立及管理 Python 虛擬環境 ### # Step 1:安裝及更新 conda >>> python –V # 檢查目前 Python 版本 >>> pip list # 檢查目前 Python 環境安裝了那些 Package >>> conda –V # 檢查目前 conda 版本 >>> conda list # 檢查目前 conda 環境安裝了那些 Package >>> conda update conda # 若想要進行更新,可以輸入下列命令 (更新必須以系統管理員執行 Anaconda Prompt) # Step 2:建立虛擬環境 >>> conda env list # 看目前系統已經安裝幾個虛擬環境 >>> conda create --name myenv python=3.9 # 若要建立一個叫做 myenv 的虛擬環境,並且指定最新的 Python 的版本 >>> conda create --name myenv_27 python=2.7 # 若要建立一個叫做 myenv_27 的虛擬環境,並且指定 Python 2.7 的版本 >>> conda env list # 再次檢查目前虛擬環境 # Step 3:啟動虛擬環境 >>> activate myenv_27 # 啟動一個新的虛擬環境 (myenv_27) >>> conda list # 檢查目前此虛擬環境中的 Conda 安裝了那些東西 (myenv_27) >>> pip list # 檢查目前虛擬環境的 Python 環境,安裝了那些 Package (myenv_27) >>> conda install numpy # 要在此虛擬環境下安裝所需套件,例如:numpy # Step 4:離開虛擬環境 (myenv_27) >>> deactivate # 關閉目前的虛擬環境 # Step 5:刪除虛擬環境的 Package 或虛擬環境本身 (myenv_27) >>> conda remove --name myenv_27 numpy # 要刪除虛擬環境中某個 Package。(例如:虛擬環境 myenv_27 中的 numpy) (myenv_27) >>> deactivate # 關閉目前的虛擬環境 >>> conda env remove --name myenv_27 # 要刪除整個虛擬環境 (不能刪除當前的虛擬環境,必須先關閉目前的虛擬環境) # Step 6:複製虛擬環境 >>> conda create -n myenv_new --clone myenv # 複製虛擬環境 myenv,新的虛擬環境為 myenv_new # Step 7:為虛擬環境安裝 Anaconda >>> conda create --name myenv_39 python=3.9 & activate myenv_39 # 建一個 Python 3.9 的虛擬環境 myenv_39,並且切換至 myenv_39 (myenv_39) >>> conda install anaconda # 安裝 Anaconda ### ex1-3 ### # 以 Python 3.9 為例 >>> conda create -n opencvenv --clone myenv_39 # 複製一個 OpenCV 專用的 Python 3.9 虛擬環境 >>> activate opencvenv # 載入虛擬環境 opencvenv # Step 1:安裝 OpenCV 的相關支援模組 (opencvenv) >>> pip install numpy # 陣列容器,用於影像數值計算 (opencvenv) >>> pip install matplotlib # 畫圖用 (opencvenv) >>> pip install imutils # 常用的圖片處理模組 # Step 2:安裝 OpenCV (opencvenv) >>> pip install opencv-python # OpenCV 模組 (opencvenv) >>> pip install opencv-contrib-python # OpenCV 擴充模組 (opencvenv) >>> pip list # 輸入指令來檢視虛擬環境安裝的套件清單 # Step 3:檢查 OpenCV 是否成功安裝,通過匯入模組,我們可以首先檢查 OpenCV 是否匯入 (opencvenv) >>> import cv2 # 匯入 OpenCV,執行後沒有任何反應,代表匯入成功 (opencvenv) >>> cv2.__version__ # 查詢 OpenCV 版本 ### ex1-4 (1-1.py) ### import cv2 # 匯入 opencv img = cv2.imread('images/koala.jpg') # imread() 讀取圖檔。第 1 個參數:檔案路徑 (字串) cv2.imshow('Koala', img) # imshow() 顯示圖片。第 1 個參數:視窗的文字名稱 (字串),第 2 個參數:圖片內容 gray_img = cv2.imread('images/koala.jpg', cv2.IMREAD_GRAYSCALE) # imread() 讀取圖檔。第 2 個參數:可以指定 3 種的讀取格式 cv2.imshow('Koala:gray', gray_img) cv2.waitKey(0) # waitKey(0) 等待使用者按下任何鍵 cv2.destroyAllWindows() # 最後呼叫 destroyAllWindows() 方法關閉視窗 ### ex1-5 (1-1a.py) ### import cv2 img = cv2.imread('images/koala.jpg') img2 = cv2.imread('images/koala.jpg', cv2.IMREAD_GRAYSCALE) print(img.shape) # 使用 shape 屬性取得圖片的尺寸與色彩數,並顯示出來 print(img2.shape) h, w, c = img.shape # 宣告 3 個變數儲存回傳的 shape 屬性 print('圖片高: ', h) print('圖片寬: ', w) ### ex1-6 (1-1b.py) ### import cv2, imutils # 匯入 imutils 模組,來調整圖片的尺寸 img = cv2.imread('images/koala.jpg') print(img.shape) resized_img = imutils.resize(img, width = 300) # imutils.resize() 調整尺寸。第 1 個參數:圖片內容,第 2 個參數:指定 width 或 height 參數值來調整尺寸 (只需指定其中之一) print(resized_img.shape) cv2.imshow('Koala', img) cv2.imshow('Koala:resized', resized_img) cv2.waitKey(0) cv2.destroyAllWindows() ### ex1-7 #### # 字串容器 >>> myWord = '52python' # 字串容器:由字元組成 >>> myWord[0] # 字串以索引取值,結果為:'5' # tuple 容器 >>> myTuple = (1, '2', 3) # tuple 容器:由資料物件組成 >>> myTuple[0] # tuple 以索引取值,結果為:1 # 串列容器 (list) >>> myList = [1, '2', 3] # 串列容器:由資料物件組成 >>> myList[2] # 串列以索引取值,結果為:'2' # 集合容器 (set) >>> mySet = {1, '2', 3} # 集合容器:由資料物件組成,無序所以沒有索引取值 # 字典容器 (directory) >>> myDick = {'A':1, 'B':'2', 'C':3} # 字典容器:由資料物件組成,以鍵:值表示 >>> myDick['B'] # 字典以鍵取值,結果為:'2' ### ex1-8 ### import numpy as np # 匯入 numpy 模組,並使用 np 簡寫代表 a = np.array([10, 2, 45, 32, 24]) # 建立五個元素的 1-D 陣列 >>> len(a) # 計算元素個數 >>> a[2:4] # 取出第 3 (a[2])、4 (a[3]) 的元素 (口訣:有頭無尾) >>> a[:4] # 取出第 1 (a[0]) ~ 3 (a[2]) 的元素 ### ex1-9 ### import numpy as np A = np.array([[1, 4, 2], [3, 2, 0]]) # 建立兩個元素 2-D 矩陣 B = A[1:, 1:3] # 2-D array 切片,第一個索引以列切片,第二個索引以行為切片 ### ex1-10 (1-1c.py) ### import cv2 img = cv2.imread('images/koala.jpg') print(img.shape) x = 10; y = 10 # 設定切片頂點 (x, y) w = 150; h= 200 # 設定切片的寬 (w) 與高 (h) crop_img = img[y:y + h, x:x + w] # 2-D array 切片,第一個索引以列切片,第二個索引以行為切片 cv2.imshow('Koala', img) cv2.imshow('corp_Koala', crop_img) print(crop_img.shape) cv2.waitKey(0) cv2.destroyAllWindows() ### ex1-11 (1-1d.py) ### import cv2, imutils img = cv2.imread('images/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', img) cv2.imshow('Koala:rotated', rotated_img) cv2.imshow('Koala:fliped', fliped_img) cv2.imshow('Koala:translated', translated_img) cv2.waitKey(0) cv2.destroyAllWindows() ### ex1-12 (1-1e.py) ### import cv2 img = cv2.imread('images/koala.jpg') gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # cvtColor() 轉換彩色圖片成為灰階圖片。第 1 個參數:圖片內容,第 2 個參數:cv2.COLOR_BGR2GRAY 將 BGR 格式轉成灰階 rgb_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # cv2.COLOR_RGB2BGR 將 RGB 格式轉成 BGR bgr_img = cv2.cvtColor(rgb_img, cv2.COLOR_RGB2BGR) cv2.imshow('Koala:original', img) cv2.imshow('Koala:gray', gray_img) cv2.imshow('Koala:rgb', rgb_img) cv2.imshow('Koala:bgr', bgr_img) cv2.waitKey(0) cv2.destroyAllWindows() ### ex1-13 (1-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() ### ex1-14 (1-1g.py) ### import cv2 img = cv2.imread('images/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() ### ex1-15 (1-1h.py) ### import cv2 img = cv2.imread('images/koala.jpg') gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) cv2.imwrite('images/result_gray.jpg', gray_img) # imwrite() 將圖片內容寫入圖檔。第 1 個參數:欲儲存的圖檔名稱,第 2 個參數:圖片內容 cv2.imwrite('images/result.png', img) ### ex1-16 (1-2.py) ### import cv2 cap = cv2.VideoCapture('images/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) == 27: # 如果顯示一幀,持續至少 1 ms,且使用者按下 ESC 鍵,則跳離迴圈 break cap.release() # 釋放 VideoCapture 物件 cv2.destroyAllWindows() # 關閉視窗 ### ex1-17 (1-2a.py) ### import cv2 cap = cv2.VideoCapture('images/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) == 27: break cap.release() cv2.destroyAllWindows() ### ex1-18 (1-3.py) ### import cv2 cap = cv2.VideoCapture(0) # 代表第一支相機 while cap.isOpened(): ret, frame = cap.read() cv2.imshow('frame', frame) if cv2.waitKey(1) == 27: break cap.release() cv2.destroyAllWindows() ### ex1-19 (1-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) == 27: break cap.release() cv2.destroyAllWindows() ### ex1-20 (1-3b.py) ### import cv2 cap = cv2.VideoCapture(0) fourcc = cv2.VideoWriter_fourcc(*'XVID') # 首先建立影片編碼 fourcc,指定為 .avi 格式 out = cv2.VideoWriter('images/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) == 27: break else: break cap.release() out.release() cv2.destroyAllWindows() ### ex1-21 (1-4.py) ### import cv2 face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_alt2.xml') # 載入正面較精準的 alt2 image = cv2.imread('images/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('preview', cv2.WINDOW_NORMAL) # 當圖片太大,使用 namedWindow() 得到的視窗就可以自行调整大小。WINDOW_NORMAL:視窗大小可改變 cv2.imshow('preview', frame) cv2.waitKey(0) # 按任何鍵結束程式 cv2.destroyAllWindows() ### ex1-21 (1-5.py) ### import cv2 face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_alt2.xml') eye_cascade = cv2.CascadeClassifier('haarcascade_eye.xml') # 載入眼睛分類器 frame = cv2.imread('images/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('preview', cv2.WINDOW_NORMAL) cv2.imshow('preview', frame) cv2.waitKey(0) cv2.destroyAllWindows() ### ex1-22 (1-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() 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) == 27: break cap.release() cv2.destroyAllWindows() ### ex1-23 (1-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() 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) == 27: break cap.release() cv2.destroyAllWindows() ### ex1-24 (1-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)) 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: cap.release() cv2.destroyAllWindows() break cap.release() cv2.destroyAllWindows() ### ex1-25 (1-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') ### ex1-26 (1-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 = ['第一位的名字'] # 讀取攝影機資料,並轉換成灰階影像 while True: ret, frame = cap.read() frame = cv2.resize(frame, (600, 400)) 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: cap.release() cv2.destroyAllWindows() break