[ 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(member)): os.system("mkdir ./{0}/similar".format(member)) print("make dir ./{0}/similar".format(member)) os.system("mv {0} ./{1}/similar".format(hash_one_path, member)) print("move {0} to {1}".format(hash_one_path, member)) continue hash_two = hash_one names = ["Nayeon", "Jeongyeon", "Momo", "Sana", "Jihyo", "Mina", "Dahyun", "Chaeyoung", "Tzuyu"] for member in names: filter(member)最近發現可以用 glob來取代之前文章用的 os.walk,使用起來更加簡單。
之前的文章中,將捕捉的圖像利用 1.png, 2.png, 3.png...這樣的順序儲存。
但無論用 glob或 os.walk都會面臨一樣的問題,就是讀取時,數字並不會連續,顯示如下
['./Tzuyu/1.png', './Tzuyu/10.png', './Tzuyu/100.png', './Tzuyu/1000.png', './Tzuyu/1001.png', './Tzuyu/1002.png', ...]
但影片是連續性的,有必要按照順序讀取來比較,因此需要使用 sort()來重新排列。
擔心有些人看不懂,所以另外寫了幾行被註解的代碼。功能和有 lambda那行是一樣的。
接著就是計算平均 Hash值,和下一個張圖做比較,distance小於等於 2就將該圖片移至 similar資料夾中。
至於 Hamming distance到底要以多少作為基準就要各位自己拿捏了。
這個程序將會將 1.png作為比較的基準,直到有 distance大於 2的圖,便會將該圖作為比較的基準繼續往下比較。
distance設定保留大於 2的圖,其實相似度還是挺高的,需要視情況調整 distance。
如果是想要比較全部的照片,就不需要在意順序,但需要注意 list的邏輯,有點像一群人握手次數的問題。
import os import glob import photohash def filter(member): img_list = glob.glob('./{0}/*.png'.format(member)) while True: if img_list==[]: break img_target = img_list.pop() img_hash_target = photohash.average_hash(img_target) for img in img_list: hash_one = photohash.average_hash(img) distance = photohash.hash_distance(img_hash_target, hash_one) if distance <= 2: if not os.path.isdir("./{0}/similar".format(member)): os.system("mkdir ./{0}/similar".format(member)) print("make dir ./{0}/similar".format(member)) os.system("mv {0} ./{1}/similar".format(img, member)) print("move {0} to ./{1}/similar".format(img, member)) img_list.remove(img) names = ["Nayeon", "Jeongyeon", "Momo", "Sana", "Jihyo", "Mina", "Dahyun", "Chaeyoung", "Tzuyu"] for member in names: filter(member)
之前用 PyTorch寫了一個 CNN的影像辨識,原本就有預期會權重失衡,但實在有點懶就直接拿來訓練了,結果權重好像真的失衡了。
當然原因不只這個,不過本來就有必要剔除相似度過高的圖像,但相似度高不高又不是我說的算,所以才尋找一個比較科學的方式來進行篩選。
最近發現有好像比較好的方式對照片相似進行篩選,有機會再介紹吧。
留言
張貼留言