[ PhotoHash ] 利用 PhotoHash篩選相似度過高的圖像
子瑜在這部影片中,前 14秒幾乎沒有任何的動作。
若用 "利用 Dlib進行臉部捕捉" 該文中提供的程式碼,這 14秒的影片大約會擷取300多張的圖像。
用這筆數據訓練後,可能會導致權重失衡。
為了避免權重失衡影響辨識結果,有必要對圖像進行一些篩選。
用爬蟲爬取圖片的時候也容易爬到不同出處但卻是同一張照片,這麼做也很方便呦。
Hamming distance可以作為數據差異度的基準,詳細可以到維基百科了解一下。
對於圖像差異度的比較,Python也有一套 Library叫 PhotoHash可以幫忙比較圖像的差異。
先計算整張圖像的平均 Hash值後,再計算 Hamming distance。
最近發現可以用 glob來取代之前文章用的 os.walk,使用起來更加簡單。
- 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)
之前的文章中,將捕捉的圖像利用 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的影像辨識,原本就有預期會權重失衡,但實在有點懶就直接拿來訓練了,結果權重好像真的失衡了。
當然原因不只這個,不過本來就有必要剔除相似度過高的圖像,但相似度高不高又不是我說的算,所以才尋找一個比較科學的方式來進行篩選。
最近發現有好像比較好的方式對照片相似進行篩選,有機會再介紹吧。
留言
張貼留言