# 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:

1. Image normalization using equalizeHist
2. Blockwise Sobel for edge detection
3. Angle extraction using phase
4. 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 + length * math.cos(angle))
line_end_x   = int(center - length * math.cos(angle))

line_start_y = int(center + length * math.sin(angle))
line_end_y   = int(center - 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 = 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.

edit retag close merge delete

1

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

1

Sort by » oldest newest most voted

you're converting to degrees. math.sin/cos expect radians. don't convert to degrees.

more

Official site

GitHub

Wiki

Documentation