diff --git a/examples/fingerprint_template_folder_compare_with_file_rpi.py b/examples/fingerprint_template_folder_compare_with_file_rpi.py new file mode 100644 index 0000000..b68ef5b --- /dev/null +++ b/examples/fingerprint_template_folder_compare_with_file_rpi.py @@ -0,0 +1,273 @@ +# SPDX-FileCopyrightText: 2024 itsFDavid +# SPDX-License-Identifier: MIT +""" +`fingerprint_template_folder_compare_with_file.py` +==================================================== + +This is an example program to demo storing fingerprint templates in a folder. It also allows +comparing a newly obtained print with one stored in the folder in the previous step. This is helpful +when fingerprint templates are stored centrally (not on sensor's flash memory) and shared +between multiple sensors. + +* Author(s): itsFDavid + +Implementation Notes +-------------------- +This program was used on other fingerprint sensors, +and everything worked as expected, including testing with Raspberry Pi Zero 2W. + +To run the program: +1. Connect the fingerprint sensor to your Raspberry Pi. +2. Install required libraries. +3. Execute the script using Python. +""" + +import os +import time + +import serial +from PIL import Image +import adafruit_fingerprint + +# If using with a computer such as Linux/RaspberryPi, Mac, Windows with USB/serial converter: +# uart = serial.Serial("COM6", baudrate=57600, timeout=1) + +# If using with Linux/Raspberry Pi and hardware UART: +uart = serial.Serial("/dev/ttyUSB0", baudrate=57600, timeout=1) + +finger = adafruit_fingerprint.Adafruit_Fingerprint(uart) + +# Folder where fingerprint templates are stored +FINGERPRINT_FOLDER = "fingerprint/" + + +# Enroll and verification functions +def get_num(max_num): + """Prompts the user to enter a valid template number within the available range.""" + while True: + try: + num = int(input(f"Enter a template number (0-{max_num}): ")) + if 0 <= num <= max_num: + return num + print(f"Please enter a number between 0 and {max_num}.") + except ValueError: + print("Invalid input. Please enter a valid number.") + + +def get_fingerprint(): + """Get an image from the fingerprint sensor for search, process for a match.""" + print("Waiting for finger...") + while finger.get_image() != adafruit_fingerprint.OK: + pass + print("Processing image...") + if finger.image_2_tz(1) != adafruit_fingerprint.OK: + print("Error processing image.") + return False + print("Searching for matches...") + return finger.finger_search() == adafruit_fingerprint.OK + + +def enroll_finger(location): + """Enroll a fingerprint and store it in the specified location.""" + for fingerimg in range(1, 3): + action = "Place finger on sensor" if fingerimg == 1 else "Same finger again" + print(action, end="") + while True: + if finger.get_image() == adafruit_fingerprint.OK: + print("Image captured") + break + print(".", end="") + print("Processing image...", end="") + if finger.image_2_tz(fingerimg) != adafruit_fingerprint.OK: + print("Error processing image.") + return False + if fingerimg == 1: + print("Remove finger") + time.sleep(1) + while finger.get_image() != adafruit_fingerprint.NOFINGER: + pass + print("Creating model...", end="") + if finger.create_model() != adafruit_fingerprint.OK: + print("Error creating model.") + return False + print(f"Storing model in location #{location}...", end="") + if finger.store_model(location) != adafruit_fingerprint.OK: + print("Error storing model.") + return False + print("Model stored.") + return True + + +def save_fingerprint_image(filename): + """Capture a fingerprint and save the image to a file.""" + print("Waiting for finger...") + while finger.get_image() != adafruit_fingerprint.OK: + pass + img = Image.new("L", (256, 288), "white") + pixeldata = img.load() + mask = 0b00001111 + result = finger.get_fpdata(sensorbuffer="image") + coor_x, coor_y = 0, 0 + for i, value in enumerate(result): + if i % 100 == 0: + print("", end="") + pixeldata[coor_x, coor_y] = (int(value) >> 4) * 17 + coor_x += 1 + pixeldata[coor_x, coor_y] = (int(value) & mask) * 17 + if coor_x == 255: + coor_x = 0 + coor_y += 1 + else: + coor_x += 1 + img.save(filename) + print(f"\nImage saved to {filename}") + return True + + +def enroll_save_to_file(): + """Capture a fingerprint, create a model, and save it to a file.""" + for fingerimg in range(1, 3): + action = "Place finger on sensor" if fingerimg == 1 else "Same finger again" + print(action, end="") + while True: + if finger.get_image() == adafruit_fingerprint.OK: + print("Image captured") + break + print(".", end="") + print("Processing image...", end="") + if finger.image_2_tz(fingerimg) != adafruit_fingerprint.OK: + print("Error processing image.") + return False + if fingerimg == 1: + print("Remove finger") + while finger.get_image() != adafruit_fingerprint.NOFINGER: + pass + print("Creating model...", end="") + if finger.create_model() != adafruit_fingerprint.OK: + print("Error creating model.") + return False + print("Storing template...") + data = finger.get_fpdata("char", 1) + filename = os.path.join(FINGERPRINT_FOLDER, f"template_{int(time.time())}.dat") + with open(filename, "wb") as file: + file.write(bytearray(data)) + print(f"Template saved to {filename}") + return True + + +def fingerprint_check_folder(): + """Compare a fingerprint with all files in the fingerprint folder.""" + print("Waiting for fingerprint...") + while finger.get_image() != adafruit_fingerprint.OK: + pass + print("Processing image...") + if finger.image_2_tz(1) != adafruit_fingerprint.OK: + print("Error processing image.") + return False + print("Searching for matches in the template folder...", end="") + found_match = False + matched_filename = None + for filename in os.listdir(FINGERPRINT_FOLDER): + if filename.endswith(".dat"): + file_path = os.path.join(FINGERPRINT_FOLDER, filename) + with open(file_path, "rb") as file: + data = file.read() + finger.send_fpdata(list(data), "char", 2) + if finger.compare_templates() == adafruit_fingerprint.OK: + matched_filename = filename + found_match = True + break + if found_match: + print(f"Fingerprint matches the template in the file {matched_filename}!") + else: + print("No match found.") + return found_match + + +def main(): + """Main function to run the fingerprint enrollment and verification program. + This function provides a menu for the user to enroll fingerprints, search for + fingerprints, delete templates, save fingerprint images, and reset the fingerprint library. + It interacts with the user via the console and performs the necessary actions based on + user input. + """ + while True: + print("----------------") + if finger.read_templates() != adafruit_fingerprint.OK: + raise RuntimeError("Could not read templates.") + print("Stored fingerprint templates: ", finger.templates) + + if finger.count_templates() != adafruit_fingerprint.OK: + raise RuntimeError("Could not count templates.") + print("Number of templates found: ", finger.template_count) + + if finger.read_sysparam() != adafruit_fingerprint.OK: + raise RuntimeError("Could not retrieve system parameters.") + print("Template library size: ", finger.library_size) + print("Options:") + print("e) Enroll fingerprint") + print("f) Search fingerprint") + print("d) Delete fingerprint") + print("s) Save fingerprint image") + print("cf) Compare template with file") + print("esf) Enroll and save to file") + print("r) Reset library") + print("q) Exit") + print("----------------") + user_choice = input("> ") + match user_choice.lower(): + case "e": + enroll_finger(get_num(finger.library_size)) + case "f": + print_fingerprint() + case "d": + delete_fingerprint() + case "s": + save_fingerprint_image(f"fingerprint_{int(time.time())}.png") + case "cf": + fingerprint_check_folder() + case "esf": + enroll_save_to_file() + case "r": + reset_library() + case "q": + exit_program() + case _: + print("Invalid option.") + + +def print_fingerprint(): + """Prints the fingerprint detection result.""" + if get_fingerprint(): + output_finger_detected = f"Fingerprint detected with ID #{finger.finger_id}" + output_finger_confidence = f"Confidence: {finger.confidence}" + print(output_finger_detected) + print(output_finger_confidence) + else: + print("Fingerprint not found.") + + +def delete_fingerprint(): + """Deletes a fingerprint model based on user input.""" + if finger.delete_model(get_num(finger.library_size)) == adafruit_fingerprint.OK: + print("Deleted successfully!") + else: + print("Failed to delete.") + + +def reset_library(): + """Resets the fingerprint library.""" + if finger.empty_library() == adafruit_fingerprint.OK: + print("Library reset.") + else: + print("Failed to reset library.") + + +def exit_program(): + """Exits the program.""" + print("Exiting...") + raise SystemExit + + +if __name__ == "__main__": + main()