La détection d'images similaires est l'une des fonctions les plus couramment utilisées dans la reconnaissance d'images. Les systèmes de recommandation et de recherche utilisent souvent des dizaines de milliers ou des centaines de milliers d'images. Selon la taille des images et la méthode de comparaison, la recherche d'images similaires parmi des milliers ou des dizaines de milliers nécessite un temps de traitement énorme. Par conséquent, nous allons envisager une méthode pour détecter des images similaires en réduisant la quantité de données et le nombre de comparaisons en utilisant k-means et PCA.
Face Recognition Les fonctionnalités de visage utilisent face_landmark, qui est représentée par un vecteur de 128 dimensions et peut être implémentée dans la bibliothèque à l'URL suivante. https://github.com/ageitgey/face_recognition
Le nombre de dimensions après l'APC a été fixé à 20 tout en observant le taux de cotisation. Après avoir effectué l'ACP et réduit les dimensions, classer en grappes avec K = 10 par k-moyennes. Le plus proche est calculé à partir du centre de gravité de chaque cluster, et seules les images classées dans le cluster avec le centre de gravité le plus proche sont calculées et la distance est calculée pour détecter des images similaires. Il est également efficace pour réduire la capacité de stockage en enregistrant les caractéristiques de l'image sous forme de données réduites par PCA.
En utilisant 1000 images, le clustering par la méthode des k-moyennes permet de comparer 100 fois + 10 fois (comparaison avec le centre de gravité de chaque cluster) en moyenne. De plus, le nombre de dimensions de chaque vecteur a été réduit de 128 à 20 par PCA, de sorte que la quantité de calcul peut être efficacement réduite.
http://mmlab.ie.cuhk.edu.hk/projects/CelebA.html Cette fois, la source d'échantillon utilisant cette image de visage libre est indiquée ci-dessous.
# coding:utf-8
import dlib
from imutils import face_utils
import cv2
import glob
import face_recognition
from sklearn.decomposition import PCA
from sklearn.cluster import KMeans
from matplotlib import pyplot as plt
import numpy as np
# --------------------------------
# 1.Préparation à la détection des points de repère du visage
# --------------------------------
#Outil de détection de visage d'appel
face_detector = dlib.get_frontal_face_detector()
#Appeler un outil de détection de repère de visage
predictor_path = 'shape_predictor_68_face_landmarks.dat'
face_predictor = dlib.shape_predictor(predictor_path)
images = glob.glob('./faces/*.jpg')
images = sorted(images)[:100]
face_landmarks = []
face_filepaths = []
for filepath in images:
#Appel de l'image à détecter
img = face_recognition.load_image_file(filepath)
face_encodings = face_recognition.face_encodings(img)
if (len(face_encodings)>0):
face_filepaths.append(filepath)
face_landmarks.append(face_encodings[0])
pca = PCA(n_components=20)
pca.fit(face_landmarks)
#Convertir l'ensemble de données en composant principal en fonction du résultat de l'analyse
transformed = pca.fit_transform(face_landmarks)
#Tracer les principaux composants
# plt.subplot(1, 2, 2)
plt.scatter(transformed[:, 0], transformed[:, 1])
plt.title('principal component')
plt.xlabel('pc1')
plt.ylabel('pc2')
#Sortez le taux de cotisation pour chaque dimension de la composante principale
print(pca.explained_variance_ratio_)
print(sum(pca.explained_variance_ratio_))
# print(transformed[0])
# print(len(transformed[0]))
#Démarrer Kmeans
#Nombre de clusters
K = 8
cls = KMeans(n_clusters = 8)
pred = cls.fit_predict(transformed)
#Colorez chaque élément pour chaque étiquette
for i in range(K):
labels = transformed[pred == i]
plt.scatter(labels[:, 0], labels[:, 1])
#Centroïde du cluster(Centre de gravité)Dessiner
centers = cls.cluster_centers_
plt.scatter(centers[:, 0], centers[:, 1], s=100,
facecolors='none', edgecolors='black')
#Trouvez le centre de gravité le plus proche de vous
min_center_distance = -1
min_center_k = 0
#Trouvez quel centre de gravité est le plus éloigné
max_center_distance = -1
max_center_k = 0
for center_index in range(K):
distance = np.linalg.norm(transformed[0] - centers[center_index])
if ( distance < min_center_distance or min_center_distance == -1):
min_center_distance = distance
min_center_k = center_index
if ( distance > max_center_distance or max_center_distance == -1):
max_center_distance = distance
max_center_k = center_index
#Afficher les noms d'image des clusters les plus proches et les plus éloignés
print('=========== NEAREST ==============')
for i in range(len(pred)):
if ( min_center_k == pred[i] ):
print(face_filepaths[i])
print('=========== FARTHEST ==============')
for i in range(len(pred)):
if ( max_center_k == pred[i] ):
print(face_filepaths[i])
print('=========================')
#Afficher le graphique
plt.show()
#* En dessous se trouve une jambe de serpent
#Calculez la distance directe à chaque image
distance = {}
for index in range(len(transformed)):
distance[face_filepaths[index]] = np.linalg.norm(transformed[0] - transformed[index])
#Trié et affiché par ordre de distance
print(sorted(distance.items(), key=lambda x:x[1]))
Les traits de l'image, dont le centre de gravité est divisé en grappes par des cercles creux, sont affichés dans différentes couleurs. C'est un peu difficile à comprendre car le graphique à 20 dimensions est tracé en 2 dimensions, mais vous pouvez voir que les principaux composants qui sont proches les uns des autres sont regroupés.
Image basée sur l'analyse
1.jpg |
---|
Images contenues dans le même cluster
10.jpg | 11.jpg | 19.jpg | 24.jpg |
---|---|---|---|
Image contenue dans le cluster avec le centre de gravité le plus éloigné
12.jpg | 37.jpg | 51.jpg | 60.jpg |
---|---|---|---|
Un grand nombre des images divisées dans le même groupe étaient des femmes aux cheveux longs, et beaucoup des images divisées dans le groupe le plus éloigné étaient des hommes aux cheveux courts, donc je pense qu'un regroupement similaire à la sensation humaine était possible. Si vous voulez obtenir une image plus rigoureuse, vous devez calculer la norme directement comme l'image entière sans analyser les composants principaux, mais elle semble être utilisée cette fois pour viser le hasard et réaliser un calcul plus rapide. Il semble bon d'envisager la méthode.
Recommended Posts