Blockwise PCA & Sobel seem to be way off for ridge angle detection
As a forewarning, complete hobbyist here. I'm attempting to enhance the capture of fingerprints via camera. I'm performing the following steps:
- Image normalization using equalizeHist
- Blockwise Sobel for edge detection
- Angle extraction using phase
- Average of angles within the block
I then draw these angles out but they appear to vary wildly. I also tried another method using blockwise PCA, but also have a similar result. Here is the resulting image:
and here is my code so far:
#!/usr/bin/env python3
import cv2
import numpy as np
import math
def draw_angle(img, center, angle, length=10):
line_start_x = int(center[0] + length * math.cos(angle))
line_end_x = int(center[0] - length * math.cos(angle))
line_start_y = int(center[1] + length * math.sin(angle))
line_end_y = int(center[1] - length * math.sin(angle))
cv2.line(img, (line_start_x, line_start_y), (line_end_x, line_end_y), (255, 255, 0), 1)
def process_sobel(img, block_size=16):
rows, cols = img.shape
# Apply a histogram to clarify ridges
hist = cv2.equalizeHist(img)
histc = cv2.cvtColor(hist, cv2.COLOR_GRAY2RGB)
x = 0
y = 0
while y < rows - block_size:
y2 = y + block_size
while x < cols - block_size:
x2 = x + block_size
block_grax_x = cv2.Sobel(hist[y:y2, x:x2], cv2.CV_32F, 1, 0, ksize=3, scale=1, delta=0, borderType=cv2.BORDER_DEFAULT)
block_grax_y = cv2.Sobel(hist[y:y2, x:x2], cv2.CV_32F, 0, 1, ksize=3, scale=1, delta=0, borderType=cv2.BORDER_DEFAULT)
angles = cv2.phase(block_grax_x, block_grax_y)
angle = math.degrees(np.average(angles))
center = (int(x + block_size / 2), int(y + block_size / 2))
draw_angle(histc, center, angle)
cv2.rectangle(histc, (x, y), (x2, y2), (0, 0, 0), 1)
x = x2
y = y2
x = 0
return histc
def process_pca(img, block_size=16):
rows, cols = img.shape
# Apply a histogram to clarify ridges
hist = cv2.equalizeHist(img)
histc = cv2.cvtColor(hist, cv2.COLOR_GRAY2RGB)
x = 0
y = 0
while y < rows - block_size:
y2 = y + block_size
while x < cols - block_size:
x2 = x + block_size
block = hist[y:y2, x:x2]
_, eigvec, _ = cv2.PCACompute2(block, mean=None)
angle = math.atan2(eigvec[0, 1], eigvec[0, 0])
center = (int(x + block_size / 2), int(y + block_size / 2))
draw_angle(histc, center, angle)
cv2.rectangle(histc, (x, y), (x2, y2), (0, 0, 0), 1)
x = x2
y = y2
x = 0
return histc
img = cv2.imread('fingerprint2.jpg', 0)
img = process_sobel(img, 16)
cv2.imwrite('result.png', img)
I'm not too sure where I'm going wrong, it feels like I'm misunderstanding something with the operations I'm doing. Although some of the blocks appear to be spot on. I've also tried larger block sizes. All advice would be welcomed at this point.
doing anything with blocks as small as this seems to be futile (why blocks, even ?)
some filtering (e.g. gabor) followed by thinning is used mostly
@smarts. Can u post original image?