顔データのクレンジング

検証目的で顔データをインターネットからダウンロードした時、出処が違う写真で同じ顔が並ぶことがよくあります。その様な重複している顔写真ファイルを削除します。

ソースコード

import glob
import itertools

import cv2
import face_recognition as fr
import numpy as np
import shutil

def make_same_face_csv():
    # priset_face_imagesのpath
    priset_face_images_dir = 'priset_face_images'

    # print(finished_face_list[0][0])

    # ファイル全てをlistにする
    priset_face_images_list = glob.glob(priset_face_images_dir + '/*.png')
    priset_face_images_list.sort()

    # 初期化
    counter=0
    same_face_list=[]
    tmp_list=[]
    pair_list=[]

    # 同じファイル名だけ顔距離を測定する
    for file in priset_face_images_list:

        path, file_name = file.split('/', 1)
        name, _ = file_name.split('_', 1)
        if counter==0:
            print(file_name, '行きます!')
            tmp_list=[]
            pair_list=[]
            tmp_list.append(file_name)
            counter=+1
        else:
            if name in tmp_list[0]:
                # print(file_name, 'をtmp_listに加えます')
                tmp_list.append(file_name)
            else:
                # ペアが作れなければcontinue
                if len(tmp_list) < 2:
                    counter = 0
                    continue

                pair_list = list(itertools.combinations(tmp_list, 2))
                for pair in pair_list:
                    first = priset_face_images_dir + '/' + pair[0]
                    second = priset_face_images_dir + '/' + pair[1]

                    first_ndarray = cv2.imread(first)
                    first_face_location = fr.face_locations(first_ndarray,model='cnn')
                    if len(first_face_location)==0:
                        with open('no_face.csv', 'a') as fo:
                            fo.write(pair[0])
                            fo.write('\n')
                        continue
                    first_face = fr.face_encodings(first_ndarray,known_face_locations=first_face_location)

                    second_nadarray = cv2.imread(second)
                    second_face_location = fr.face_locations(second_nadarray, model='cnn')
                    if len(second_face_location)==0:
                        with open('no_face.csv', 'a') as fo:
                            fo.write(pair[1])
                            fo.write('\n')
                        continue
                    second_face = fr.face_encodings(second_nadarray,known_face_locations=second_face_location)

                    distance = np.linalg.norm(first_face[0] - second_face[0], ord=2, axis=None)
                    # if distance==0:
                    if distance<0.18:
                        print(pair)
                        first_file_path = priset_face_images_dir + '/' + pair[0]
                        second_file_path = priset_face_images_dir + '/' + pair[1]
                        
                        # csvファイルに書き込み
                        with open('same_face_file.csv', 'a') as fo:
                            fo.write(first_file_path)
                            fo.write(',')
                            fo.write(second_file_path)
                            fo.write('\n')
                        
                        # リストに格納
                        same_face_list.append(pair)
                
                    # 初期化
                    counter=0

    return same_face_list

def remove_duplicate_face():
    with open('same_face_file.csv', 'r') as fi:
        line_list = fi.read().split('\n')
        for line in line_list:
            if line=='':
                continue
            a, b = line.split(',', 1)
            print(b)  # removeする
            try:
                shutil.move(b, './same')
            except:
                pass

def csv_to_list():
    # 初期化
    finished_face_list=[]
    with open('same_face_file.csv', 'r') as fi:
        finished_face_list.append(fi.read().split('\n'))
    
    return finished_face_list

if __name__=='__main__':

    # finished_face_list = csv_to_list()
    # print(finished_face_list[0][0])
    # print(finished_face_list[0][1])
    # print(finished_face_list[0][2])

    same_face_list = make_same_face_csv()

    remove_duplicate_face()
    
    pass

結果

priset_face_images/トータス松本_16.png,priset_face_images/トータス松本_7.png
priset_face_images/トータス松本_20.png,priset_face_images/トータス松本_8.png
priset_face_images/トータス松本_20.png,priset_face_images/トータス松本_default.png

csvファイルの中身は以下の様になっています。

priset_face_images/トータス松本_16.png,priset_face_images/トータス松本_7.png
priset_face_images/トータス松本_20.png,priset_face_images/トータス松本_8.png
priset_face_images/トータス松本_20.png,priset_face_images/トータス松本_default.png
priset_face_images/トータス松本_6.png,priset_face_images/トータス松本_8.png
priset_face_images/トータス松本_8.png,priset_face_images/トータス松本_default.png
priset_face_images/上島竜兵_1.png,priset_face_images/上島竜兵_18.png
priset_face_images/上島竜兵_1.png,priset_face_images/上島竜兵_2.png
priset_face_images/上島竜兵_11.png,priset_face_images/上島竜兵_12.png
priset_face_images/上島竜兵_18.png,priset_face_images/上島竜兵_2.png
priset_face_images/上村愛子_23.png,priset_face_images/上村愛子_5.png
priset_face_images/上村愛子_8.png,priset_face_images/上村愛子_9.png
priset_face_images/上田まりえ_10.png,priset_face_images/上田まりえ_15.png
priset_face_images/上田まりえ_17.png,priset_face_images/上田まりえ_6.png
priset_face_images/上田まりえ_18.png,priset_face_images/上田まりえ_23.png
priset_face_images/上田晋也_10.png,priset_face_images/上田晋也_6.png
priset_face_images/上田晋也_12.png,priset_face_images/上田晋也_39.png
priset_face_images/上田晋也_13.png,priset_face_images/上田晋也_45.png
priset_face_images/上田晋也_2.png,priset_face_images/上田晋也_3.png
priset_face_images/上田晋也_2.png,priset_face_images/上田晋也_9.png
priset_face_images/上田晋也_24.png,priset_face_images/上田晋也_7.png
priset_face_images/上田晋也_3.png,priset_face_images/上田晋也_9.png
priset_face_images/上田晋也_4.png,priset_face_images/上田晋也_43.png
以下略

実際にフォルダ内を確認すると以下の図の様に顔が重複した複数のファイルが確認できました。

顔が重複している複数ファイル

考察

16,471枚の顔写真ファイルが14,208枚まで減りました。同じ顔があっても計算資源を余計に消費するだけですのでデータのクレンジングは必須です。顔認証を使うと顔認証に必要なデータを顔認証でクレンジングするという事が出来るんですね。

今回はこれで以上です。最後までお読み頂きありがとうございました。