make a canny edge detection function from scratch and use it to calculate homography in matlab

Here is an implementation of canny edge detection from scratch using MATLAB:

main.m
function edgeImg = myCannyDetector(img, sigma, thLow, thHigh)

    % Compute Gaussian filter
    filterSize = 2*ceil(3*sigma)+1;
    gaussFilter = fspecial('gaussian', filterSize, sigma);
    
    % Apply Gaussian filter
    imgFiltered = imfilter(img, gaussFilter, 'replicate');
    
    % Compute gradients using Sobel operators
    filterSobelX = [1 0 -1; 2 0 -2; 1 0 -1];
    filterSobelY = [1 2 1; 0 0 0; -1 -2 -1];
    imgSobelX = imfilter(imgFiltered, filterSobelX, 'replicate');
    imgSobelY = imfilter(imgFiltered, filterSobelY, 'replicate');
    gradMag = sqrt(imgSobelX.^2 + imgSobelY.^2);
    gradDir = atan2(imgSobelY, imgSobelX) * 180/pi;
    
    % Compute non-maximum suppression
    [h, w] = size(img);
    edgeImg = zeros(h, w);
    for i = 2:h-1
        for j = 2:w-1
            theta = gradDir(i, j);
            if (theta < 0)
                theta = theta + 180;
            end
            if ((theta >= 0   && theta < 22.5 ) || ...
                (theta >= 157.5 && theta <= 180) || ...
                (theta >= 67.5  && theta < 112.5))
                % Check left and right neighbors
                if (gradMag(i, j) > gradMag(i, j-1) && ...
                    gradMag(i, j) > gradMag(i, j+1))
                    edgeImg(i, j) = gradMag(i, j);
                end
            elseif ((theta >= 22.5 && theta < 67.5) || ...
                    (theta >= 112.5 && theta < 157.5))
                % Check top left-right and bottom left-right neighbors
                if (gradMag(i, j) > gradMag(i-1, j-1) && ...
                    gradMag(i, j) > gradMag(i+1, j+1)) || ...
                   (gradMag(i, j) > gradMag(i-1, j+1) && ...
                    gradMag(i, j) > gradMag(i+1, j-1))
                    edgeImg(i, j) = gradMag(i, j);
                end
            end
        end
    end
    
    % Apply hysteresis thresholding
    thLow = thLow * max(max(edgeImg));
    thHigh = thHigh * max(max(edgeImg));
    thresImg = zeros(size(edgeImg));
    thresImg(edgeImg >= thHigh) = 1;
    thresImg = bwmorph(thresImg, 'bridge');
    while (1)
        oldThresImg = thresImg;
        weakEdges = edgeImg >= thLow & ~thresImg;
        if any(weakEdges(:))
            [r, c] = find(weakEdges);
            for i = 1:numel(r)
                if any(thresImg(max(1, r(i)-1):min(end, r(i)+1), ...
                                 max(1, c(i)-1):min(end, c(i)+1)))
                    thresImg(r(i), c(i)) = 1;
                end
            end
        end
        if (isequal(oldThresImg, thresImg))
            break;
        end
    end
    edgeImg = thresImg;
2598 chars
71 lines

The myCannyDetector function takes four arguments: the input image (img), the standard deviation of the Gaussian filter (sigma), and the low and high threshold values for hysteresis thresholding (thLow and thHigh). The function returns a binary image with 1's at the edges and 0's elsewhere.

Here's an example of how to use myCannyDetector to calculate homography between two images:

main.m
% Load two images
img1 = imread('image1.jpg');
img2 = imread('image2.jpg');

% Detect edges using canny edge detection
edgeImg1 = myCannyDetector(img1, 1, 0.1, 0.3);
edgeImg2 = myCannyDetector(img2, 1, 0.1, 0.3);

% Find matching features using SURF
points1 = detectSURFFeatures(edgeImg1);
points2 = detectSURFFeatures(edgeImg2);
features1 = extractFeatures(edgeImg1, points1);
features2 = extractFeatures(edgeImg2, points2);
indexPairs = matchFeatures(features1, features2);

% Calculate homography using RANSAC
tolerance = 5;
[homography, inlierIndex] = estimateGeometricTransform(...
    points1(indexPairs(:,1)), points2(indexPairs(:,2)), ...
    'projective', 'MaxDistance', tolerance);

% Visualize the results
figure;
showMatchedFeatures(img1, img2, ...
    points1(indexPairs(:,1)), points2(indexPairs(:,2)), ...
    'montage', 'Parent', axes);
title('Matched Features');
legend('Matched points 1', 'Matched points 2');

figure;
showMatchedFeatures(img1, img2, ...
    points1(inlierIndex), points2(inlierIndex), ...
    'montage', 'Parent', axes);
title('Inlier Features');
legend('Inlier points 1', 'Inlier points 2');

figure;
plot(img1);
hold on;
projectedPoints = transformPointsForward(homography, [1 1; 1 size(img2,1); size(img2,2) size(img2,1); size(img2,2) 1]);
line(projectedPoints(:,1), projectedPoints(:,2), 'color', 'r');
title('Projected Image 2 onto Image 1');
1384 chars
43 lines

This code first detects edges in both images using myCannyDetector. Then, it uses the Speeded Up Robust Features (SURF) algorithm to find matching feature points between the two images. The estimateGeometricTransform function is used to calculate a homography transformation between the two sets of feature points using a Random Sample Consensus (RANSAC) algorithm. Finally, the code visualizes the matched and inlier feature points, as well as the projected image 2 onto image 1 using the calculated homography.

gistlibby LogSnag