Feature Matching Points
The objective of this project is to find the matches two images using local feature matching techniques. The matching process here is divided into three steps: First step is to find the corner points using Harris corner detector as they have distinctive surroundings that can be easily identified, apply. The second step is to calculate the SIFT descriptors for the interesting points. The final step is to calculate the feature differences and select point pairs according to the threshold ratio.
In this function, we first implement the Harris corner detection algorithm. First the image is filtered. Then at each pixel, y and y gradients are computed Ix and Iy. These are used to compute Ix2 Iy2 and Ixy. A thresholding operation is peformed and points having a sufficiently high cornerness score are selected.
%example code
[Gx, Gy] = gradient(fspecial('Gaussian',5,1));
Ix = imfilter(image, Gx);
Iy = imfilter(image, Gy);
Gaussian_Filter = fspecial('Gaussian', feature_width, 2);
Ixx = imfilter((Ix .* Ix), Gaussian_Filter);
Ixy = imfilter(Ix .* Iy, Gaussian_Filter);
Iyy = imfilter(Iy .* Iy, Gaussian_Filter);
alpha = 0.06;
R = (Ixx.*Iyy - Ixy.^2) - alpha*((Ixx + Iyy).^2);
R = R / max(max(R));
R=R.*(R>0.025);
B=colfilt(R,[5,5],'sliding',@max);
R = R .* (R == B);
[Y,X]=find(R);
Interest Points
After the interest points are calculated in the previous method, each points feature descriptor is computed. 4 by 4 grid in 8 directions is constructed and each bin contains magnitude of the intensity in that angle/direction. Thus we get 128 dimensions or a vector of 1 by 128.
%example code
for i = 1: size(x,1)
magnitude_mat = magnitude(y(i)-7:y(i)+8, x(i)-7:x(i)+8);
direction_mat = direction(y(i)-7:y(i)+8, x(i)-7:x(i)+8);
cur_feature = [];
for xi = 1: 4 : feature_width
for yi = 1: 4: feature_width
points_vals = zeros(1,8);
for xii = xi: xi+3
for yii = yi: yi+3
den = (pi/4);
num = (direction_mat(xii, yii) + pi);
pix = ceil(num / den);
points_vals(pix) = points_vals(pix) + magnitude_mat(xii, yii);
end
end
points_vals = points_vals / sum(points_vals);
cur_feature = [cur_feature points_vals];
end
end
features(i,:) = cur_feature;
end
The final step in the process is matching between feature points detected in the two images. This is done in my program by computing the Euclidean distance between every pair of feature points in the two images. The smallest distances means closest similarity amongst the different feature points in Image1 and Image2. For a given feature point in Image 1, the nearest neighbour and second nearest neighbour are identified by sorting the results of distances and getting the smallest two values. The ratio of these two distances is taken and values greater than particular treshold value are taken as pairs that are matching.
%example code
for i = 1 : size(features1, 1)
dists = features2;
%calculating distances between all features
for j = 1 : size(dists, 1)
dists(j, :) = (dists(j, :) - features1(i, :)).^2;
end
%sorting to help find nearest neighbor
[sorted_distances_list, index] = sort(sum(dists, 2));
%ratio of smallest and second smallest to get reliability
rel = sorted_distances_list(2) / sorted_distances_list(1);
confidence = (rel)^-1;
if confidence < threshold
matches(counter, 1) = i;
matches(counter, 2) = index(1);
confidences(counter) = confidence;
counter = counter + 1;
end
end
Arrows showing the pairs matched
The pairs that are matching according to my algorithm are compared with the ground truth. This is done to determine the accuracy of the pairs matched by the algorithm.
The accuracy obtained for Notre Dame is 84% and accuracy obtained for Mount Rushmore is 93% after varying the treshold value to 0.75 for which the best results are obtained. For different pairs of images different values of threshold give high accuracy. This may vary due to the scaling of the images. Images that differ in the rotation/orientation show lesser accuracy on experimentation