Advanced face recognition with Python
Stokry
Posted on April 20, 2021
Imagine that we have thousands of images inside of a folder and we want to delete all images where a particular person appears. That process can take hours or even days, and that's where this script comes in.
The program works in a simple way, you need to load a folder and choose an image of the person, after that the script will find all images associated with that person and delete them.
This is a dataset: https://www.kaggle.com/anku5hk/5-faces-dataset
Let's jump to the code!
First we need to import dependencies
import tkinter as tk
from threading import Thread
from tkinter.filedialog import askopenfilename
from tkinter.filedialog import askdirectory
from PIL import ImageTk, Image
from tkinter.ttk import Progressbar
from tkinter import messagebox
import face_recognition
import os
I am using Face Recognition.
Recognize and manipulate faces from Python or from the command line with the world’s simplest face recognition library. Built using dlib’s state-of-the-art face recognition built with deep learning.
Since this is a GUI we are using the tkinter
:
class FaceApp(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.geometry("900x800")
self.resizable(True, True)
self.title('Bulker')
row = tk.Frame(self)
lab = tk.Label(row, width=5, text="Image : ", anchor='w')
self._file_field = tk.Entry(row)
self._file_open_btn = tk.Button(row, text='Find',
command=lambda: self.load_file())
row1 = tk.Frame(self)
lab1 = tk.Label(row1, width=5, text="Folder : ", anchor='w')
self._folder_field = tk.Entry(row1)
self._folder_open_btn = tk.Button(row1, text='Open',
command=lambda: self.load_folder())
self._image_panel = tk.Frame(self)
bottom_row = tk.Frame(self)
self._start_btn = tk.Button(bottom_row, text='Start',
command=lambda: self.run_process())
self._progress = Progressbar(bottom_row, orient=tk.HORIZONTAL, length=500, mode='determinate')
lab.pack(side=tk.LEFT, padx=30)
self._file_field.pack(side=tk.LEFT, ipadx=250)
self._file_open_btn.pack(side=tk.LEFT, ipadx=10, padx=10)
row.pack(side=tk.TOP, fill=tk.X, padx=10, pady=8)
lab1.pack(side=tk.LEFT, padx=30)
self._folder_field.pack(side=tk.LEFT, ipadx=250)
self._folder_open_btn.pack(side=tk.LEFT, ipadx=10, padx=10)
row1.pack(side=tk.TOP, fill=tk.X, padx=10, pady=8)
self._image_panel.pack(side=tk.TOP, fill=tk.X, padx=10, pady=8)
self._start_btn.pack(side=tk.BOTTOM, ipadx=10, padx=10)
self._progress.pack(side=tk.BOTTOM, pady=5)
bottom_row.pack(side=tk.TOP, fill=tk.X, padx=10, pady=8)
Our GUI looks like this:
After that we define our load_file
, load_folder
with option to delete current value:
def load_file(self):
filename = askopenfilename()
self._file_field.delete(0, tk.END)
self._file_field.insert(0, filename)
for widget in self._image_panel.winfo_children():
widget.destroy()
img = ImageTk.PhotoImage(Image.open(filename))
panel = tk.Label(self._image_panel, image=img)
panel.img = img
panel.pack(side="bottom", fill="both", expand="yes")
def load_folder(self):
filename = askdirectory()
self._folder_field.delete(0, tk.END)
self._folder_field.insert(0, filename)
Next we can define start_process
and run_process
:
def start_process(self):
ref_path = self._file_field.get()
folder_path = self._folder_field.get()
self.find_and_delete(folder_path, ref_path)
def run_process(self):
self._run_task = True
t = Thread(target=self.start_process)
t.start()
Then actual process start, we need to find and delete the face (images):
def find_and_delete(self, directory, ref_image_path):
ref_face = self.get_ref_face(ref_image_path)
if ref_face is None:
messagebox.showinfo("Error", "Can't find a face. Reference Image quality is not enough")
return
files = os.listdir(directory)
i = 1
for filename in files:
try:
percentage = int((i / len(files)) * 100)
self._progress['value'] = percentage
self.update_idletasks()
i += 1
file_path = os.path.join(directory, filename)
if self.is_user_in_image(ref_face, file_path):
os.remove(file_path)
print(filename, 'deleted.')
except:
print('Error reading file', filename)
messagebox.showinfo("Information", "Process Finished")
def get_ref_face(self, ref_image_path):
try:
ref_image = face_recognition.load_image_file(ref_image_path)
ref_face = face_recognition.face_encodings(ref_image)[0]
return ref_face
except:
return None
def is_user_in_image(self, ref_face, image_path):
unknown_picture = face_recognition.load_image_file(image_path)
unknown_faces = face_recognition.face_encodings(unknown_picture)
for unknown_face in unknown_faces:
results = face_recognition.compare_faces([ref_face], unknown_face)
if results[0]:
return True
return False
if __name__ == "__main__":
app = FaceApp()
app.mainloop()
Program will find all images of Bill Gates and delete them.
Full code: Bulker
If anybody wants to be a part of this project, feel free to tell me. The script needs to be fast and have better accuracy.
You are all more than welcome.
Posted on April 20, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.