[ OpenCV ] 利用 OpenCV抓取影片中的臉部數據
除了網路爬蟲,也可以透過影片搜集數據。但由於畫面太連續,數據差異太小,訓練 ML或 DL可能會有 overfitting的問題,有必要對擷取的畫面進行一些篩選。
篩選的方法可以使用 Hamming distance或是 SSIM,可以參考 "利用 PhotoHash篩選相似度過高的圖像" 或 "利用 SSIM篩選相似度過高的圖像"。
之前不知道手殘打錯了什麼,讓我誤以為 MacOS的 cv2.VideoCapture不能使用,所以找了 scikit-video作為替代的方案,用法也很簡單,歡迎參考 scikit-video官網。
先使用以下由 JYP官方提供的子瑜女神特寫影片吧。
可以利用 OnlineVideoConverter這個網站下載 YouTube的影片,頁面上可以透過 "more setting"選擇下載的格式和畫質。
這次實作使用的是 1080p的 mp4檔。
可以利用 matplotlib.pyplot來觀察捕捉的情況,但會消耗較多的資源。不懂這裡怎麼回事的可以參考上一篇。
大部分都與 "利用 OpenCV抓取相片中的臉部數據" 這篇差不多。
稍微需要注意的是 scikit-video所讀取的圖片格式是 RGB,所以在第 10行灰化時,是使用 RGB2GRAY。
雖然有時候會把眼睛誤認為嘴巴,但看起來沒有太多問題,先用這樣的參數來儲存臉部數據吧。
執行 matplotlib.pyplot其實會花費滿多計算資源,可以註解掉 matplotlib.pyplot的部分,速度會快上許多。
短短 59秒的影片,在這樣的條件下儲存了 475張圖像。先來看看幾張。
除了一些捕捉到不好的圖像外,該影片在剪接的過程中使用了一些淡化轉場的效果,所以會有一些畫面有重疊的圖像。
以下是一些本人覺得應該要刪除的圖像。
由於從影片中可以捕捉到非常大量的數據,但進行篩選後應該還是有一定的量。
另外捕捉錯誤的圖像除了手動刪除外,也可以有技巧地使用 Hamming distance或 SSIM進行篩選,整理起來應該會輕鬆許多。
篩選的方法可以使用 Hamming distance或是 SSIM,可以參考 "利用 PhotoHash篩選相似度過高的圖像" 或 "利用 SSIM篩選相似度過高的圖像"。
之前不知道手殘打錯了什麼,讓我誤以為 MacOS的 cv2.VideoCapture不能使用,所以找了 scikit-video作為替代的方案,用法也很簡單,歡迎參考 scikit-video官網。
先使用以下由 JYP官方提供的子瑜女神特寫影片吧。
可以利用 OnlineVideoConverter這個網站下載 YouTube的影片,頁面上可以透過 "more setting"選擇下載的格式和畫質。
這次實作使用的是 1080p的 mp4檔。
import cv2 import numpy as np import matplotlib.pyplot as plt import skvideo.io face_cascade = cv2.CascadeClassifier('./cascades/haarcascade_frontalface_default.xml') eye_cascade = cv2.CascadeClassifier('./cascades/haarcascade_eye.xml') def detect(img, idx): gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY) faces = face_cascade.detectMultiScale(gray, scaleFactor=1.3, minNeighbors=5, minSize=(220,220),) for (x,y,w,h) in faces: roi_gray = gray[y:y+h, x:x+w] eyes = eye_cascade.detectMultiScale(roi_gray, scaleFactor=1.05, minNeighbors=5, minSize=(50,50),) img = cv2.rectangle(img,(x,y),(x+w,y+h),(0,0,255),5) for (ex,ey,ew,eh) in eyes: img = cv2.rectangle(img,(x+ex,y+ey),(x+ex+ew,y+ey+eh),(0,255,0),5) print('Working with %s frame' % idx) return img videogen = skvideo.io.vreader('tzuyu.mp4') plt.ion() for idx,frame in enumerate(videogen): frame = detect(frame, idx) plt.imshow(frame) plt.pause(.01) plt.cla() # Clear axis plt.clf() # Clear figure plt.ioff()先利用 scikit-video讀取影片,在建立一個 for迴圈處理每個幀。
可以利用 matplotlib.pyplot來觀察捕捉的情況,但會消耗較多的資源。不懂這裡怎麼回事的可以參考上一篇。
大部分都與 "利用 OpenCV抓取相片中的臉部數據" 這篇差不多。
稍微需要注意的是 scikit-video所讀取的圖片格式是 RGB,所以在第 10行灰化時,是使用 RGB2GRAY。
import cv2 import numpy as np import matplotlib.pyplot as plt import skvideo.io face_cascade = cv2.CascadeClassifier('./cascades/haarcascade_frontalface_default.xml') eye_cascade = cv2.CascadeClassifier('./cascades/haarcascade_eye.xml') face_filename = 1 def detect(img, idx): gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY) faces = face_cascade.detectMultiScale(gray, scaleFactor=1.3, minNeighbors=5, minSize=(220,220),) for (x,y,w,h) in faces: roi_gray = gray[y:y+h, x:x+w] eyes = eye_cascade.detectMultiScale(roi_gray, scaleFactor=1.05, minNeighbors=5, minSize=(50,50),) img = cv2.rectangle(img,(x,y),(x+w,y+h),(0,0,255),5) for (ex,ey,ew,eh) in eyes: img = cv2.rectangle(img,(x+ex,y+ey),(x+ex+ew,y+ey+eh),(0,255,0),5) if len(eyes)>=2: f = cv2.resize(gray[y:y+h, x:x+w], (200, 200)) global face_filename name = './face/%d.png' % face_filename cv2.imwrite(name, f) face_filename += 1 else: pass print('Working with %s frame' % idx) return img videogen = skvideo.io.vreader('tzuyu.mp4') plt.ion() for idx,frame in enumerate(videogen): frame = detect(frame, idx) plt.imshow(frame) plt.pause(.01) plt.cla() # Clear axis plt.clf() # Clear figure plt.ioff()在第 27行開始加入了儲存的條件等。
執行 matplotlib.pyplot其實會花費滿多計算資源,可以註解掉 matplotlib.pyplot的部分,速度會快上許多。
短短 59秒的影片,在這樣的條件下儲存了 475張圖像。先來看看幾張。
以下是一些本人覺得應該要刪除的圖像。
由於從影片中可以捕捉到非常大量的數據,但進行篩選後應該還是有一定的量。
另外捕捉錯誤的圖像除了手動刪除外,也可以有技巧地使用 Hamming distance或 SSIM進行篩選,整理起來應該會輕鬆許多。
留言
張貼留言