Skip to content

Commit 7e98b90

Browse files
committed
Add Gabor filter,a linear filter used for texture analysis, which means that it basically analyzes whether there are any specific frequency content in the image in specific directions in a localized region around the point or region of analysis
1 parent 3f299f9 commit 7e98b90

17 files changed

+671
-0
lines changed
Binary file not shown.
Binary file not shown.
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# -*- coding: utf-8 -*-
2+
"""
3+
Created on Fri Apr 22 02:51:53 2016
4+
5+
@author: utkarsh
6+
"""
7+
8+
9+
10+
# FREQEST - Estimate fingerprint ridge frequency within image block
11+
#
12+
# Function to estimate the fingerprint ridge frequency within a small block
13+
# of a fingerprint image. This function is used by RIDGEFREQ
14+
#
15+
# Usage:
16+
# freqim = freqest(im, orientim, windsze, minWaveLength, maxWaveLength)
17+
#
18+
# Arguments:
19+
# im - Image block to be processed.
20+
# orientim - Ridge orientation image of image block.
21+
# windsze - Window length used to identify peaks. This should be
22+
# an odd integer, say 3 or 5.
23+
# minWaveLength, maxWaveLength - Minimum and maximum ridge
24+
# wavelengths, in pixels, considered acceptable.
25+
#
26+
# Returns:
27+
# freqim - An image block the same size as im with all values
28+
# set to the estimated ridge spatial frequency. If a
29+
# ridge frequency cannot be found, or cannot be found
30+
# within the limits set by min and max Wavlength
31+
# freqim is set to zeros.
32+
#
33+
# Suggested parameters for a 500dpi fingerprint image
34+
# freqim = freqest(im,orientim, 5, 5, 15);
35+
#
36+
# See also: RIDGEFREQ, RIDGEORIENT, RIDGESEGMENT
37+
38+
### REFERENCES
39+
40+
# Peter Kovesi
41+
# School of Computer Science & Software Engineering
42+
# The University of Western Australia
43+
# pk at csse uwa edu au
44+
# http://www.csse.uwa.edu.au/~pk
45+
46+
47+
import numpy as np
48+
import math
49+
import scipy.ndimage
50+
#import cv2
51+
def frequest(im,orientim,windsze,minWaveLength,maxWaveLength):
52+
rows,cols = np.shape(im);
53+
54+
# Find mean orientation within the block. This is done by averaging the
55+
# sines and cosines of the doubled angles before reconstructing the
56+
# angle again. This avoids wraparound problems at the origin.
57+
58+
59+
cosorient = np.mean(np.cos(2*orientim));
60+
sinorient = np.mean(np.sin(2*orientim));
61+
orient = math.atan2(sinorient,cosorient)/2;
62+
63+
# Rotate the image block so that the ridges are vertical
64+
65+
#ROT_mat = cv2.getRotationMatrix2D((cols/2,rows/2),orient/np.pi*180 + 90,1)
66+
#rotim = cv2.warpAffine(im,ROT_mat,(cols,rows))
67+
rotim = scipy.ndimage.rotate(im,orient/np.pi*180 + 90,axes=(1,0),reshape = False,order = 3,mode = 'nearest');
68+
69+
# Now crop the image so that the rotated image does not contain any
70+
# invalid regions. This prevents the projection down the columns
71+
# from being mucked up.
72+
73+
cropsze = int(np.fix(rows/np.sqrt(2)));
74+
offset = int(np.fix((rows-cropsze)/2));
75+
rotim = rotim[offset:offset+cropsze][:,offset:offset+cropsze];
76+
77+
# Sum down the columns to get a projection of the grey values down
78+
# the ridges.
79+
80+
proj = np.sum(rotim,axis = 0);
81+
dilation = scipy.ndimage.grey_dilation(proj, windsze,structure=np.ones(windsze));
82+
83+
temp = np.abs(dilation - proj);
84+
85+
peak_thresh = 2;
86+
87+
maxpts = (temp<peak_thresh) & (proj > np.mean(proj));
88+
maxind = np.where(maxpts);
89+
90+
rows_maxind,cols_maxind = np.shape(maxind);
91+
92+
# Determine the spatial frequency of the ridges by divinding the
93+
# distance between the 1st and last peaks by the (No of peaks-1). If no
94+
# peaks are detected, or the wavelength is outside the allowed bounds,
95+
# the frequency image is set to 0
96+
97+
if(cols_maxind<2):
98+
freqim = np.zeros(im.shape);
99+
else:
100+
NoOfPeaks = cols_maxind;
101+
waveLength = (maxind[0][cols_maxind-1] - maxind[0][0])/(NoOfPeaks - 1);
102+
if waveLength>=minWaveLength and waveLength<=maxWaveLength:
103+
freqim = 1/np.double(waveLength) * np.ones(im.shape);
104+
else:
105+
freqim = np.zeros(im.shape);
106+
107+
return(freqim);
108+
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# -*- coding: utf-8 -*-
2+
"""
3+
Created on Mon Apr 18 11:42:58 2016
4+
5+
@author: utkarsh
6+
"""
7+
8+
import numpy as np
9+
#import cv2
10+
#import numpy as np;
11+
import matplotlib.pylab as plt;
12+
import scipy.ndimage
13+
import sys
14+
import cv2
15+
16+
from image_enhance import image_enhance
17+
18+
19+
if(len(sys.argv)<2):
20+
print('loading sample image');
21+
img_name = '01.jpg'
22+
img = scipy.ndimage.imread('images/' + img_name);
23+
24+
elif(len(sys.argv) >= 2):
25+
img_name = sys.argv[1];
26+
img = scipy.ndimage.imread(sys.argv[1]);
27+
28+
if(len(img.shape)>2):
29+
# img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
30+
img = np.dot(img[...,:3], [0.299, 0.587, 0.114]);
31+
32+
33+
print(img.shape)
34+
35+
rows,cols = np.shape(img);
36+
aspect_ratio = np.double(rows)/np.double(cols);
37+
38+
new_rows = 350; # randomly selected number
39+
new_cols = new_rows/aspect_ratio;
40+
41+
#img = cv2.resize(img,(new_rows,new_cols));
42+
img = scipy.misc.imresize(img,(np.int(new_rows),np.int(new_cols)));
43+
44+
enhanced_img = image_enhance(img);
45+
enhanced_img = 255*np.uint8(enhanced_img)
46+
kernel = np.ones((5,5),np.uint8)
47+
# closing = cv2.morphologyEx(enhanced_img, cv2.MORPH_OPEN, kernel)
48+
erosion = cv2.erode(enhanced_img,kernel,iterations = 1)
49+
50+
cv2.imshow('output',enhanced_img)
51+
cv2.waitKey(0)
52+
53+
54+
55+
if(1):
56+
print('saving the image')
57+
scipy.misc.imsave('../enhanced/' + img_name, enhanced_img)
58+
else:
59+
plt.imshow(enhanced_img,cmap = 'Greys_r');
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# -*- coding: utf-8 -*-
2+
"""
3+
Created on Mon Apr 18 22:50:30 2016
4+
5+
@author: utkarsh
6+
"""
7+
from ridge_segment import ridge_segment
8+
from ridge_orient import ridge_orient
9+
from ridge_freq import ridge_freq
10+
from ridge_filter import ridge_filter
11+
import cv2
12+
import numpy as np
13+
import scipy.ndimage
14+
15+
def image_enhance(img):
16+
blksze = 40;
17+
thresh=0.1
18+
normim,mask = ridge_segment(img,blksze,thresh); # normalise the image and find a ROI
19+
temp=normim -normim.min()
20+
temp =temp/temp.max()
21+
cv2.imshow("normim",normim)
22+
cv2.waitKey(0)
23+
24+
gradientsigma = 1;
25+
blocksigma = 9;
26+
orientsmoothsigma = 7;
27+
orientim = ridge_orient(normim, gradientsigma, blocksigma, orientsmoothsigma); # find orientation of every pixel
28+
cv2.imshow("orientim",orientim)
29+
cv2.waitKey(0)
30+
31+
blksze = 50;
32+
windsze = 5;
33+
minWaveLength = 5;
34+
maxWaveLength = 15;
35+
freq,medfreq = ridge_freq(normim, mask, orientim, blksze, windsze, minWaveLength,maxWaveLength); #find the overall frequency of ridges
36+
37+
38+
freq = medfreq*mask;
39+
kx = 0.65;ky = 0.65;
40+
newim = ridge_filter(normim, orientim, freq, kx, ky); # create gabor filter and do the actual filtering
41+
# temp=newim-newim.min();
42+
# temp = temp/temp.max()
43+
# cv2.imshow('output',newim)
44+
# cv2.waitKey(0)
45+
46+
47+
#gray = cv2.cvtColor(newim, cv2.COLOR_BGR2GRAY)
48+
#thresholding
49+
th, bin_im = cv2.threshold(np.uint8(newim),0,255,cv2.THRESH_BINARY);
50+
# cv2.imshow('out',bin_im)
51+
# cv2.waitKey(0)
52+
# th3 = cv2.adaptiveThreshold((bin_im).astype('uint8'),255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,11,2)
53+
54+
# cv2.imshow('out',th3)
55+
# kernel = np.ones((5,5),np.uint8)
56+
# closing = cv2.morphologyEx(bin_im, cv2.MORPH_OPEN, kernel)
57+
# cv2.imshow('outclosed',closing)
58+
# cv2.waitKey(0)
59+
60+
cv2.waitKey(0)
61+
return(newim<th )
Loading
Loading
Loading
Binary file not shown.
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
# -*- coding: utf-8 -*-
2+
"""
3+
Created on Fri Apr 22 03:15:03 2016
4+
5+
@author: utkarsh
6+
"""
7+
8+
9+
# RIDGEFILTER - enhances fingerprint image via oriented filters
10+
#
11+
# Function to enhance fingerprint image via oriented filters
12+
#
13+
# Usage:
14+
# newim = ridgefilter(im, orientim, freqim, kx, ky, showfilter)
15+
#
16+
# Arguments:
17+
# im - Image to be processed.
18+
# orientim - Ridge orientation image, obtained from RIDGEORIENT.
19+
# freqim - Ridge frequency image, obtained from RIDGEFREQ.
20+
# kx, ky - Scale factors specifying the filter sigma relative
21+
# to the wavelength of the filter. This is done so
22+
# that the shapes of the filters are invariant to the
23+
# scale. kx controls the sigma in the x direction
24+
# which is along the filter, and hence controls the
25+
# bandwidth of the filter. ky controls the sigma
26+
# across the filter and hence controls the
27+
# orientational selectivity of the filter. A value of
28+
# 0.5 for both kx and ky is a good starting point.
29+
# showfilter - An optional flag 0/1. When set an image of the
30+
# largest scale filter is displayed for inspection.
31+
#
32+
# Returns:
33+
# newim - The enhanced image
34+
#
35+
# See also: RIDGEORIENT, RIDGEFREQ, RIDGESEGMENT
36+
37+
# Reference:
38+
# Hong, L., Wan, Y., and Jain, A. K. Fingerprint image enhancement:
39+
# Algorithm and performance evaluation. IEEE Transactions on Pattern
40+
# Analysis and Machine Intelligence 20, 8 (1998), 777 789.
41+
42+
### REFERENCES
43+
44+
# Peter Kovesi
45+
# School of Computer Science & Software Engineering
46+
# The University of Western Australia
47+
# pk at csse uwa edu au
48+
# http://www.csse.uwa.edu.au/~pk
49+
50+
51+
52+
import numpy as np
53+
import scipy;
54+
def ridge_filter(im, orient, freq, kx, ky):
55+
angleInc = 3;
56+
im = np.double(im);
57+
rows,cols = im.shape;
58+
newim = np.zeros((rows,cols));
59+
60+
freq_1d = np.reshape(freq,(1,rows*cols));
61+
ind = np.where(freq_1d>0);
62+
63+
ind = np.array(ind);
64+
ind = ind[1,:];
65+
66+
# Round the array of frequencies to the nearest 0.01 to reduce the
67+
# number of distinct frequencies we have to deal with.
68+
69+
non_zero_elems_in_freq = freq_1d[0][ind];
70+
non_zero_elems_in_freq = np.double(np.round((non_zero_elems_in_freq*100)))/100;
71+
72+
unfreq = np.unique(non_zero_elems_in_freq);
73+
74+
# Generate filters corresponding to these distinct frequencies and
75+
# orientations in 'angleInc' increments.
76+
77+
sigmax = 1/unfreq[0]*kx;
78+
sigmay = 1/unfreq[0]*ky;
79+
80+
sze = np.round(3*np.max([sigmax,sigmay]));
81+
82+
x,y = np.meshgrid(np.linspace(-sze,sze,(2*sze + 1)),np.linspace(-sze,sze,(2*sze + 1)));
83+
84+
reffilter = np.exp(-(( (np.power(x,2))/(sigmax*sigmax) + (np.power(y,2))/(sigmay*sigmay)))) * np.cos(2*np.pi*unfreq[0]*x); # this is the original gabor filter
85+
86+
filt_rows, filt_cols = reffilter.shape;
87+
88+
gabor_filter = np.array(np.zeros((int(180/angleInc), (filt_rows), (filt_cols)), dtype = int))
89+
90+
angle_for_iter = (0,180/angleInc)
91+
start_angle, last_angle = angle_for_iter
92+
start_angle = int(start_angle)
93+
last_angle = int(last_angle)
94+
print(last_angle)
95+
for o in range(start_angle,last_angle):
96+
97+
# Generate rotated versions of the filter. Note orientation
98+
# image provides orientation *along* the ridges, hence +90
99+
# degrees, and imrotate requires angles +ve anticlockwise, hence
100+
# the minus sign.
101+
rot_filt = scipy.ndimage.rotate(reffilter,-(o*angleInc + 90),reshape = False);
102+
gabor_filter[o] = rot_filt;
103+
104+
# Find indices of matrix points greater than maxsze from the image
105+
# boundary
106+
107+
maxsze = int(sze);
108+
109+
temp = freq>0;
110+
validr,validc = np.where(temp)
111+
112+
temp1 = validr>maxsze;
113+
temp2 = validr<rows - maxsze;
114+
temp3 = validc>maxsze;
115+
temp4 = validc<cols - maxsze;
116+
117+
final_temp = temp1 & temp2 & temp3 & temp4;
118+
119+
finalind = np.where(final_temp);
120+
121+
# Convert orientation matrix values from radians to an index value
122+
# that corresponds to round(degrees/angleInc)
123+
124+
maxorientindex = np.round(180/angleInc);
125+
orientindex = np.round(orient/np.pi*180/angleInc);
126+
127+
#do the filtering
128+
129+
for i in range(0,rows):
130+
for j in range(0,cols):
131+
if(orientindex[i][j] < 1):
132+
orientindex[i][j] = orientindex[i][j] + maxorientindex;
133+
if(orientindex[i][j] > maxorientindex):
134+
orientindex[i][j] = orientindex[i][j] - maxorientindex;
135+
finalind_rows,finalind_cols = np.shape(finalind);
136+
sze = int(sze);
137+
for k in range(0,finalind_cols):
138+
r = validr[finalind[0][k]];
139+
c = validc[finalind[0][k]];
140+
141+
img_block = im[r-sze:r+sze + 1][:,c-sze:c+sze + 1];
142+
143+
newim[r][c] = np.sum(img_block * gabor_filter[int(orientindex[r][c]) - 1]);
144+
145+
return(newim);

0 commit comments

Comments
 (0)