Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting stuck on Matlab's subplot mechanism for matching images' points for vlfeat

I am doing vlfeat in Matlab and I am following this question here.

These below are my simple testing images:

Left Image:

L

Right Image:

R

I did a simple test with 2 simple images here (the right image is just rotated version of the left), and I got the result accordingly:

test

It works, but I have one more requirement, which is to match the SIFT points of the two images and show them, like this:

likethis

I do understand that vl_ubcmatch returns 2 arrays of matched indices, and it is not a problem to map them for which point goes to which point on two images. However, I am currently stuck in matlab's procedure. I found this. But that only works if the subplot stays that way. When you add an image into the subplot, the size changes and the normalization failed.

Here is my code: (im and im2 are images. f, d and f2, d2 are frames and descriptors from vl_sift function from 2 images respectively)

    [matches score] = vl_ubcmatch(d,d2,threshold);%threshold originally is 1.5

if (mode >= 2)%verbose 2

    subplot(211);
    imshow(uint8(im));
    hold on;
    plot(f(1,matches(1,:)),f(2,matches(1,:)),'b*');

    subplot(212);
    imshow(uint8(im2));
    hold on;
    plot(f2(1,matches(2,:)),f2(2,matches(2,:)),'g*');

end

if (mode >= 3)%verbose 3

     [xa1 ya1] = ds2nfu(  f(1,matches(1,:)),  f(2,matches(1,:)));
     [xa2 ya2] = ds2nfu( f2(1,matches(2,:)), f2(2,matches(2,:)));

    for k=1:numel(matches(1,:))

        xxa1 = xa1(1, k);
        yya1 = ya1(1, k);
        xxa2 = xa2(1, k);
        yya2 = ya2(1, k);

        annotation('line',[xxa1 xxa2],[yya1 yya2],'color','r');
    end
end

The code above yields this:

an

I think subplot isn't a good way to go for something like this. Is there a better method for this in Matlab? If possible, I want something like an empty panel that I can draw my image, draw lines freely and zoom freely, just like drawing 2D games in OpenGL style.

like image 677
Karl Avatar asked Nov 09 '12 09:11

Karl


2 Answers

From zplesivcak's suggestion, yes, it is possible, and not that problematic after all. Here is the code:

%  After we have applied vl_sift with 2 images, we will get frames f,f2, 
%  and descriptor d,d2 of the images. After that, we can apply it into 
%  vl_ubcmatch to perform feature matching:

[matches score] = vl_ubcmatch(d,d2,threshold); %threshold originally is 1.5

% check for sizes and take longest width and longest height into
% account
if (size(im,1) > size(im2,1))
    longestWidth = size(im,1);       
else
    longestWidth = size(im2,1);
end

if (size(im,2) > size(im2,2))
    longestHeight = size(im,2);
else
    longestHeight = size(im2,2);
end


% create new matrices with longest width and longest height
newim = uint8(zeros(longestWidth, longestHeight, 3)); %3 cuz image is RGB
newim2 = uint8(zeros(longestWidth, longestHeight, 3));

% transfer both images to the new matrices respectively.
newim(1:size(im,1), 1:size(im,2), 1:3) = im;
newim2(1:size(im2,1), 1:size(im2,2), 1:3) = im2;

% with the same proportion and dimension, we can now show both
% images. Parts that are not used in the matrices will be black.
imshow([newim newim2]);

hold on;

    X = zeros(2,1);
    Y = zeros(2,1);

    % draw line from the matched point in one image to the respective matched point in another image.
    for k=1:numel(matches(1,:))

        X(1) = f(1, matches(1, k));
        Y(1) = f(2, matches(1, k));
        X(2) = f2(1, matches(2, k)) + longestHeight; % for placing matched point of 2nd image correctly.
        Y(2) = f2(2, matches(2, k));

        line(X,Y);

    end

Here is the test case:

tc

By modifying the canvas width and height of one of the images from the question, we see that the algorithm above will take care of that and display the image accordingly. Unused area will be black. Furthermore, we see that the algorithm can match the features of two images respectively.

EDIT:

Alternatively, suggested by Maurits, for cleaner and better implementation, check out Lowe SIFT matlab wrappers.

like image 141
Karl Avatar answered Nov 10 '22 05:11

Karl


If you have Matlab Computer Vision Library installed on your disc already, you can simply use

M1 = [f(1, match(1, :)); f(2, match(1, :)); ones(1, length(match))];
M2 = [f2(1, match(2, :)); f2(2, match(2, :)); ones(1, length(match))];

showMatchedFeatures(im,im2,[M1(1:2, :)]',[M2(1:2, :)]','montage','PlotOptions',{'ro','g+','b-'} );
like image 3
SimaGuanxing Avatar answered Nov 10 '22 04:11

SimaGuanxing