發表文章

目前顯示的是 7月, 2017的文章

[ PhotoHash ] 利用 PhotoHash篩選相似度過高的圖像

圖片
子瑜在這部影片中,前 14秒幾乎沒有任何的動作。 若用 " 利用 Dlib進行臉部捕捉 " 該文中提供的程式碼,這 14秒的影片大約會擷取300多張的圖像。 用這筆數據訓練後,可能會導致權重失衡。 為了避免權重失衡影響辨識結果,有必要對圖像進行一些篩選。 用爬蟲爬取圖片的時候也容易爬到不同出處但卻是同一張照片,這麼做也很方便呦。 Hamming distance可以作為數據差異度的基準,詳細可以到 維基百科 了解一下。 對於圖像差異度的比較,Python也有一套 Library叫 PhotoHash 可以幫忙比較圖像的差異。 先計算整張圖像的平均 Hash值後,再計算 Hamming distance。 import os import glob import photohash def filter(member): img_list = glob.glob('./{0}/*.png'.format(member)) # def order_by_num(num): # return int(num.split('/')[-1].split('.')[0]) # img_list.sort(key=order_by_num) img_list.sort(key=lambda num: int(num.split('/')[-1].split('.')[0])) for img in img_list: hash_one_path = img hash_one = photohash.average_hash(hash_one_path) if 'hash_two' in locals(): distance = photohash.hash_distance(hash_one, hash_two) if distance <= 2: if not os.path.isdir("./{0}/similar".format

[ Dlib ] 利用 Dlib進行臉部捕捉

圖片
為了更高品質的臉部數據,特別研究了一下 Face Alignment,相較 Haar等方式,似乎 Dlib更能有效地捕捉臉部,再利用 Face Alignment能有效地將捕捉的臉部校正,以取得更高的數據品質。 Dlib安裝稍微有點複雜,可以參考由 Adrian Rosebrock寫的 " How to install dlib "。 from imutils import face_utils import numpy as np import imutils import dlib import cv2 face_cascade = cv2.CascadeClassifier('./cascades/haarcascade_frontalface_default.xml') def detect_haar(filename): img = cv2.imread(filename) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=3,) for (x,y,w,h) in faces: img = cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),3) cv2.imwrite('./haar.png', img) detector = dlib.get_frontal_face_detector() predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat") def detect_face_landmarks(filename): img = cv2.imread(filename) gray = cv2.cvtColor(img,

[ MoviePy ] 利用MoviePy將影片加入音訊

圖片
由於 OpenCV是視覺處理的 Library,很自然它並沒有處理音訊的部分,所以生成出來的影片是沒有聲音的。 雖然拿 Twice的影片當作 OpenCV練習的素材滿有趣的,但看著沒有音樂的 MV也挺枯燥的。 因此特地找了 MoviePy 這個 Library。 MoviePy是用於視頻編輯的 Library,可用於基本操作(如剪切、連接、標題插入),視頻合成(非線性編輯),視頻處理或創建高級效果。它可以讀取和寫入最常見的視頻格式,也包含 GIF。 接著就把 Opencv輸出,但沒有音頻的影片加入音樂吧。 from moviepy.editor import VideoFileClip clip1 = VideoFileClip("twice_jelly_jelly.mp4") audioclip1 = clip1.audio clip2 = VideoFileClip("face_twice_jelly_jelly.avi") new_video = clip2.set_audio(audioclip1) # audioclip1.write_audiofile("twice_jelly_jelly.mp3") # 如果想要輸出 mp3 new_video.write_videofile("face_twice_jelly_jelly_audio.mp4") 再來介紹一個比較有趣的,網路上常會有人製作 GIF動畫貼在各大論壇。 MoviePy同樣也能輕鬆地製作這些 GIF動畫。 import moviepy.editor as mpy clip = mpy.VideoFileClip("spcial_video_tzuyu.mp4") subclip = clip.subclip(14.9,16.7) # 從第幾秒開始到第幾秒結束 subclip = subclip.resize(0.2) # 長寬皆乘上 0.2來縮小尺寸。 subclip.write_gif("try.gif") Resize共有下面四種方法 myClip.resize( (460,720) ) # New

[ OpenCV ] 利用 OpenCV進行臉部辨識批量訓練

圖片
透過上一章 " 利用 OpenCV抓取影片中的臉部數據 ",有了大量的圖片數據後,可能沒有辦法像之前一樣,全部一起訓練模型,必須採用批量訓練。 但模型更新受到一定的限制,官方說法是只有 Local Binary Pattern Histogram ( LBPH )可以對模型進行更新。所以本章只會使用 LBPH練習。 開始訓練前的資料夾結構如下 . ├── Chaeyoung │   └── ... ├── Dahyun │   └── ... ├── Jeongyeon │   └── ... ├── Jihyo │   └── ... ├── Mina │   └── ... ├── Momo │   └── ... ├── Nayeon │   └── ... ├── Sana │   └── ... ├── Tzuyu │   └── ... └── model_train.py model_train.py代碼如下 import os import cv2 import numpy as np batch = 50 names = ["Nayeon", "Jeongyeon", "Momo", "Sana", "Jihyo", "Mina", "Dahyun", "Chaeyoung", "Tzuyu"] model_LBPH = cv2.face.createLBPHFaceRecognizer() if os.path.isfile("./twice_model_LBPH.xml"): model_LBPH.load("twice_model_LBPH.xml") trained_data = 0 def model_training(x,y): if not os.path.isfile("./twice_model_LBPH.xml"): model_LBPH.train(np.asarray(x), np.asarray(y)) els

[ OpenCV ] 利用 OpenCV抓取影片中的臉部數據

圖片
除了網路爬蟲,也可以透過影片搜集數據。但由於畫面太連續,數據差異太小,訓練 ML或 DL可能會有 overfitting的問題,有必要對擷取的畫面進行一些篩選。 篩選的方法可以使用 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),) fo

[ OpenCV ] MacOS 無法使用 cv2.imshow()播放 Webcam的替代方案

圖片
OpenCV在 MacOS系統下有些功能無法使用, Python官方 也清楚地告知了。 IMPORTANT NOTE MacOS and Linux wheels have currently some limitations: video related functionality is not supported (not compiled with FFmpeg) for example  cv2.imshow()  will not work (not compiled with GTK+ 2.x or Carbon support) 嘗試了各種 OpenCV的安裝方法,OpenCV在 MacOS上總會碰上不少挫折。據說有人跟著這篇 安裝指南 後,能正常運作。但我安裝到一半仍然卡關了。 但為了使用 Webcam,不得不做一些妥協。若不願意在別的系統上開發,就只好先用一些替代方案。 import cv2 import numpy as np import matplotlib.pyplot as plt face_cascade = cv2.CascadeClassifier('./cascades/haarcascade_frontalface_default.xml') cam = cv2.VideoCapture(0) plt.ion() while(True): ret, img = cam.read() gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) faces = face_cascade.detectMultiScale(gray, 1.2, 3) for (x,y,w,h) in faces: img = cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2) img = cv2.flip(img,1) # 1 水平翻轉, 0 垂直翻轉, -1 水平垂直翻轉 img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) plt.imshow(img) plt.pause(.01) plt.cla() #

[ OpenCV ] 利用 OpenCV進行臉部辨識

圖片
之前寫了捕捉臉部的 Code後,就變得有點貪心了,想說試著看看能不能分類 Twice的成員。 先利用上一篇 " 利用 OpenCV抓取臉部數據 ",捕捉要訓練用的臉部圖片。 很殘酷的是,用同樣的參數抓取大量格式不一的網路圖片時,應該會有很多圖片的臉部捕捉錯誤,可能需要手工移除錯誤的圖片,目前我也沒有有效的方法去解決這個問題。有招的大大拜託不要留招。 開始之前,我的資料夾結構如下 . ├── cascades │   └── haarcascade_frontalface_default.xml ├── Chaeyoung │   └── ... ├── Dahyun │   └── ... ├── Jeongyeon │   └── ... ├── Jihyo │   └── ... ├── Mina │   └── ... ├── Momo │   └── ... ├── Nayeon │   └── ... ├── Sana │   └── ... ├── Tzuyu │   └── ... └── facial_recognition.py 裡面放著類似這樣的圖,大約每個成員都有40張左右的數據。     一個都不認識?沒關係,讓 OpenCV介紹給你認識。 import os import cv2 import numpy as np import random names = ['Nayeon', 'Jeongyeon', 'Momo', 'Sana', 'Jihyo', 'Mina', 'Dahyun', 'Chaeyoung', 'Tzuyu'] x,y = [],[] for idx,member in enumerate(names): for fileNames in os.walk("./%s" % member): for fileName in fileNames[-1]: if fileName == '.DS_Store':