This code loosely follows the approach presented by
Hong, L., Wan, Y., and Jain, A. K. 'Fingerprint image enhancement: Algorithm and performance evaluation'. IEEE Transactions on Pattern Analysis and Machine Intelligence 20, 8 (1998), pp 777-789.
Ridge regions in the image are identified and normalised, ridge orientations are determined, local ridge frequencies calculated, and then contextual filters with the appropriate orientation and frequency are applied.
im = imread('finger.png'); % Identify ridge-like regions and normalise image blksze = 16; thresh = 0.1; [normim, mask] = ridgesegment(im, blksze, thresh); show(normim,1); % Determine ridge orientations [orientim, reliability] = ridgeorient(normim, 1, 5, 5); plotridgeorient(orientim, 20, im, 2) show(reliability,6)
'Reliability' of orientations
% Determine ridge frequency values across the image blksze = 36; [freq, medfreq] = ridgefreq(normim, mask, orientim, blksze, 5, 5, 15); show(freq,3)
% Actually I find the median frequency value used across the whole % fingerprint gives a more satisfactory result... freq = medfreq.*mask; % Now apply filters to enhance the ridge pattern newim = ridgefilter(normim, orientim, freq, 0.5, 0.5, 1); show(newim,4);
% Binarise, ridge/valley threshold is 0 binim = newim > 0; show(binim,5);
% Display binary image for where the mask values are one and where % the orientation reliability is greater than 0.5 show(binim.*mask.*(reliability>0.5), 7)
Masked binary image
It would probably be sensible to apply a morphological closing to the (reliability > 0.5) masking image so that small 'holes' in the reliability data (which often occur at minutiae points) are removed.
Download this code example
I leave it to you to thin the binary image and then try to pick out the valid minutiae...