Contactless Fingerprints Recognition in Python
Background
This research method proposes a contactless fingerprint recognition system that eliminates the need for physical contact and utilizes pure image processing techniques.The system is designed to run on a normal CPU core i3. The system captures finger photos from a distance using an image sensor or mobile camera and enhances them using image processing methods like Gabor filters and CLAHE. It extracts global features using a Siamese Convolutional Neural Network (CNN) and incorporates minutiae-based features for fingerprint matching. The matching scores obtained from both approaches are fused to generate the final matching score. The system achieves promising results in terms of accuracy, making it a viable option for contactless fingerprint recognition on a standard CPU core i3.
The process begins by capturing finger photos using an image sensor. These photos are then subjected to various image processing techniques, including Gabor filters and Contrast Limited Adaptive Histogram Equalization (CLAHE), among others. These techniques enhance the quality of the fingerprint images and improve the visibility of important features. To extract fingerprint features, a Siamese Convolutional Neural Network (CNN) is specifically designed.
This CNN is responsible for extracting global features from the given finger photos. Global features represent the overall fingerprint patterns and can aid in matching fingerprints accurately. Additionally, the system also incorporates minutiae-based features for fingerprint matching. Minutiae are small, distinctive ridge characteristics such as ridge endings and bifurcations. By analyzing these minutiae, the system can establish more detailed and localized patterns within the fingerprints. The matching process involves computing matching scores based on the CNN-based features and the minutiae-based features. The scores derived from both approaches are then fused to obtain the final matching score between the probe (input fingerprint) and reference fingerprint templates. This fusion process combines the strengths of global and local features, resulting in a more accurate and robust matching mechanism.
Very First, This code is implementing a function called remove_background that removes the background from images in a specified input folder and saves the resulting images in an output folder.
![Contactless Fingerprints Preprocessing Contactless Fingerprints Preprocessing](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQZIs8DFY9RH_smadR-DWVwWnC4ek0aO8uEI4N2qw7QpRF4mQtO_AzJGm4IqjRddB-e-aRRbjwCkYwYdCiZ01_y8R9nkF48RL_6A1FUGgxSKG5Cso4XpP26H-j0XYtwzDaBNzk_NYWZA8YmkxFtVl_Fj0g-itlMStL_Q_tE1pOPVDyi_MNIjbPTpk2OA/w400-h98/fing.PNG) |
Fingerprints Enhancement using Gabor Filter and different techniques |
Background Removal Script:
import cv2
import numpy as np
import osdef remove_background(input_folder_path, output_folder_path):
# Create the output folder if it doesn't exist
os.makedirs(output_folder_path, exist_ok=True)
# Loop through all image files in the input folder
for file_name in os.listdir(input_folder_path):
# Check if the file is an image
if file_name.endswith('.jpg') or file_name.endswith('.png'):
# Construct the full input and output file paths
input_file_path = os.path.join(input_folder_path, file_name)
output_file_path = os.path.join(output_folder_path, file_name)
# Read the image
imgo = cv2.imread(input_file_path)
# Removing the background
height, width = imgo.shape[:2]
# Create a mask holder
mask = np.zeros(imgo.shape[:2], np.uint8)
# Grab Cut the object
bgdModel = np.zeros((1, 65), np.float64)
fgdModel = np.zeros((1, 65), np.float64)
# Hard Coding the Rect… The object must lie within this rect.
rect = (10, 10, width - 30, height - 30)
cv2.grabCut(imgo, mask, rect, bgdModel, fgdModel, 5, cv2.GC_INIT_WITH_RECT)
mask = np.where((mask == 2) | (mask == 0), 0, 1).astype("uint8")
img1 = imgo * mask[:, :, np.newaxis]
# Get the background
background = cv2.absdiff(imgo, img1)
# Change all pixels in the background that are not dark enough to white
background[np.where((background > [30, 30, 30]).all(axis=2))] = [255, 255, 255]
# Add the background and the image
final = background + img1
# To be done – Smoothening the edges….
cv2.imwrite(output_file_path, final)
# Delete the input file
os.remove(input_file_path)
# Replace the folder paths
input_folder_path = r"C:\Users\FingerPrintRecognition\ReducedImages"
output_folder_path = r"C:\\FingerPrintRecognition\BackgroundRemoves"
remove_background(input_folder_path, output_folder_path)
Image Processing Code for Fingerprints Pattern Enhancement
import os
import cv2
import numpy as np
from skimage import io
from skimage.filters import frangi
def gabor_filter(img, sigma, theta, lambd, gamma, psi):
ksize = 31
kernel = cv2.getGaborKernel((ksize, ksize), sigma, theta, lambd, gamma, psi, ktype=cv2.CV_64F)
enhanced_img = cv2.filter2D(img, cv2.CV_64F, kernel)
enhanced_img = np.abs(enhanced_img)
enhanced_img = ((enhanced_img - np.min(enhanced_img)) / (np.max(enhanced_img) - np.min(enhanced_img))) * 255
return enhanced_img.astype(np.uint8)
def enhance_image(img):
# create a CLAHE object
clahe = cv2.createCLAHE(clipLimit=5, tileGridSize=(12, 12))
img = clahe.apply(img)
enhanced_img = enhance_ridges(img)
return enhanced_img
def normalize(img):
img_min, img_max = np.min(img), np.max(img)
normalized_img = (img - img_min) * (255 / (img_max - img_min))
return normalized_img.astype(np.uint8)
def enhance_ridges(img):
img = normalize(img)
sigmas = [1, 2, 3]
thetas = [np.pi * t / 6 for t in range(12)]
lambd = 3
gamma = 0.5
psi = 0
filtered_imgs = []
for sigma in sigmas:
for theta in thetas:
filtered_img = gabor_filter(img, sigma, theta, lambd, gamma, psi)
filtered_imgs.append(filtered_img)
enhanced_img = np.max(filtered_imgs, axis=0)
return enhanced_img
def binarize(img):
blockSize = 15
C = 3
binary_img = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, blockSize, C)
return binary_img
def denoise(img):
kernel = np.ones((1, 1), np.uint8)
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
closing = cv2.morphologyEx(opening, cv2.MORPH_CLOSE, kernel)
return closing
def process_fingerprint(img):
enhanced_img = enhance_image(img)
binary_img = binarize(enhanced_img)
denoised_img = denoise(binary_img)
return denoised_img
def main():
input_dir = r"C:\Users\PycharmProjects\FingerPrintRecognition\BackgroundRemoves" # Input folder path
output_dir = r"C:\Users\PycharmProjects\FingerPrintRecognition\frangi" # Output folder path
if not os.path.exists(output_dir):
os.makedirs(output_dir)
for filename in os.listdir(input_dir):
if filename.endswith(".jpg") or filename.endswith(".png"):
img_path = os.path.join(input_dir, filename)
img = io.imread(img_path, as_gray=True)
img = (img * 255).astype(np.uint8)
processed_fingerprint = process_fingerprint(img)
output_filename = f"{os.path.splitext(filename)[0]}.png"
output_img_path = os.path.join(output_dir, output_filename)
cv2.imwrite(output_img_path, processed_fingerprint)
print(f"Processed and saved {output_filename} to the output directory.")
os.remove(img_path)
print(f"Deleted {filename} from the input directory.")
print("All images processed successfully.")
if __name__ == "__main__":
main()
Fingerprints Matching and Verification
import numpy as np
import cv2 as cv
import glob, os
def match_fingerprints(single_image_folder, multiple_images_folder):
# Assume the single image is the first one in the directory
single_image_file = os.listdir(single_image_folder)[0]
single_image_path = os.path.join(single_image_folder, single_image_file)
input_img = cv.imread(single_image_path)
input_img = input_img.astype('uint8')
gray = cv.cvtColor(input_img, cv.COLOR_BGR2GRAY)
sift = cv.SIFT_create()
kp1, des1 = sift.detectAndCompute(input_img, None)
flag = 0
highest_match_percentage = 0
highest_match_file = None
for file in os.listdir(multiple_images_folder):
frame_path = os.path.join(multiple_images_folder, file)
frame = cv.imread(frame_path)
frame = frame.astype('uint8')
gray1 = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
sift = cv.SIFT_create()
kp2, des2 = sift.detectAndCompute(frame, None)
FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)
search_params = dict(checks=50)
flann = cv.FlannBasedMatcher(index_params, search_params)
matches = flann.knnMatch(des1, des2, k=2)
good = []
for m, n in matches:
if m.distance < 0.7 * n.distance:
good.append(m)
total_keypoints = min(len(kp1), len(kp2))
if total_keypoints > 0:
match_percentage = len(good) / total_keypoints * 100
print(f"Matched {file} with match percentage: {match_percentage}%")
if match_percentage > highest_match_percentage:
highest_match_percentage = match_percentage
highest_match_file = file
if len(good) > 10:
src_pts = np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1, 1, 2)
dst_pts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1, 1, 2)
M, mask = cv.findHomography(src_pts, dst_pts, cv.RANSAC, 5.0)
matchesMask = mask.ravel().tolist()
flag = 1
else:
matchesMask = None
draw_params = dict(matchColor=(0, 255, 0), # draw matches in green color
singlePointColor=None,
matchesMask=matchesMask, # draw only inliers
flags=2)
img1_kp = cv.drawKeypoints(input_img, kp1, None)
img2_kp = cv.drawKeypoints(frame, kp2, None)
img3 = cv.drawMatches(img1_kp, kp1, img2_kp, kp2, good, None, **draw_params)
if flag == 0:
print("No Matches among the given set!!")
else:
print(f"Highest match file: {highest_match_file} with match percentage: {highest_match_percentage}%")
# Delete the single_image_path file after all processing is complete
if os.path.isfile(single_image_path):
os.remove(single_image_path)
return os.path.splitext(highest_match_file)[0] if highest_match_file else None
Code Summary and Conclusion
The code provided implements several functions related to fingerprint image processing and matching. It utilizes various image processing techniques and algorithms to enhance fingerprint images, remove background, and match a single fingerprint image with a set of multiple fingerprint images. The following is a summary of each component:
Remove Background
The "remove_background" function takes an input folder path and an output folder path as parameters. It iterates through the files in the input folder and processes each image to remove the background using the GrabCut algorithm. The resulting foreground image is saved in the output folder.
Fingerprint Image Enhancement
The code includes functions for enhancing fingerprint images. It applies Contrast Limited Adaptive Histogram Equalization (CLAHE) to improve image contrast and uses Gabor filters to enhance the ridges in the fingerprint. The enhanced images are then converted to binary form through adaptive thresholding and noise removal techniques.
SIFT-Based Fingerprint Matching
The "match_fingerprints" function implements a fingerprint matching algorithm using the Scale-Invariant Feature Transform (SIFT) technique. It takes a single fingerprint image and a folder of multiple fingerprint images as input. The SIFT algorithm is used to detect and compute the keypoints and descriptors for the images. The FLANN matcher is applied to find matches between the descriptors, and the match percentage is calculated. The function returns the filename of the image with the highest match percentage.
Overall, the code provides functionalities to remove background from fingerprint images, enhance the quality of fingerprint images, and match a single fingerprint image with a set of multiple images using the SIFT algorithm. These components contribute to the broader goal of fingerprint image processing and analysis.
No comments:
Post a Comment