Commit 26200fcf authored by Antoine Rollet's avatar Antoine Rollet

Upload New File

parent 4725314e
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Tue Nov 5 15:45:23 2019
@author: Anthony Yang & Antoine Rollet
"""
#import des librairies nécessaires
#PIL est nécessaire pour lire les images au format JPEG
import matplotlib.pyplot as plt
import numpy as np
import sklearn.decomposition as decomp
import PIL
import os
import random
import time
#Chemins d'accès aux images de la base de données
folder_path="C:/Users/Antoine/Documents/FISE_2021_M1/ODATA/data/dataset1/images/"
#On liste les noms de fichiers de toutes les images à notre disposition
filenames=os.listdir(folder_path)[:]
#
#la liste photos contient le nom de toutes les images sans leur extension
# -4 ==> retire ".jpg" à la fin des noms de fichers
photos=[filename[:-4] for filename in filenames]
#On liste le nom de tous les individus ayant une photo (on s'arrête donc après le premier point ("."))
individus=[photo[:photo.find(".")] for photo in photos]
individus=list(set(individus)) # suppression des doublons (un individu = plusieurs images)
#Nombre d'individus à rechercher dont on va supprimer les images = Nombre d'individus dont on va garder des images dans la base
# Nombre de requêtes = 2*nbr_a_suppr
nbr_a_suppr=100
individus_supprimes=[]
#On stocke le nom des individus dont les images seront supprimées de la BDD dans individus_supprimes, la méthode "pop" les retire de la liste individus
for i in range(nbr_a_suppr):
ind=np.random.randint(len(individus))
individus_supprimes.append(individus.pop(ind))
a_suppr=[]
for j in range(len(photos)):
p=photos[j]
for indi in individus_supprimes:
if indi in p:
a_suppr.append(j) #On récupère les indices des éléments (noms des photos) à supprimer
a_suppr.reverse() # On commence par supprimer les derniers éléments pour ne pas créer de décalage lors des pops
for j in a_suppr:
photos.pop(j)
# On retire toutes les photos correspondant à des individus dont on ne veut plus dans la BDD
# On recrée les noms des photos des requêtes des individus plus présents dans la BDD
# On choisit à chaque fois la première photo par facilité
requetes_fausses=[indi+".1" for indi in individus_supprimes]
# On crée les requêtes (=nom de la photo) pour les individus encore présents dans la BDD
# Encore une fois pour chaque individu choisi, on prend sa première photo par facilité
individus_presents=[individus[i] for i in random.sample(range(len(individus)),nbr_a_suppr)]
requetes_vraies=[indi+".1" for indi in individus_presents]
# On retire quand même ces photos de la BDD mais en gardant les autres de l'inidividu
for r in requetes_vraies:
photos.remove(r)
# Création des tableaux de données, requêtes vraies, requêtes fausses
# Maintenant, nous avons le nom de toutes les photos-requêtes et les photos-gallery (c'est-à-dire toutes les photos sauf celles des reqûetes et sauf toutes les autres des individus des reqûetes considérées comme fausses)
# On transforme toutes les photos en tableau numpy, chaque ligne = une photo = un vecteur de taille 150*150 = 22500
gallery_list=[]
i=0
filenames=[photo + ".jpg" for photo in photos] #On remet les extensions de fichiers
for file in filenames:
img=plt.imread(folder_path+file)
gallery_list.append(list(img.flatten()))
i+=1
print(i)
complete_gallery=np.array(gallery_list)
true_probes_list=[]
i=0
filenames=[r + ".jpg" for r in requetes_vraies] #On remet les extensions de fichiers
for file in filenames:
img=plt.imread(folder_path+file)
true_probes_list.append(list(img.flatten()))
i+=1
print(i)
complete_true_probes=np.array(true_probes_list)
false_probes_list=[]
i=0
filenames=[r + ".jpg" for r in requetes_fausses] #On remet les extensions de fichiers
for file in filenames:
img=plt.imread(folder_path+file)
false_probes_list.append(list(img.flatten()))
i+=1
print(i)
complete_false_probes=np.array(false_probes_list)
# Transformation des données avec Eigenfaces
eigenfaces=True
if eigenfaces:
# k= nombre de dimensions que l'on gardera à la fin
# La procédure suivante est celle détaillée en 8.2 du sujet afin d'éviter de faire une ACP avec 22500 variables (une variable = un pixel)
k=50
M=np.concatenate((complete_gallery,complete_false_probes,complete_true_probes))
# Centrage des données
M=M-np.mean(M,axis=0)
cov_M_t=np.cov(M)
#Récupération des valeurs et vecteurs propres
v=(np.linalg.eig(cov_M_t))
w=M.transpose().dot(np.real(v[1]))
# Normalisation des vecteurs obtenus
for i in range(w.shape[1]):
w[:,i]=w[:,i]/np.sqrt(sum(w[:,i]**2))
new_M=M.dot(w[:,:k])
# On re-sépare les données entre gallery, requêtes vraies (individus présents dans la BDD) et requêtes fausses (individus absents de la BDD)
complete_gallery=new_M[:-2*nbr_a_suppr]
complete_false_probes=new_M[-2*nbr_a_suppr:-nbr_a_suppr]
complete_true_probes=new_M[-nbr_a_suppr:]
# Calcul du seuil
# Une étape importante est la détermination du seuil à partir duquel on estime que deux photos représentés par des vecteurs correspondent à un même individu
# La méthode est expliquée plus en détail dans le rapport
def euclid(A,B):
assert len(A)==len(B)
return np.sqrt(sum((A-B)**2))
def calcul_de_r():
m_dist=[]
for i in range(len(photos)):
p=photos[i]
ind=p[:p.find(".")]
photos_same_ind=[]
for j in range(len(photos)):
if ind in photos[j]:
photos_same_ind.append(j)
other_photos=complete_gallery[photos_same_ind,:]
m=0
for p in other_photos:
m+=euclid(complete_gallery[i,:],p)
if len(photos_same_ind) >1:
m_dist.append(m/(len(photos_same_ind)-1))
print(m/(len(photos_same_ind)-1))
print(i)
return np.mean(m_dist)
R=calcul_de_r()
# Force brute
# Les deux systèmes reposent sur la force brute: on va comparer chaque photo avec la requête et si la distance euclidienne les séparant est inférieure à un certain seuil R déterminé au préalable, alors on considère que les photos correspondent à la même personne et l'authentifcation est réussie (=return True)
def aut(G,R,seuil):
for photo in G:
if euclid(photo,R)<=seuil:
return True
return False
# Positifs va contenir le résultat de la tentative d'authentification pour toutes les requêtes vraies. Dans le meilleur des cas, tous ses éléments sont vrais.
t0=time.time()
positifs=[]
for req in complete_true_probes:
positifs.append(aut(complete_gallery,req,R))
# Négatifs va contenir le résultat de la tentative d'authentification pour toutes les requêtes fausses. Dans le meilleur des cas, tous ses éléments sont faux.
negatifs=[]
for req in complete_false_probes:
negatifs.append(aut(complete_gallery,req,R))
t_recherche=time.time()-t0
# Les fonctions des différents mesures de précision en fonction des listes positives et négatives définies ci-dessus
def exactitude(pos,neg):
n1=len(pos)
n2=len(neg)
return (sum(pos)+n2-sum(neg))/(n1+n2)
def precision(pos,neg):
return sum(pos)/(sum(pos)+sum(neg))
def rappel(pos,neg):
return sum(pos)/len(pos)
def sensibilite(pos,neg):
n1=len(pos)
n2=len(neg)
return (n2-sum(neg))/n2
# Affichage des résultats obtenus
print("Temps nécessaires à l'authentification des",2*nbr_a_suppr,"requêtes:",t_recherche)
print("Exactitude:",exactitude(positifs,negatifs))
print("Precision:", precision(positifs,negatifs))
print("Rappel:",rappel(positifs,negatifs))
print("Sensibilité:",sensibilite(positifs,negatifs))
# Les tableaux présents dans le rapport présentent des résultats en faisant varier les paramètres suivants: eigenfaces (True/False), k(50/10/5 si eigenfaces = True) et folder_path (pour changer de dataset)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment