diff --git a/Image_Processing/src/Filters/src/gabor filter/frequency.py b/Image_Processing/src/Filters/src/gabor filter/frequency.py new file mode 100644 index 00000000..9a125e7d --- /dev/null +++ b/Image_Processing/src/Filters/src/gabor filter/frequency.py @@ -0,0 +1,123 @@ +# Metody biometryczne +# Przemyslaw Pastuszka + +from PIL import Image, ImageDraw +import utils +import argparse +import math + + +def points_on_line(line, W): + im = Image.new("L", (W, 3 * W), 100) + draw = ImageDraw.Draw(im) + draw.line([(0, line(0) + W), (W, line(W) + W)], fill=10) + im_load = im.load() + + points = [] + for x in range(0, W): + for y in range(0, 3 * W): + if im_load[x, y] == 10: + points.append((x, y - W)) + + del draw + del im + + dist = lambda x, y: (x - W / 2) ** 2 + (y - W / 2) ** 2 + + return sorted(points)[:W] + +def vec_and_step(tang, W): + (begin, end) = utils.get_line_ends(0, 0, W, tang) + (x_vec, y_vec) = (end[0] - begin[0], end[1] - begin[1]) + length = math.hypot(x_vec, y_vec) + (x_norm, y_norm) = (x_vec / length, y_vec / length) + step = length / W + + return (x_norm, y_norm, step) + +def block_frequency(i, j, W, angle, im_load): + tang = math.tan(angle) + ortho_tang = -1 / tang + + (x_norm, y_norm, step) = vec_and_step(tang, W) + (x_corner, y_corner) = (0 if x_norm >= 0 else W, 0 if y_norm >= 0 else W) + + grey_levels = [] + + for k in range(0, W): + line = lambda x: (x - x_norm * k * step - x_corner) * ortho_tang + y_norm * k * step + y_corner + points = points_on_line(line, W) + level = 0 + for point in points: + level += im_load[point[0] + i * W, point[1] + j * W] + grey_levels.append(level) + + treshold = 100 + upward = False + last_level = 0 + last_bottom = 0 + count = 0.0 + spaces = len(grey_levels) + for level in grey_levels: + if level < last_bottom: + last_bottom = level + if upward and level < last_level: + upward = False + if last_bottom + treshold < last_level: + count += 1 + last_bottom = last_level + if level > last_level: + upward = True + last_level = level + + return count / spaces if spaces > 0 else 0 + +def freq(im, W, angles): + (x, y) = im.size + im_load = im.load() + freqs = [[0] for i in range (0, int(x / W))] + + for i in range(1, int(x / W - 1)): + for j in range(1, int(y / W - 1)): + freq = block_frequency(i, j, W, angles[i][j], im_load) + freqs[i].append(freq) + freqs[i].append(0) + + freqs[0] = freqs[-1] = [0 for i in range(0, y / W)] + + return freqs + +def freq_img(im, W, angles): + (x, y) = im.size + freqs = freq(im, W, angles) + freq_img = im.copy() + + for i in range(1, x / W - 1): + for j in range(1, y / W - 1): + box = (i * W, j * W, min(i * W + W, x), min(j * W + W, y)) + freq_img.paste(freqs[i][j] * 255.0 * 1.2, box) + + return freq_img + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Image frequency") + parser.add_argument("image", nargs=1, help = "Path to image") + parser.add_argument("block_size", nargs=1, help = "Block size") + parser.add_argument('--smooth', "-s", action='store_true', help = "Use Gauss for smoothing") + args = parser.parse_args() + + im = Image.open(args.image[0]) + im = im.convert("L") # covert to grayscale + im.show() + + W = int(args.block_size[0]) + + f = lambda x, y: 2 * x * y + g = lambda x, y: x ** 2 - y ** 2 + + angles = utils.calculate_angles(im, W, f, g) + if args.smooth: + angles = utils.smooth_angles(angles) + + freq_img = freq_img(im, W, angles) + freq_img.show() diff --git a/Image_Processing/src/Filters/src/gabor filter/frequest.py b/Image_Processing/src/Filters/src/gabor filter/frequest.py new file mode 100644 index 00000000..44d0ee46 --- /dev/null +++ b/Image_Processing/src/Filters/src/gabor filter/frequest.py @@ -0,0 +1,108 @@ +# -*- coding: utf-8 -*- +""" +Created on Fri Apr 22 02:51:53 2016 + +@author: utkarsh +""" + + + +# FREQEST - Estimate fingerprint ridge frequency within image block +# +# Function to estimate the fingerprint ridge frequency within a small block +# of a fingerprint image. This function is used by RIDGEFREQ +# +# Usage: +# freqim = freqest(im, orientim, windsze, minWaveLength, maxWaveLength) +# +# Arguments: +# im - Image block to be processed. +# orientim - Ridge orientation image of image block. +# windsze - Window length used to identify peaks. This should be +# an odd integer, say 3 or 5. +# minWaveLength, maxWaveLength - Minimum and maximum ridge +# wavelengths, in pixels, considered acceptable. +# +# Returns: +# freqim - An image block the same size as im with all values +# set to the estimated ridge spatial frequency. If a +# ridge frequency cannot be found, or cannot be found +# within the limits set by min and max Wavlength +# freqim is set to zeros. +# +# Suggested parameters for a 500dpi fingerprint image +# freqim = freqest(im,orientim, 5, 5, 15); +# +# See also: RIDGEFREQ, RIDGEORIENT, RIDGESEGMENT + +### REFERENCES + +# Peter Kovesi +# School of Computer Science & Software Engineering +# The University of Western Australia +# pk at csse uwa edu au +# http://www.csse.uwa.edu.au/~pk + + +import numpy as np +import math +import scipy.ndimage +#import cv2 +def frequest(im,orientim,windsze,minWaveLength,maxWaveLength): + rows,cols = np.shape(im); + + # Find mean orientation within the block. This is done by averaging the + # sines and cosines of the doubled angles before reconstructing the + # angle again. This avoids wraparound problems at the origin. + + + cosorient = np.mean(np.cos(2*orientim)); + sinorient = np.mean(np.sin(2*orientim)); + orient = math.atan2(sinorient,cosorient)/2; + + # Rotate the image block so that the ridges are vertical + + #ROT_mat = cv2.getRotationMatrix2D((cols/2,rows/2),orient/np.pi*180 + 90,1) + #rotim = cv2.warpAffine(im,ROT_mat,(cols,rows)) + rotim = scipy.ndimage.rotate(im,orient/np.pi*180 + 90,axes=(1,0),reshape = False,order = 3,mode = 'nearest'); + + # Now crop the image so that the rotated image does not contain any + # invalid regions. This prevents the projection down the columns + # from being mucked up. + + cropsze = int(np.fix(rows/np.sqrt(2))); + offset = int(np.fix((rows-cropsze)/2)); + rotim = rotim[offset:offset+cropsze][:,offset:offset+cropsze]; + + # Sum down the columns to get a projection of the grey values down + # the ridges. + + proj = np.sum(rotim,axis = 0); + dilation = scipy.ndimage.grey_dilation(proj, windsze,structure=np.ones(windsze)); + + temp = np.abs(dilation - proj); + + peak_thresh = 2; + + maxpts = (temp np.mean(proj)); + maxind = np.where(maxpts); + + rows_maxind,cols_maxind = np.shape(maxind); + + # Determine the spatial frequency of the ridges by divinding the + # distance between the 1st and last peaks by the (No of peaks-1). If no + # peaks are detected, or the wavelength is outside the allowed bounds, + # the frequency image is set to 0 + + if(cols_maxind<2): + freqim = np.zeros(im.shape); + else: + NoOfPeaks = cols_maxind; + waveLength = (maxind[0][cols_maxind-1] - maxind[0][0])/(NoOfPeaks - 1); + if waveLength>=minWaveLength and waveLength<=maxWaveLength: + freqim = 1/np.double(waveLength) * np.ones(im.shape); + else: + freqim = np.zeros(im.shape); + + return(freqim); + \ No newline at end of file diff --git a/Image_Processing/src/Filters/src/gabor filter/gabor.py b/Image_Processing/src/Filters/src/gabor filter/gabor.py new file mode 100644 index 00000000..7eb05b90 --- /dev/null +++ b/Image_Processing/src/Filters/src/gabor filter/gabor.py @@ -0,0 +1,77 @@ +# Metody biometryczne +# Przemyslaw Pastuszka + +from PIL import Image, ImageDraw +import utils +import argparse +import math +import frequency +import os + +def gabor_kernel(W, angle, freq): + cos = math.cos(angle) + sin = math.sin(angle) + + yangle = lambda x, y: x * cos + y * sin + xangle = lambda x, y: -x * sin + y * cos + + xsigma = ysigma = 4 + + return utils.kernel_from_function(W, lambda x, y: + math.exp(-( + (xangle(x, y) ** 2) / (xsigma ** 2) + + (yangle(x, y) ** 2) / (ysigma ** 2)) / 2) * + math.cos(2 * math.pi * freq * xangle(x, y))) + +def gabor(im, W, angles): + (x, y) = im.size + im_load = im.load() + + freqs = frequency.freq(im, W, angles) + print ("computing local ridge frequency done") + + gauss = utils.gauss_kernel(3) + utils.apply_kernel(freqs, gauss) + + for i in range(1, x / W - 1): + for j in range(1, y / W - 1): + kernel = gabor_kernel(W, angles[i][j], freqs[i][j]) + for k in range(0, W): + for l in range(0, W): + im_load[i * W + k, j * W + l] = utils.apply_kernel_at( + lambda x, y: im_load[x, y], + kernel, + i * W + k, + j * W + l) + + return im + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Gabor filter applied") + parser.add_argument("-t","--image", nargs=1, help = "Path to image") + parser.add_argument("-l","--block_size", nargs=1, help = "Block size") + parser.add_argument("--save", action='store_true', help = "Save result image as src_image_enhanced.gif") + args = parser.parse_args() + + im = Image.open(args.image[0]) + im = im.convert("L") # covert to grayscale + im.show() + + W = int(args.block_size[0]) + + f = lambda x, y: 2 * x * y + g = lambda x, y: x ** 2 - y ** 2 + + angles = utils.calculate_angles(im, W, f, g) + print(angles) + print ("calculating orientation done") + + angles = utils.smooth_angles(angles) + print("smoothing angles done") + + result = gabor(im, W, angles) + result.show() + + if args.save: + base_image_name = os.path.splitext(os.path.basename(args.image[0]))[0] + im.save(base_image_name + "_enhanced.gif", "GIF") diff --git a/Image_Processing/src/Filters/src/gabor filter/gabor_enhancement.py b/Image_Processing/src/Filters/src/gabor filter/gabor_enhancement.py new file mode 100644 index 00000000..888e9479 --- /dev/null +++ b/Image_Processing/src/Filters/src/gabor filter/gabor_enhancement.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +""" +Created on Mon Apr 18 11:42:58 2016 + +@author: utkarsh +""" + +import numpy as np +#import cv2 +#import numpy as np; +import matplotlib.pylab as plt; +import scipy.ndimage +import sys +import cv2 + +from image_enhance import image_enhance + + +if(len(sys.argv)<2): + print('loading sample image'); + img_name = '01.jpg' + img = scipy.ndimage.imread('images/' + img_name); + +elif(len(sys.argv) >= 2): + img_name = sys.argv[1]; + img = scipy.ndimage.imread(sys.argv[1]); + +if(len(img.shape)>2): + # img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) + img = np.dot(img[...,:3], [0.299, 0.587, 0.114]); + + +print(img.shape) + +rows,cols = np.shape(img); +aspect_ratio = np.double(rows)/np.double(cols); + +new_rows = 350; # randomly selected number +new_cols = new_rows/aspect_ratio; + +#img = cv2.resize(img,(new_rows,new_cols)); +img = scipy.misc.imresize(img,(np.int(new_rows),np.int(new_cols))); + +enhanced_img = image_enhance(img); +enhanced_img = 255*np.uint8(enhanced_img) +kernel = np.ones((5,5),np.uint8) +# closing = cv2.morphologyEx(enhanced_img, cv2.MORPH_OPEN, kernel) +erosion = cv2.erode(enhanced_img,kernel,iterations = 1) + +cv2.imshow('output',enhanced_img) +cv2.waitKey(0) +cv2.imshow('outclosed',erosion) +cv2.waitKey(0) + + +if(1): + print('saving the image') + scipy.misc.imsave('../enhanced/' + img_name, enhanced_img) +else: + plt.imshow(enhanced_img,cmap = 'Greys_r'); diff --git a/Image_Processing/src/Filters/src/gabor filter/image_enhance.py b/Image_Processing/src/Filters/src/gabor filter/image_enhance.py new file mode 100644 index 00000000..6b466724 --- /dev/null +++ b/Image_Processing/src/Filters/src/gabor filter/image_enhance.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +""" +Created on Mon Apr 18 22:50:30 2016 + +@author: utkarsh +""" +from ridge_segment import ridge_segment +from ridge_orient import ridge_orient +from ridge_freq import ridge_freq +from ridge_filter import ridge_filter +import cv2 +import numpy as np +import scipy.ndimage + +def image_enhance(img): + blksze = 40; + thresh=0.1 + normim,mask = ridge_segment(img,blksze,thresh); # normalise the image and find a ROI + temp=normim -normim.min() + temp =temp/temp.max() + cv2.imshow("normim",normim) + cv2.waitKey(0) + + gradientsigma = 1; + blocksigma = 9; + orientsmoothsigma = 7; + orientim = ridge_orient(normim, gradientsigma, blocksigma, orientsmoothsigma); # find orientation of every pixel + cv2.imshow("orientim",orientim) + cv2.waitKey(0) + + blksze = 50; + windsze = 5; + minWaveLength = 5; + maxWaveLength = 15; + freq,medfreq = ridge_freq(normim, mask, orientim, blksze, windsze, minWaveLength,maxWaveLength); #find the overall frequency of ridges + + + freq = medfreq*mask; + kx = 0.65;ky = 0.65; + newim = ridge_filter(normim, orientim, freq, kx, ky); # create gabor filter and do the actual filtering + temp=newim-newim.min(); + temp = temp/temp.max() + cv2.imshow('output',newim) + cv2.waitKey(0) + + + #gray = cv2.cvtColor(newim, cv2.COLOR_BGR2GRAY) + + th, bin_im = cv2.threshold(np.uint8(newim),0,255,cv2.THRESH_BINARY); + cv2.imshow('out',bin_im) + cv2.waitKey(0) + # kernel = np.ones((5,5),np.uint8) + # closing = cv2.morphologyEx(bin_im, cv2.MORPH_CLOSE, kernel) + # cv2.imshow('outclosed',closing) + # cv2.waitKey(0) + th3 = cv2.adaptiveThreshold((bin_im).astype('uint8'),255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,11,2) + + cv2.imshow('out',th3) + kernel = np.ones((5,5),np.uint8) + closing = cv2.morphologyEx(bin_im, cv2.MORPH_OPEN, kernel) + cv2.imshow('outclosed',closing) + cv2.waitKey(0) + + cv2.waitKey(0) + return(newim0); + + ind = np.array(ind); + ind = ind[1,:]; + + # Round the array of frequencies to the nearest 0.01 to reduce the + # number of distinct frequencies we have to deal with. + + non_zero_elems_in_freq = freq_1d[0][ind]; + non_zero_elems_in_freq = np.double(np.round((non_zero_elems_in_freq*100)))/100; + + unfreq = np.unique(non_zero_elems_in_freq); + + # Generate filters corresponding to these distinct frequencies and + # orientations in 'angleInc' increments. + + sigmax = 1/unfreq[0]*kx; + sigmay = 1/unfreq[0]*ky; + + sze = np.round(3*np.max([sigmax,sigmay])); + + x,y = np.meshgrid(np.linspace(-sze,sze,(2*sze + 1)),np.linspace(-sze,sze,(2*sze + 1))); + + 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 + + filt_rows, filt_cols = reffilter.shape; + + gabor_filter = np.array(np.zeros((int(180/angleInc), (filt_rows), (filt_cols)), dtype = int)) + + angle_for_iter = (0,180/angleInc) + start_angle, last_angle = angle_for_iter + start_angle = int(start_angle) + last_angle = int(last_angle) + print(last_angle) + for o in range(start_angle,last_angle): + + # Generate rotated versions of the filter. Note orientation + # image provides orientation *along* the ridges, hence +90 + # degrees, and imrotate requires angles +ve anticlockwise, hence + # the minus sign. + rot_filt = scipy.ndimage.rotate(reffilter,-(o*angleInc + 90),reshape = False); + gabor_filter[o] = rot_filt; + + # Find indices of matrix points greater than maxsze from the image + # boundary + + maxsze = int(sze); + + temp = freq>0; + validr,validc = np.where(temp) + + temp1 = validr>maxsze; + temp2 = validrmaxsze; + temp4 = validc maxorientindex): + orientindex[i][j] = orientindex[i][j] - maxorientindex; + finalind_rows,finalind_cols = np.shape(finalind); + sze = int(sze); + for k in range(0,finalind_cols): + r = validr[finalind[0][k]]; + c = validc[finalind[0][k]]; + + img_block = im[r-sze:r+sze + 1][:,c-sze:c+sze + 1]; + + newim[r][c] = np.sum(img_block * gabor_filter[int(orientindex[r][c]) - 1]); + + return(newim); \ No newline at end of file diff --git a/Image_Processing/src/Filters/src/gabor filter/ridge_freq.py b/Image_Processing/src/Filters/src/gabor filter/ridge_freq.py new file mode 100644 index 00000000..4a6db982 --- /dev/null +++ b/Image_Processing/src/Filters/src/gabor filter/ridge_freq.py @@ -0,0 +1,89 @@ +# -*- coding: utf-8 -*- +""" +Created on Tue Apr 19 12:14:49 2016 + +@author: utkarsh +""" + + +# RIDGEFREQ - Calculates a ridge frequency image +# +# Function to estimate the fingerprint ridge frequency across a +# fingerprint image. This is done by considering blocks of the image and +# determining a ridgecount within each block by a call to FREQEST. +# +# Usage: +# [freqim, medianfreq] = ridgefreq(im, mask, orientim, blksze, windsze, ... +# minWaveLength, maxWaveLength) +# +# Arguments: +# im - Image to be processed. +# mask - Mask defining ridge regions (obtained from RIDGESEGMENT) +# orientim - Ridge orientation image (obtained from RIDGORIENT) +# blksze - Size of image block to use (say 32) +# windsze - Window length used to identify peaks. This should be +# an odd integer, say 3 or 5. +# minWaveLength, maxWaveLength - Minimum and maximum ridge +# wavelengths, in pixels, considered acceptable. +# +# Returns: +# freqim - An image the same size as im with values set to +# the estimated ridge spatial frequency within each +# image block. If a ridge frequency cannot be +# found within a block, or cannot be found within the +# limits set by min and max Wavlength freqim is set +# to zeros within that block. +# medianfreq - Median frequency value evaluated over all the +# valid regions of the image. +# +# Suggested parameters for a 500dpi fingerprint image +# [freqim, medianfreq] = ridgefreq(im,orientim, 32, 5, 5, 15); +# + +# See also: RIDGEORIENT, FREQEST, RIDGESEGMENT + +# Reference: +# 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), 777 789. + +### REFERENCES + +# Peter Kovesi +# School of Computer Science & Software Engineering +# The University of Western Australia +# pk at csse uwa edu au +# http://www.csse.uwa.edu.au/~pk + + + +import numpy as np +#import math +#import scipy.ndimage +from frequest import frequest + +def ridge_freq(im, mask, orient, blksze, windsze,minWaveLength, maxWaveLength): + rows,cols = im.shape; + freq = np.zeros((rows,cols)); + + for r in range(0,rows-blksze,blksze): + for c in range(0,cols-blksze,blksze): + blkim = im[r:r+blksze][:,c:c+blksze]; + blkor = orient[r:r+blksze][:,c:c+blksze]; + + + freq[r:r+blksze][:,c:c+blksze] = frequest(blkim,blkor,windsze,minWaveLength,maxWaveLength); + + freq = freq*mask; + freq_1d = np.reshape(freq,(1,rows*cols)); + ind = np.where(freq_1d>0); + + ind = np.array(ind); + ind = ind[1,:]; + + non_zero_elems_in_freq = freq_1d[0][ind]; + + meanfreq = np.mean(non_zero_elems_in_freq); + medianfreq = np.median(non_zero_elems_in_freq); # does not work properly + print(meanfreq) + return(freq,0.1681) \ No newline at end of file diff --git a/Image_Processing/src/Filters/src/gabor filter/ridge_orient.py b/Image_Processing/src/Filters/src/gabor filter/ridge_orient.py new file mode 100644 index 00000000..d05b6559 --- /dev/null +++ b/Image_Processing/src/Filters/src/gabor filter/ridge_orient.py @@ -0,0 +1,112 @@ +# -*- coding: utf-8 -*- +""" +Created on Tue Apr 19 11:31:54 2016 + +@author: utkarsh +""" + + + +# RIDGEORIENT - Estimates the local orientation of ridges in a fingerprint +# +# Usage: [orientim, reliability, coherence] = ridgeorientation(im, gradientsigma,... +# blocksigma, ... +# orientsmoothsigma) +# +# Arguments: im - A normalised input image. +# gradientsigma - Sigma of the derivative of Gaussian +# used to compute image gradients. +# blocksigma - Sigma of the Gaussian weighting used to +# sum the gradient moments. +# orientsmoothsigma - Sigma of the Gaussian used to smooth +# the final orientation vector field. +# Optional: if ommitted it defaults to 0 +# +# Returns: orientim - The orientation image in radians. +# Orientation values are +ve clockwise +# and give the direction *along* the +# ridges. +# reliability - Measure of the reliability of the +# orientation measure. This is a value +# between 0 and 1. I think a value above +# about 0.5 can be considered 'reliable'. +# reliability = 1 - Imin./(Imax+.001); +# coherence - A measure of the degree to which the local +# area is oriented. +# coherence = ((Imax-Imin)./(Imax+Imin)).^2; +# +# With a fingerprint image at a 'standard' resolution of 500dpi suggested +# parameter values might be: +# +# [orientim, reliability] = ridgeorient(im, 1, 3, 3); +# +# See also: RIDGESEGMENT, RIDGEFREQ, RIDGEFILTER + +### REFERENCES + +# May 2003 Original version by Raymond Thai, +# January 2005 Reworked by Peter Kovesi +# October 2011 Added coherence computation and orientsmoothsigma made optional +# +# School of Computer Science & Software Engineering +# The University of Western Australia +# pk at csse uwa edu au +# http://www.csse.uwa.edu.au/~pk + + +import numpy as np; +import cv2; +from scipy import ndimage; +from scipy import signal + +def ridge_orient(im, gradientsigma, blocksigma, orientsmoothsigma): + rows,cols = im.shape; + #Calculate image gradients. + sze = np.fix(6*gradientsigma); + if np.remainder(sze,2) == 0: + sze = sze+1; + + gauss = cv2.getGaussianKernel(np.int(sze),gradientsigma); + f = gauss * gauss.T; + + fy,fx = np.gradient(f); #Gradient of Gaussian + + #Gx = ndimage.convolve(np.double(im),fx); + #Gy = ndimage.convolve(np.double(im),fy); + + Gx = signal.convolve2d(im,fx,mode='same'); + Gy = signal.convolve2d(im,fy,mode='same'); + + Gxx = np.power(Gx,2); + Gyy = np.power(Gy,2); + Gxy = Gx*Gy; + + #Now smooth the covariance data to perform a weighted summation of the data. + + sze = np.fix(6*blocksigma); + + gauss = cv2.getGaussianKernel(np.int(sze),blocksigma); + f = gauss * gauss.T; + + Gxx = ndimage.convolve(Gxx,f); + Gyy = ndimage.convolve(Gyy,f); + Gxy = 2*ndimage.convolve(Gxy,f); + + # Analytic solution of principal direction + denom = np.sqrt(np.power(Gxy,2) + np.power((Gxx - Gyy),2)) + np.finfo(float).eps; + + sin2theta = Gxy/denom; # Sine and cosine of doubled angles + cos2theta = (Gxx-Gyy)/denom; + + + if orientsmoothsigma: + sze = np.fix(6*orientsmoothsigma); + if np.remainder(sze,2) == 0: + sze = sze+1; + gauss = cv2.getGaussianKernel(np.int(sze),orientsmoothsigma); + f = gauss * gauss.T; + cos2theta = ndimage.convolve(cos2theta,f); # Smoothed sine and cosine of + sin2theta = ndimage.convolve(sin2theta,f); # doubled angles + + orientim = np.pi/2 + np.arctan2(sin2theta,cos2theta)/2; + return(orientim); \ No newline at end of file diff --git a/Image_Processing/src/Filters/src/gabor filter/ridge_segment.py b/Image_Processing/src/Filters/src/gabor filter/ridge_segment.py new file mode 100644 index 00000000..603a0558 --- /dev/null +++ b/Image_Processing/src/Filters/src/gabor filter/ridge_segment.py @@ -0,0 +1,97 @@ +# -*- coding: utf-8 -*- +""" +Created on Mon Apr 18 23:04:30 2016 + +@author: utkarsh +""" + + + +# RIDGESEGMENT - Normalises fingerprint image and segments ridge region +# +# Function identifies ridge regions of a fingerprint image and returns a +# mask identifying this region. It also normalises the intesity values of +# the image so that the ridge regions have zero mean, unit standard +# deviation. +# +# This function breaks the image up into blocks of size blksze x blksze and +# evaluates the standard deviation in each region. If the standard +# deviation is above the threshold it is deemed part of the fingerprint. +# Note that the image is normalised to have zero mean, unit standard +# deviation prior to performing this process so that the threshold you +# specify is relative to a unit standard deviation. +# +# Usage: [normim, mask, maskind] = ridgesegment(im, blksze, thresh) +# +# Arguments: im - Fingerprint image to be segmented. +# blksze - Block size over which the the standard +# deviation is determined (try a value of 16). +# thresh - Threshold of standard deviation to decide if a +# block is a ridge region (Try a value 0.1 - 0.2) +# +# Returns: normim - Image where the ridge regions are renormalised to +# have zero mean, unit standard deviation. +# mask - Mask indicating ridge-like regions of the image, +# 0 for non ridge regions, 1 for ridge regions. +# maskind - Vector of indices of locations within the mask. +# +# Suggested values for a 500dpi fingerprint image: +# +# [normim, mask, maskind] = ridgesegment(im, 16, 0.1) +# +# See also: RIDGEORIENT, RIDGEFREQ, RIDGEFILTER + +### REFERENCES + +# Peter Kovesi +# School of Computer Science & Software Engineering +# The University of Western Australia +# pk at csse uwa edu au +# http://www.csse.uwa.edu.au/~pk + + +import numpy as np +import cv2 + +def normalise(img,mean,std): + normed = (img - np.mean(img))/(np.std(img)); + return(normed) + +def ridge_segment(im,blksze,thresh): + + rows,cols = im.shape; + + im = normalise(im,0,1); # normalise to get zero mean and unit standard deviation + + + new_rows = np.int(blksze * np.ceil((np.float(rows))/(np.float(blksze)))) + new_cols = np.int(blksze * np.ceil((np.float(cols))/(np.float(blksze)))) + + padded_img = np.zeros((new_rows,new_cols)); + stddevim = np.zeros((new_rows,new_cols)); + + padded_img[0:rows][:,0:cols] = im; + + for i in range(0,new_rows,blksze): + for j in range(0,new_cols,blksze): + block = padded_img[i:i+blksze][:,j:j+blksze]; + + stddevim[i:i+blksze][:,j:j+blksze] = np.std(block)*np.ones(block.shape) + + stddevim = stddevim[0:rows][:,0:cols] + + + mask = stddevim > thresh; +# print(mask) +# mask = 255*np.uint8(mask) +# cv2.imshow("l",mask) +# cv2.waitKey(0) + + mean_val = np.mean(im[mask]); + + std_val = np.std(im[mask]); + + normim = (im - mean_val)/(std_val); + + + return(normim,mask) \ No newline at end of file