import os import glob import shutil import logging import matplotlib.pyplot as plt import numpy as np from scipy import ndimage, misc, signal, spatial from skimage.filters import gaussian import cv2 import math def mkdir(path): if not os.path.exists(path): os.makedirs(path) def re_mkdir(path): if os.path.exists(path): shutil.rmtree(path) os.makedirs(path) def init_log(output_dir): re_mkdir(output_dir) logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(message)s', datefmt='%Y%m%d-%H:%M:%S', filename=os.path.join(output_dir, 'log.log'), filemode='w') console = logging.StreamHandler() console.setLevel(logging.INFO) logging.getLogger('').addHandler(console) return logging def copy_file(path_s, path_t): shutil.copy(path_s, path_t) def get_files_in_folder(folder, file_ext=None): files = glob.glob(os.path.join(folder, "*" + file_ext)) files_name = [] for i in files: _, name = os.path.split(i) name, ext = os.path.splitext(name) files_name.append(name) return np.asarray(files), np.asarray(files_name) def point_rot(points, theta, b_size, a_size): cosA = np.cos(theta) sinA = np.sin(theta) b_center = [b_size[1]/2.0, b_size[0]/2.0] a_center = [a_size[1]/2.0, a_size[0]/2.0] points = np.dot(points-b_center, np.array([[cosA,-sinA],[sinA,cosA]]))+a_center return points def mnt_reader(file_name): f = open(file_name) minutiae = [] for i, line in enumerate(f): if i < 4 or len(line) == 0: continue w, h, o = [float(x) for x in line.split()] w, h = int(round(w)), int(round(h)) minutiae.append([w, h, o]) f.close() return minutiae def mnt_writer(mnt, image_name, image_size, file_name): f = open(file_name, 'w') f.write('%s\n'%(image_name)) f.write('%d %d %d\n'%(mnt.shape[0], image_size[0], image_size[1])) for i in xrange(mnt.shape[0]): f.write('%d %d %.6f %.4f\n'%(mnt[i,0], mnt[i,1], mnt[i,2], mnt[i,3])) f.close() return def gabor_fn(ksize, sigma, theta, Lambda, psi, gamma): sigma_x = sigma sigma_y = float(sigma) / gamma # Bounding box nstds = 3 xmax = ksize[0]/2 ymax = ksize[1]/2 xmin = -xmax ymin = -ymax (y, x) = np.meshgrid(np.arange(ymin, ymax + 1), np.arange(xmin, xmax + 1)) # Rotation x_theta = x * np.cos(theta) + y * np.sin(theta) y_theta = -x * np.sin(theta) + y * np.cos(theta) gb_cos = np.exp(-.5 * (x_theta ** 2 / sigma_x ** 2 + y_theta ** 2 / sigma_y ** 2)) * np.cos(2 * np.pi / Lambda * x_theta + psi) gb_sin = np.exp(-.5 * (x_theta ** 2 / sigma_x ** 2 + y_theta ** 2 / sigma_y ** 2)) * np.sin(2 * np.pi / Lambda * x_theta + psi) return gb_cos, gb_sin def gabor_bank(stride=2,Lambda=8): filters_cos = np.ones([25,25,180/stride], dtype=float) filters_sin = np.ones([25,25,180/stride], dtype=float) for n, i in enumerate(xrange(-90,90,stride)): theta = i*np.pi/180. kernel_cos, kernel_sin = gabor_fn((24,24),4.5, -theta, Lambda, 0, 0.5) filters_cos[..., n] = kernel_cos filters_sin[..., n] = kernel_sin filters_cos = np.reshape(filters_cos,[25,25,1,-1]) filters_sin = np.reshape(filters_sin,[25,25,1,-1]) return filters_cos, filters_sin def gaussian2d(shape=(5,5),sigma=0.5): """ 2D gaussian mask - should give the same result as MATLAB's fspecial('gaussian',[shape],[sigma]) """ m,n = [(ss-1.)/2. for ss in shape] y,x = np.ogrid[-m:m+1,-n:n+1] h = np.exp( -(x*x + y*y) / (2.*sigma*sigma) ) h[ h < np.finfo(h.dtype).eps*h.max() ] = 0 sumh = h.sum() if sumh != 0: h /= sumh return h def gausslabel(length=180, stride=2): gaussian_pdf = signal.gaussian(length+1, 3) label = np.reshape(np.arange(stride/2, length, stride), [1,1,-1,1]) y = np.reshape(np.arange(stride/2, length, stride), [1,1,1,-1]) delta = np.array(np.abs(label - y), dtype=int) delta = np.minimum(delta, length-delta)+length/2 return gaussian_pdf[delta] def angle_delta(A, B, max_D=np.pi*2): delta = np.abs(A - B) delta = np.minimum(delta, max_D-delta) return delta def fmeasure(P, R): return 2*P*R/(P+R+1e-10) def distance(y_true, y_pred, max_D=16, max_O=np.pi/6): D = spatial.distance.cdist(y_true[:, :2], y_pred[:, :2], 'euclidean') O = spatial.distance.cdist(np.reshape(y_true[:, 2], [-1, 1]), np.reshape(y_pred[:, 2], [-1, 1]), angle_delta) return (D<=max_D)*(O<=max_O) def metric_P_R_F(y_true, y_pred, maxd=16, maxo=np.pi/6): # Calculate Precision, Recall, F-score if y_pred.shape[0]==0 or y_true.shape[0]==0: return 0,0,0,0,0 y_true, y_pred = np.array(y_true), np.array(y_pred) total_gt, total = float(y_true.shape[0]), float(y_pred.shape[0]) # Using L2 loss dis = spatial.distance.cdist(y_pred[:, :2], y_true[:, :2], 'euclidean') mindis,idx = dis.min(axis=1),dis.argmin(axis=1) #Change to adapt to new annotation: old version. When training, comment it # y_pred[:,2] = -y_pred[:,2] angle = abs(np.mod(y_pred[:,2],2*np.pi) - y_true[idx,2]) angle = np.asarray([angle, 2*np.pi-angle]).min(axis=0) # Satisfy the threshold tmp=(mindis <= maxd) & (angle<=maxo) #print('mindis,idx,angle,tmp=%s,%s,%s,%s'%(mindis,idx,angle,tmp)) precision = len(np.unique(idx[(mindis <= maxd) & (angle<=maxo)]))/float(y_pred.shape[0]) recall = len(np.unique(idx[(mindis <= maxd) & (angle<=maxo)]))/float(y_true.shape[0]) #print('pre=%f/ %f'%(len(np.unique(idx[(mindis <= maxd) & (angle<=maxo)])),float(y_pred.shape[0]))) #print('recall=%f/ %f'%(len(np.unique(idx[(mindis <= maxd) & (angle<=maxo)])),float(y_true.shape[0]))) if recall!=0: loc = np.mean(mindis[(mindis <= maxd) & (angle<=maxo)]) ori = np.mean(angle[(mindis <= maxd) & (angle<=maxo)]) else: loc = 0 ori = 0 return precision, recall, fmeasure(precision, recall), loc, ori def nms(mnt): if mnt.shape[0]==0: return mnt # sort score mnt_sort = mnt.tolist() mnt_sort.sort(key=lambda x:x[3], reverse=True) mnt_sort = np.array(mnt_sort) # cal distance inrange = distance(mnt_sort, mnt_sort, max_D=16, max_O=np.pi/6).astype(np.float32) keep_list = np.ones(mnt_sort.shape[0]) for i in xrange(mnt_sort.shape[0]): if keep_list[i] == 0: continue keep_list[i+1:] = keep_list[i+1:]*(1-inrange[i, i+1:]) return mnt_sort[keep_list.astype(np.bool), :] def fuse_nms(mnt, mnt_set_2): if mnt.shape[0]==0: return mnt # sort score all_mnt = np.concatenate((mnt, mnt_set_2)) mnt_sort = all_mnt.tolist() mnt_sort.sort(key=lambda x:x[3], reverse=True) mnt_sort = np.array(mnt_sort) # cal distance inrange = distance(mnt_sort, mnt_sort, max_D=16, max_O=2*np.pi).astype(np.float32) keep_list = np.ones(mnt_sort.shape[0]) for i in xrange(mnt_sort.shape[0]): if keep_list[i] == 0: continue keep_list[i+1:] = keep_list[i+1:]*(1-inrange[i, i+1:]) return mnt_sort[keep_list.astype(np.bool), :] def py_cpu_nms(det, thresh): if det.shape[0]==0: return det dets = det.tolist() dets.sort(key=lambda x:x[3], reverse=True) dets = np.array(dets) box_sz = 25 x1 = np.reshape(dets[:,0],[-1,1]) -box_sz y1 = np.reshape(dets[:,1],[-1,1]) -box_sz x2 = np.reshape(dets[:,0],[-1,1]) +box_sz y2 = np.reshape(dets[:,1],[-1,1]) +box_sz scores = dets[:, 2] areas = (x2 - x1 + 1) * (y2 - y1 + 1) order = scores.argsort()[::-1] keep = [] while order.size > 0: i = order[0] keep.append(i) xx1 = np.maximum(x1[i], x1[order[1:]]) yy1 = np.maximum(y1[i], y1[order[1:]]) xx2 = np.minimum(x2[i], x2[order[1:]]) yy2 = np.minimum(y2[i], y2[order[1:]]) w = np.maximum(0.0, xx2 - xx1 + 1) h = np.maximum(0.0, yy2 - yy1 + 1) inter = w * h ovr = inter / (areas[i] + areas[order[1:]] - inter) inds = np.where(ovr <= thresh)[0] order = order[inds + 1] return dets[keep, :] def draw_minutiae(image, minutiae, fname, saveimage= False, r=15, drawScore=False): image = np.squeeze(image) fig = plt.figure() plt.imshow(image,cmap='gray') plt.hold(True) # Check if no minutiae if minutiae.shape[0] > 0: plt.plot(minutiae[:, 0], minutiae[:, 1], 'rs', fillstyle='none', linewidth=1) for x, y, o, s in minutiae: plt.plot([x, x+r*np.cos(o)], [y, y+r*np.sin(o)], 'r-') if drawScore == True: plt.text(x - 10, y - 10, '%.2f' % s, color='yellow', fontsize=4) plt.axis([0,image.shape[1],image.shape[0],0]) plt.axis('off') if saveimage: plt.savefig(fname, dpi=500, bbox_inches='tight', pad_inches = 0) plt.close(fig) else: plt.show() return def draw_minutiae_overlay(image, minutiae, mnt_gt, fname, saveimage= False, r=15, drawScore=False): image = np.squeeze(image) fig = plt.figure() plt.imshow(image,cmap='gray') plt.hold(True) if mnt_gt.shape[1] > 3: mnt_gt = mnt_gt[:,:3] if mnt_gt.shape[0] > 0: if mnt_gt.shape[1] > 3: mnt_gt = mnt_gt[:, :3] plt.plot(mnt_gt[:, 0], mnt_gt[:, 1], 'bs', fillstyle='none', linewidth=1) for x, y, o in mnt_gt: plt.plot([x, x+r*np.cos(o)], [y, y+r*np.sin(o)], 'b-') if minutiae.shape[0] > 0: plt.plot(minutiae[:, 0], minutiae[:, 1], 'rs', fillstyle='none', linewidth=1) for x, y, o in minutiae: plt.plot([x, x+r*np.cos(o)], [y, y+r*np.sin(o)], 'r-') if drawScore == True: plt.text(x - 10, y - 10, '%.2f' % s, color='yellow', fontsize=4) plt.axis([0,image.shape[1],image.shape[0],0]) plt.axis('off') plt.show() if saveimage: plt.savefig(fname, dpi=500, bbox_inches='tight') plt.close(fig) else: plt.show() return def draw_minutiae_overlay_with_score(image, minutiae, mnt_gt, fname, saveimage=False, r=15): image = np.squeeze(image) fig = plt.figure() plt.imshow(image, cmap='gray') plt.hold(True) if mnt_gt.shape[0] > 0: plt.plot(mnt_gt[:, 0], mnt_gt[:, 1], 'bs', fillstyle='none', linewidth=1) if mnt_gt.shape[1] > 3: for x, y, o, s in mnt_gt: plt.plot([x, x + r * np.cos(o)], [y, y + r * np.sin(o)], 'b-') plt.text(x - 10, y - 5, '%.2f' % s, color='green', fontsize=4) else: for x, y, o in mnt_gt: plt.plot([x, x + r * np.cos(o)], [y, y + r * np.sin(o)], 'b-') if minutiae.shape[0] > 0: plt.plot(minutiae[:, 0], minutiae[:, 1], 'rs', fillstyle='none', linewidth=1) for x, y, o, s in minutiae: plt.plot([x, x + r * np.cos(o)], [y, y + r * np.sin(o)], 'r-') plt.text(x-10,y-10,'%.2f'%s,color='yellow',fontsize=4) plt.axis([0, image.shape[1], image.shape[0], 0]) plt.axis('off') if saveimage: plt.savefig(fname, dpi=500, bbox_inches='tight') plt.close(fig) else: plt.show() return def draw_ori_on_img(img, ori, mask, fname, saveimage=False, coh=None, stride=16): ori = np.squeeze(ori) #mask = np.squeeze(np.round(mask)) img = np.squeeze(img) ori = ndimage.zoom(ori, np.array(img.shape)/np.array(ori.shape, dtype=float), order=0) if mask.shape != img.shape: mask = ndimage.zoom(mask, np.array(img.shape)/np.array(mask.shape, dtype=float), order=0) if coh is None: coh = np.ones_like(img) fig = plt.figure() plt.imshow(img,cmap='gray') plt.hold(True) for i in xrange(stride,img.shape[0],stride): for j in xrange(stride,img.shape[1],stride): if mask[i, j] == 0: continue x, y, o, r = j, i, ori[i,j], coh[i,j]*(stride*0.9) plt.plot([x, x+r*np.cos(o)], [y, y+r*np.sin(o)], 'r-') plt.axis([0,img.shape[1],img.shape[0],0]) plt.axis('off') if saveimage: plt.savefig(fname, bbox_inches='tight') plt.close(fig) else: plt.show() return def local_constrast_enhancement(img): img = img.astype(np.float32) meanV = cv2.blur(img,(15,15)) normalized = img - meanV var = abs(normalized) var = cv2.blur(var,(15,15)) normalized = normalized/(var+10) *0.75 normalized = np.clip(normalized, -1, 1) normalized = (normalized+1)*127.5 return normalized def get_quality_map_ori_dict(img, dict, spacing, dir_map = None, block_size = 16): if img.dtype=='uint8': img = img.astype(np.float) img = FastEnhanceTexture(img) h, w = img.shape blkH, blkW = dir_map.shape quality_map = np.zeros((blkH,blkW),dtype=np.float) fre_map = np.zeros((blkH,blkW),dtype=np.float) ori_num = len(dict) #dir_map = math.pi/2 - dir_map dir_ind = dir_map*ori_num/math.pi dir_ind = dir_ind.astype(np.int) dir_ind = dir_ind%ori_num patch_size = np.sqrt(dict[0].shape[1]) patch_size = patch_size.astype(np.int) pad_size = (patch_size-block_size)//2 img = np.lib.pad(img, (pad_size, pad_size), 'symmetric') for i in range(0,blkH): for j in range(0,blkW): ind = dir_ind[i,j] patch = img[i*block_size:i*block_size+patch_size,j*block_size:j*block_size+patch_size] patch = patch.reshape(patch_size*patch_size,) patch = patch - np.mean(patch) patch = patch / (np.linalg.norm(patch)+0.0001) patch[patch>0.05] = 0.05 patch[patch<-0.05] = -0.05 simi = np.dot(dict[ind], patch) similar_ind = np.argmax(abs(simi)) quality_map[i,j] = np.max(abs(simi)) fre_map[i,j] = 1./spacing[ind][similar_ind] quality_map = gaussian(quality_map,sigma=2) return quality_map, fre_map def FastEnhanceTexture(img,sigma=2.5,show=False): img = img.astype(np.float32) h, w = img.shape h2 = 2 ** nextpow2(h) w2 = 2 ** nextpow2(w) FFTsize = np.max([h2, w2]) x, y = np.meshgrid(range(-FFTsize / 2, FFTsize / 2), range(-FFTsize / 2, FFTsize / 2)) r = np.sqrt(x * x + y * y) + 0.0001 r = r/FFTsize L = 1. / (1 + (2 * math.pi * r * sigma)** 4) img_low = LowpassFiltering(img, L) gradim1= compute_gradient_norm(img) gradim1 = LowpassFiltering(gradim1,L) gradim2= compute_gradient_norm(img_low) gradim2 = LowpassFiltering(gradim2,L) diff = gradim1-gradim2 ar1 = np.abs(gradim1) diff[ar1>1] = diff[ar1>1]/ar1[ar1>1] diff[ar1 <= 1] = 0 cmin = 0.3 cmax = 0.7 weight = (diff-cmin)/(cmax-cmin) weight[diffcmax] = 1 u = weight * img_low + (1-weight)* img temp = img - u lim = 20 temp1 = (temp + lim) * 255 / (2 * lim) temp1[temp1 < 0] = 0 temp1[temp1 >255] = 255 v = temp1 if show: plt.imshow(v,cmap='gray') plt.show() return v def compute_gradient_norm(input): input = input.astype(np.float32) Gx, Gy = np.gradient(input) out = np.sqrt(Gx * Gx + Gy * Gy) + 0.000001 return out def LowpassFiltering(img,L): h,w = img.shape h2,w2 = L.shape img = cv2.copyMakeBorder(img, 0, h2-h, 0, w2-w, cv2.BORDER_CONSTANT, value=0) img_fft = np.fft.fft2(img) img_fft = np.fft.fftshift(img_fft) img_fft = img_fft * L rec_img = np.fft.ifft2(np.fft.fftshift(img_fft)) rec_img = np.real(rec_img) rec_img = rec_img[:h,:w] return rec_img def nextpow2(x): return int(math.ceil(math.log(x, 2))) def construct_dictionary(ori_num = 30): ori_dict = [] s = [] for i in range(ori_num): ori_dict.append([]) s.append([]) patch_size2 = 16 patch_size = 32 dict_all = [] spacing_all = [] ori_all = [] Y, X = np.meshgrid(range(-patch_size2,patch_size2), range(-patch_size2,patch_size2)) for spacing in range(6,13): for valley_spacing in range(3,spacing//2): ridge_spacing = spacing - valley_spacing for k in range(ori_num): theta = np.pi/2-k*np.pi / ori_num X_r = X * np.cos(theta) - Y * np.sin(theta) for offset in range(0,spacing-1,2): X_r_offset = X_r + offset + ridge_spacing / 2 X_r_offset = np.remainder(X_r_offset, spacing) Y1 = np.zeros((patch_size, patch_size)) Y2 = np.zeros((patch_size, patch_size)) Y1[X_r_offset <= ridge_spacing] = X_r_offset[X_r_offset <= ridge_spacing] Y2[X_r_offset > ridge_spacing] = X_r_offset[X_r_offset > ridge_spacing] - ridge_spacing element = -np.sin(2 * math.pi * (Y1 / ridge_spacing / 2)) + np.sin(2 * math.pi * (Y2 / valley_spacing / 2)) element = element.reshape(patch_size*patch_size,) element = element-np.mean(element) element = element/ np.linalg.norm(element) ori_dict[k].append(element) s[k].append(spacing) dict_all.append(element) spacing_all.append(1.0/spacing) ori_all.append(theta) for i in range(len(ori_dict)): ori_dict[i] = np.asarray(ori_dict[i]) s[k] = np.asarray(s[k]) dict_all = np.asarray(dict_all) dict_all = np.transpose(dict_all) spacing_all = np.asarray(spacing_all) ori_all = np.asarray(ori_all) return ori_dict, s, dict_all, ori_all,spacing_all def get_maps_STFT(img,patch_size = 64,block_size = 16, preprocess = False): assert len(img.shape) == 2 nrof_dirs = 16 ovp_size = (patch_size-block_size)//2 if preprocess: img = FastEnhanceTexture(img, sigma=2.5, show=False) img = np.lib.pad(img, (ovp_size,ovp_size),'symmetric') h,w = img.shape blkH = (h - patch_size)//block_size+1 blkW = (w - patch_size)//block_size+1 local_info = np.empty((blkH,blkW),dtype = object) x, y = np.meshgrid(range(-patch_size / 2,patch_size / 2), range(-patch_size / 2,patch_size / 2)) x = x.astype(np.float32) y = y.astype(np.float32) r = np.sqrt(x*x + y*y) + 0.0001 RMIN = 3 # min allowable ridge spacing RMAX = 200 # maximum allowable ridge spacing FLOW = patch_size / RMAX FHIGH = patch_size / RMIN dRLow = 1. / (1 + (r / FHIGH) ** 4) dRHigh = 1. / (1 + (FLOW / r) ** 4) dBPass = dRLow * dRHigh # bandpass dir = np.arctan2(y,x) dir[dir<0] = dir[dir<0] + math.pi dir_ind = np.floor(dir/(math.pi/nrof_dirs)) dir_ind = dir_ind.astype(np.int,copy=False) dir_ind[dir_ind==nrof_dirs] = 0 dir_ind_list = [] for i in range(nrof_dirs): tmp = np.argwhere(dir_ind == i) dir_ind_list.append(tmp) sigma = patch_size/3 weight = np.exp(-(x*x + y*y)/(sigma*sigma)) for i in range(0,blkH): for j in range(0,blkW): patch =img[i*block_size:i*block_size+patch_size,j*block_size:j*block_size+patch_size].copy() local_info[i,j] = local_STFT(patch,weight,dBPass) local_info[i, j].analysis(r,dir_ind_list) # get the ridge flow from the local information dir_map,fre_map = get_ridge_flow_top(local_info) dir_map = smooth_dir_map(dir_map) return dir_map, fre_map def smooth_dir_map(dir_map,sigma=2.0,mask = None): cos2Theta = np.cos(dir_map * 2) sin2Theta = np.sin(dir_map * 2) if mask is not None: assert (dir_map.shape[0] == mask.shape[0]) assert (dir_map.shape[1] == mask.shape[1]) cos2Theta[mask == 0] = 0 sin2Theta[mask == 0] = 0 cos2Theta = gaussian(cos2Theta, sigma, multichannel=False, mode='reflect') sin2Theta = gaussian(sin2Theta, sigma, multichannel=False, mode='reflect') dir_map = np.arctan2(sin2Theta,cos2Theta)*0.5 return dir_map def get_ridge_flow_top(local_info): blkH,blkW = local_info.shape dir_map = np.zeros((blkH,blkW)) - 10 fre_map = np.zeros((blkH, blkW)) - 10 for i in range(blkH): for j in range(blkW): if local_info[i,j].ori is None: continue dir_map[i,j] = local_info[i,j].ori[0] #+ math.pi*0.5 fre_map[i,j] = local_info[i,j].fre[0] return dir_map,fre_map class local_STFT: def __init__(self,patch,weight = None, dBPass = None): if weight is not None: patch = patch * weight patch = patch - np.mean(patch) norm = np.linalg.norm(patch) patch = patch / (norm+0.000001) f = np.fft.fft2(patch) fshift = np.fft.fftshift(f) if dBPass is not None: fshift = dBPass * fshift self.patch_FFT = fshift self.patch = patch self.ori = None self.fre = None self.confidence = None self.patch_size = patch.shape[0] def analysis(self,r,dir_ind_list=None,N=2): assert(dir_ind_list is not None) energy = np.abs(self.patch_FFT) energy = energy / (np.sum(energy)+0.00001) nrof_dirs = len(dir_ind_list) ori_interval = math.pi/nrof_dirs ori_interval2 = ori_interval/2 pad_size = 1 dir_norm = np.zeros((nrof_dirs + 2,)) for i in range(nrof_dirs): tmp = energy[dir_ind_list[i][:, 0], dir_ind_list[i][:, 1]] dir_norm[i + 1] = np.sum(tmp) dir_norm[0] = dir_norm[nrof_dirs] dir_norm[nrof_dirs + 1] = dir_norm[1] # smooth dir_norm smoothed_dir_norm = dir_norm for i in range(1, nrof_dirs + 1): smoothed_dir_norm[i] = (dir_norm[i - 1] + dir_norm[i] * 4 + dir_norm[i + 1]) / 6 smoothed_dir_norm[0] = smoothed_dir_norm[nrof_dirs] smoothed_dir_norm[nrof_dirs + 1] = smoothed_dir_norm[1] den = np.sum(smoothed_dir_norm[1:nrof_dirs + 1]) + 0.00001 # verify if den == 1 smoothed_dir_norm = smoothed_dir_norm/den # normalization if den == 1, this line can be removed ori = [] fre = [] confidence = [] wenergy = energy*r for i in range(1, nrof_dirs+1): if smoothed_dir_norm[i] > smoothed_dir_norm[i-1] and smoothed_dir_norm[i] > smoothed_dir_norm[i+1]: tmp_ori = (i-pad_size)*ori_interval + ori_interval2 + math.pi/2 ori.append(tmp_ori) confidence.append(smoothed_dir_norm[i]) tmp_fre = np.sum(wenergy[dir_ind_list[i-pad_size][:, 0], dir_ind_list[i-pad_size][:, 1]])/dir_norm[i] tmp_fre = 1/(tmp_fre+0.00001) fre.append(tmp_fre) if len(confidence)>0: confidence = np.asarray(confidence) fre = np.asarray(fre) ori = np.asarray(ori) ind = confidence.argsort()[::-1] confidence = confidence[ind] fre = fre[ind] ori = ori[ind] if len(confidence) >= 2 and confidence[0]/confidence[1]>2.0: self.ori = [ori[0]] self.fre = [fre[0]] self.confidence = [confidence[0]] elif len(confidence)>N: fre = fre[:N] ori = ori[:N] confidence = confidence[:N] self.ori = ori self.fre = fre self.confidence = confidence else: self.ori = ori self.fre = fre self.confidence = confidence def get_features_of_topN(self,N=2): if self.confidence is None: self.border_wave = None return candi_num = len(self.ori) candi_num = np.min([candi_num,N]) patch_size = self.patch_FFT.shape for i in range(candi_num): kernel = gabor_kernel(self.fre[i], theta=self.ori[i], sigma_x=10, sigma_y=10) kernel_f = np.fft.fft2(kernel.real, patch_size) kernel_f = np.fft.fftshift(kernel_f) patch_f = self.patch_FFT * kernel_f patch_f = np.fft.ifftshift(patch_f) # *np.sqrt(np.abs(fshift))) rec_patch = np.real(np.fft.ifft2(patch_f)) plt.subplot(121), plt.imshow(self.patch, cmap='gray') plt.title('Input patch'), plt.xticks([]), plt.yticks([]) plt.subplot(122), plt.imshow(rec_patch, cmap='gray') plt.title('filtered patch'), plt.xticks([]), plt.yticks([]) plt.show() def reconstruction(self,weight=None): f_ifft = np.fft.ifftshift(self.patch_FFT) # *np.sqrt(np.abs(fshift))) rec_patch = np.real(np.fft.ifft2(f_ifft)) if weight is not None: rec_patch = rec_patch * weight return rec_patch def gabor_filtering(self,theta,fre,weight=None): patch_size = self.patch_FFT.shape kernel = gabor_kernel(fre, theta=theta,sigma_x=4,sigma_y=4) f = kernel.real f = f - np.mean(f) f = f / (np.linalg.norm(f)+0.0001) kernel_f = np.fft.fft2(f,patch_size) kernel_f = np.fft.fftshift(kernel_f) patch_f = self.patch_FFT*kernel_f patch_f = np.fft.ifftshift(patch_f) # *np.sqrt(np.abs(fshift))) rec_patch = np.real(np.fft.ifft2(patch_f)) if weight is not None: rec_patch = rec_patch * weight return rec_patch def show_orientation_field(img,dir_map,mask=None,fname=None): h,w = img.shape[:2] if mask is None: mask = np.ones((h,w),dtype=np.uint8) blkH, blkW = dir_map.shape blk_size = h/blkH R = blk_size/2 fig, ax = plt.subplots(1) ax.imshow(img, cmap='gray') for i in range(blkH): y0 = i*blk_size + blk_size/2 y0 = int(y0) for j in range(blkW): x0 = j*blk_size + blk_size/2 x0 = int(x0) ori = dir_map[i,j] if mask[y0,x0] == 0: continue if ori<-9: continue x1 = x0 - R * math.cos(ori) x2 = x0 + R * math.cos(ori) y1 = y0 - R * math.sin(ori) y2 = y0 + R * math.sin(ori) plt.plot([x1, x2], [y1, y2], 'r-', lw=1) plt.axis('off') if fname is not None: fig.savefig(fname,dpi = 500, bbox_inches='tight', pad_inches = 0) plt.close() else: plt.show(block=True)