How to Enhance Fingerprint Images Without Blurring Ridges? i am using django [closed]
How to Enhance Fingerprint Images Without Blurring Ridges? i am using django. I'm currently working on a fingerprint enhancement project using OpenCV, and while my code is producing results, the ridges in the fingerprint images are coming out blurred. here is my code
import cv2
import numpy as np
import math
import fingerprint_enhancer # Ensure this module is available
from django.shortcuts import render
from django.core.files.base import ContentFile
from .forms import HandFingerForm
from .models import ThumbImage
import base64
MAX_IMAGES = 10
def remove_green(img):
empty_img = np.zeros_like(img)
RED, GREEN, BLUE = (2, 1, 0)
reds = img[:, :, RED]
greens = img[:, :, GREEN]
blues = img[:, :, BLUE]
# Create a mask for the areas to keep
tmpMask = (greens < 35) | (reds > greens) | (blues > greens)
img[tmpMask == 0] = (0, 0, 0) # Remove background from original picture
empty_img[tmpMask] = (255, 255, 255) # Mask with finger in white
return img, empty_img
def detect_nail(gray_mask_finger):
# Find contours in the mask image
contours, _ = cv2.findContours(gray_mask_finger, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for contour in contours:
# Only consider large enough contours as nails
if cv2.contourArea(contour) > 100: # Adjust this threshold as needed
x, y, w, h = cv2.boundingRect(contour)
# Draw a rectangle around the detected nail
cv2.rectangle(gray_mask_finger, (x, y), (x + w, y + h), (255, 0, 0), 2) # Blue rectangle
def process_fingerprint(image):
clip_hist_percent = 25
# Convert to grayscale
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# Calculate grayscale histogram
hist = cv2.calcHist([gray], [0], None, [256], [0, 256])
hist_size = len(hist)
# Calculate cumulative distribution from the histogram
accumulator = []
accumulator.append(float(hist[0]))
for index in range(1, hist_size):
accumulator.append(accumulator[index - 1] + float(hist[index]))
# Locate points to clip
maximum = accumulator[-1]
clip_hist_percent *= (maximum / 100.0)
clip_hist_percent /= 2.0
# Locate left cut
minimum_gray = 0
while accumulator[minimum_gray] < clip_hist_percent:
minimum_gray += 1
# Locate right cut
maximum_gray = hist_size - 1
while accumulator[maximum_gray] >= (maximum - clip_hist_percent):
maximum_gray -= 1
# Calculate alpha and beta values
alpha = 255 / (maximum_gray - minimum_gray)
beta = -minimum_gray * alpha
auto_result = cv2.convertScaleAbs(image, alpha=alpha, beta=beta)
gray = cv2.cvtColor(auto_result, cv2.COLOR_BGR2GRAY)
# Compute gamma
mid = 0.5
mean = np.mean(gray)
gamma = math.log(mid * 255) / math.log(mean)
# Apply gamma correction
img_gamma = np.power(auto_result, gamma).clip(0, 255).astype(np.uint8)
g1 = cv2.cvtColor(img_gamma, cv2.COLOR_BGR2GRAY)
# Adaptive thresholding
thresh2 = cv2.adaptiveThreshold(g1, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY, 199, 3)
# Morphological operations
blur = ((3, 3), 1)
erode_ = (5, 5)
dilate_ = (3, 3)
dilate = cv2.dilate(cv2.erode(cv2.GaussianBlur(thresh2 / 255, blur[0], blur[1]),
np.ones(erode_)), np.ones(dilate_)) * 255
# Enhance fingerprint
out = fingerprint_enhancer.enhance_Fingerprint(dilate)
return out
def upload_image(request):
if 'upload_count' not in request.session:
request.session['upload_count'] = 0
upload_count = request.session['upload_count']
if request.method == 'POST':
if 'skip' in request.POST:
request.session['upload_count'] = 0
return render(request, 'captureimage.html', {
'message': 'Skipped the remaining uploads.',
'next_finger': None,
'max_images': MAX_IMAGES
})
finger_number = request.POST.get('finger')
image_data = request.POST.get('image')
if not image_data or ';base64,' not in image_data:
return render(request, 'captureimage.html', {
'error': 'Invalid image data',
'next_finger': upload_count + 1,
'max_images': MAX_IMAGES
})
try:
format, imgstr = image_data.split(';base64,')
except ValueError:
return render(request, 'captureimage.html', {
'error': 'Failed to parse image data',
'next_finger': upload_count + 1,
'max_images': MAX_IMAGES
})
ext = format.split('/')[-1]
image_file = ContentFile(base64.b64decode(imgstr), name=f'finger_{finger_number}.{ext}')
form_data = {'finger': finger_number}
form_files = {'image': image_file}
form = HandFingerForm(form_data, form_files)
if form.is_valid():
form.save()
# Load and process the saved image
saved_image_path = form.instance.image.path
image = cv2.imread(saved_image_path, 1) # Load the image
image = cv2.resize(image, None, fx=0.3, fy=0.3) # Resize
image = cv2.GaussianBlur(image, (3, 3), 0) # Apply Gaussian blur
# Process fingerprint
enhanced_image = process_fingerprint(image)
# Remove green background
no_green_image, mask_finger = remove_green(enhanced_image)
# Convert to grayscale
gray_mask_finger = cv2.cvtColor(mask_finger, cv2.COLOR_BGR2GRAY)
# Call the function to detect nail
detect_nail(gray_mask_finger)
request.session['upload_count'] += 1
if request.session['upload_count'] < MAX_IMAGES:
return render(request, 'captureimage.html', {
'message': 'Finger image uploaded successfully.',
'next_finger': request.session['upload_count'] + 1,
'max_images': MAX_IMAGES
})
else:
request.session['upload_count'] = 0
return render(request, 'captureimage.html', {
'message': 'All 10 images uploaded successfully!',
'next_finger': None,
'max_images': MAX_IMAGES
})
else:
return render(request, 'captureimage.html', {
'error': 'Invalid form data',
'details': form.errors,
'next_finger': upload_count + 1,
'max_images': MAX_IMAGES
})
return render(request, 'captureimage.html', {
'next_finger': request.session['upload_count'] + 1,
'max_images': MAX_IMAGES
})
#frontend
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Capture Finger Image</title>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap" rel="stylesheet">
<style>
body {
font-family: 'Roboto', sans-serif;
background-color: #f4f4f9;
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
.container {
background: #ffffff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
max-width: 500px;
width: 100%;
text-align: center;
}
h2 {
margin-bottom: 20px;
color: #333;
}
#instructions {
font-size: 1.1em;
margin-bottom: 20px;
color: #555;
}
#video {
width: 100%;
border-radius: 8px;
margin-bottom: 10px;
border: 2px solid #007bff;
}
#preview {
margin: 10px 0;
}
#capturedImage {
max-width: 100%;
border-radius: 8px;
border: 2px solid #28a745;
}
select {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
margin-bottom: 20px;
font-size: 1em;
}
.button-group {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
margin-top: 20px;
}
button {
background-color: #007bff;
color: white;
border: none;
border-radius: 4px;
padding: 10px 15px;
font-size: 1em;
cursor: pointer;
transition: background-color 0.3s;
flex: 1;
margin: 5px;
}
button:hover {
background-color: #0056b3;
}
.skip-btn {
background-color: #dc3545;
}
.skip-btn:hover {
background-color: #c82333;
}
/* Responsive styles */
@media (max-width: 600px) {
.button-group {
flex-direction: column;
}
button {
margin: 5px 0;
}
}
</style>
</head>
<body>
<div class="container">
<h2>Capture Finger Image</h2>
<div id="instructions">
Please select a finger and place it in front of the camera with good lighting for a clear image.
</div>
<!-- Display Success or Error Message -->
{% if message %}
<p style="color:green;">{{ message }}</p>
{% elif error %}
<p style="color:red;">{{ error }}</p>
{% endif %}
<div class="video-container">
<!-- Video stream -->
<video id="video" autoplay></video>
<!-- Preview for captured image -->
<div id="preview">
<p>Captured Image:</p>
<img id="capturedImage" src="" alt="No image captured yet">
</div>
</div>
<!-- Dropdown for selecting finger -->
<form id="fingerForm">
<select id="fingerSelect" name="finger">
<option value="">Select Finger</option>
<option value="Right Thumb">Right Thumb</option>
<option value="Left Thumb">Left Thumb</option>
<option value="Right Index">Right Index</option>
<option value="Left Index">Left Index</option>
<option value="Right Middle">Right Middle</option>
<option value="Left Middle">Left Middle</option>
<option value="Right Ring">Right Ring</option>
<option value="Left Ring">Left Ring</option>
<option value="Right Pinky">Right Pinky</option>
<option value="Left Pinky">Left Pinky</option>
</select>
</form>
<div class="button-group">
<button id="snap">Capture Finger Image</button>
<!-- Image Upload Form -->
<form id="imageForm" action="{% url 'upload_image' %}" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<input type="hidden" name="image" id="imageInput">
<button type="submit" id="uploadButton" disabled>Upload Finger Image</button>
</form>
<!-- Skip Button -->
<form action="{% url 'upload_image' %}" method="POST">
{% csrf_token %}
<button type="submit" class="skip-btn" name="skip" value="true">Skip Remaining</button>
</form>
</div>
</div>
<script>
const video = document.getElementById('video');
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
const snap = document.getElementById('snap');
const imageInput = document.getElementById('imageInput');
const capturedImage = document.getElementById('capturedImage');
const uploadButton = document.getElementById('uploadButton');
const fingerSelect = document.getElementById('fingerSelect');
// Access the camera with higher resolution for better detail
navigator.mediaDevices.getUserMedia({ video: { width: 1280, height: 720 } })
.then((stream) => {
video.srcObject = stream;
})
.catch((error) => {
console.error("Error accessing camera: ", error);
});
// Capture image on button click
snap.addEventListener('click', () => {
// Check if a finger is selected
if (fingerSelect.value === "") {
alert("Please select a finger before capturing the image.");
return;
}
// Set canvas size to match the video feed
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
// Apply a sharpness filter to enhance the fingerprint details
context.filter = 'contrast(1.5) brightness(1.2)'; // Adjust contrast and brightness for clarity
context.drawImage(video, 0, 0, canvas.width, canvas.height);
// Convert the canvas image to base64
const dataURL = canvas.toDataURL('image/png');
imageInput.value = dataURL; // Set base64 image in hidden input
// Display the captured image in the img tag
capturedImage.src = dataURL;
// Set the selected finger in the form data
const fingerInput = document.createElement('input');
fingerInput.type = 'hidden';
fingerInput.name = 'finger';
fingerInput.value = fingerSelect.value;
document.getElementById('imageForm').appendChild(fingerInput);
// Enable the upload button
uploadButton.disabled = false;
});
// Enable form submission when a finger is selected
fingerSelect.addEventListener('change', () => {
if (fingerSelect.value !== "") {
uploadButton.disabled = true; // Reset button state
}
});
</script>
</body>
</html>
#models.py
from django.db import models
class ThumbImage(models.Model):
FINGER_CHOICES = [
('Right Thumb', 'Right Thumb'),
('Left Thumb', 'Left Thumb'),
('Right Index', 'Right Index'),
('Left Index', 'Left Index'),
('Right Middle', 'Right Middle'),
('Left Middle', 'Left Middle'),
('Right Ring', 'Right Ring'),
('Left Ring', 'Left Ring'),
('Right Pinky', 'Right Pinky'),
('Left Pinky', 'Left Pinky'),
]
finger = models.CharField(max_length=50, choices=FINGER_CHOICES)
image = models.ImageField(upload_to='finger_images/')
def __str__(self):
return f"{self.finger} image"
I’m currently working on a project that focuses on enhancing fingerprint images using OpenCV. I've been implementing various techniques, including converting the images to grayscale, applying histogram equalization, performing gamma correction, using adaptive thresholding, and carrying out morphological operations.
Initially, these steps seemed to improve the contrast and clarity of the images. However, I've encountered a problem: the ridge patterns in the fingerprints appear blurred instead of sharp. I expected to see clear, well-defined ridges, but the final results are lacking in clarity.
I would love to hear any suggestions or adjustments I can make to improve the ridge clarity in my fingerprint images. Any advice would be greatly appreciated!