# imports import numpy as np import skimage import cv2 import matplotlib.pyplot as plt from scipy.spatial import distance import scipy ############################################## ### Provided code - nothing to change here ### ############################################## """ Harris Corner Detector Usage: Call the function harris(filename) for corner detection Reference (Code adapted from): http://www.kaij.org/blog/?p=89 Kai Jiang - Harris Corner Detector in Python """ from pylab import * from scipy import signal from scipy import * import numpy as np from PIL import Image def harris(filename, min_distance = 10, threshold = 0.1): """ filename: Path of image file threshold: (optional)Threshold for corner detection min_distance : (optional)Minimum number of pixels separating corners and image boundary """ im = np.array(Image.open(filename).convert("L")) harrisim = compute_harris_response(im) filtered_coords = get_harris_points(harrisim,min_distance, threshold) plot_harris_points(im, filtered_coords) def gauss_derivative_kernels(size, sizey=None): """ returns x and y derivatives of a 2D gauss kernel array for convolutions """ size = int(size) if not sizey: sizey = size else: sizey = int(sizey) y, x = mgrid[-size:size+1, -sizey:sizey+1] #x and y derivatives of a 2D gaussian with standard dev half of size # (ignore scale factor) gx = - x * exp(-(x**2/float((0.5*size)**2)+y**2/float((0.5*sizey)**2))) gy = - y * exp(-(x**2/float((0.5*size)**2)+y**2/float((0.5*sizey)**2))) return gx,gy def gauss_kernel(size, sizey = None): """ Returns a normalized 2D gauss kernel array for convolutions """ size = int(size) if not sizey: sizey = size else: sizey = int(sizey) x, y = mgrid[-size:size+1, -sizey:sizey+1] g = exp(-(x**2/float(size)+y**2/float(sizey))) return g / g.sum() def compute_harris_response(im): """ compute the Harris corner detector response function for each pixel in the image""" #derivatives gx,gy = gauss_derivative_kernels(3) imx = signal.convolve(im,gx, mode='same') imy = signal.convolve(im,gy, mode='same') #kernel for blurring gauss = gauss_kernel(3) #compute components of the structure tensor Wxx = signal.convolve(imx*imx,gauss, mode='same') Wxy = signal.convolve(imx*imy,gauss, mode='same') Wyy = signal.convolve(imy*imy,gauss, mode='same') #determinant and trace Wdet = Wxx*Wyy - Wxy**2 Wtr = Wxx + Wyy return Wdet / Wtr def get_harris_points(harrisim, min_distance=10, threshold=0.1): """ return corners from a Harris response image min_distance is the minimum nbr of pixels separating corners and image boundary""" #find top corner candidates above a threshold corner_threshold = max(harrisim.ravel()) * threshold harrisim_t = (harrisim > corner_threshold) * 1 #get coordinates of candidates candidates = harrisim_t.nonzero() coords = [ (candidates[0][c],candidates[1][c]) for c in range(len(candidates[0]))] #...and their values candidate_values = [harrisim[c[0]][c[1]] for c in coords] #sort candidates index = argsort(candidate_values) #store allowed point locations in array allowed_locations = zeros(harrisim.shape) allowed_locations[min_distance:-min_distance,min_distance:-min_distance] = 1 #select the best points taking min_distance into account filtered_coords = [] for i in index: if allowed_locations[coords[i][0]][coords[i][1]] == 1: filtered_coords.append(coords[i]) allowed_locations[(coords[i][0]-min_distance):(coords[i][0]+min_distance), (coords[i][1]-min_distance):(coords[i][1]+min_distance)] = 0 return filtered_coords def plot_harris_points(image, filtered_coords): """ plots corners found in image""" figure() gray() imshow(image) plot([p[1] for p in filtered_coords],[p[0] for p in filtered_coords],'r*') axis('off') show() # Usage: #harris('./path/to/image.jpg') # Provided code for plotting inlier matches between two images def plot_inlier_matches(ax, img1, img2, inliers): """ Plot the matches between two images according to the matched keypoints :param ax: plot handle :param img1: left image :param img2: right image :inliers: x,y in the first image and x,y in the second image (Nx4) """ res = np.hstack([img1, img2]) ax.set_aspect('equal') ax.imshow(res, cmap='gray') ax.plot(inliers[:,0], inliers[:,1], '+r') ax.plot(inliers[:,2] + img1.shape[1], inliers[:,3], '+r') ax.plot([inliers[:,0], inliers[:,2] + img1.shape[1]], [inliers[:,1], inliers[:,3]], 'r', linewidth=0.4) ax.axis('off') # Usage: # fig, ax = plt.subplots(figsize=(20,10)) # plot_inlier_matches(ax, img1, img2, computed_inliers) ####################################### ### Your implementation starts here ### ####################################### # See assignment page for the instructions!