[ 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檔。
先利用 scikit-video讀取影片,在建立一個 for迴圈處理每個幀。
- 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()
可以利用 matplotlib.pyplot來觀察捕捉的情況,但會消耗較多的資源。不懂這裡怎麼回事的可以參考上一篇。
大部分都與 "利用 OpenCV抓取相片中的臉部數據" 這篇差不多。
稍微需要注意的是 scikit-video所讀取的圖片格式是 RGB,所以在第 10行灰化時,是使用 RGB2GRAY。
在第 27行開始加入了儲存的條件等。
- 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()
執行 matplotlib.pyplot其實會花費滿多計算資源,可以註解掉 matplotlib.pyplot的部分,速度會快上許多。
短短 59秒的影片,在這樣的條件下儲存了 475張圖像。先來看看幾張。



以下是一些本人覺得應該要刪除的圖像。



由於從影片中可以捕捉到非常大量的數據,但進行篩選後應該還是有一定的量。
另外捕捉錯誤的圖像除了手動刪除外,也可以有技巧地使用 Hamming distance或 SSIM進行篩選,整理起來應該會輕鬆許多。
留言
張貼留言