# 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!