%==========================================================================
%Image Retrieval using Edge Histograms
%Programming by Yang Liu
%2010-02-01
%==========================================================================

%Each edge image is partitioned by m*n tiles
m = 6;
n = 8;

%Store the name of the images
store_imname = cell(5,1);
store_imname{1} = 'animals-';
store_imname{2} = 'bird-';
store_imname{3} = 'butterfly-';
store_imname{4} = 'face-';
store_imname{5} = 'landscape-';

%store the histogram of each image in store_hist
store_hist = zeros(30,m*n);

im_num = 1;
for i = 1 : 5
    for j = 0 : 5
        current_imname = strcat(store_imname{i},num2str(j),'.jpg');
        current_im = im2uint8(imread(current_imname));
        im_edge = im2uint8(edge(rgb2gray(current_im),'canny'));            %get the edge of each image by canny method
        tile_row = round(size(im_edge,1)/m);
        tile_col = round(size(im_edge,2)/n);                               %the length and width of each tile
        hist_num = 1;
        for k1 = 1 : m
            if k1 == m
                t_r_end = size(im_edge,1);
            else
                t_r_end = tile_row*k1;
            end
            for k2 = 1 : n   
                if k2 == n
                    t_c_end = size(im_edge,2);
                else
                    t_c_end = tile_col*k2;
                end
                for kk1 = (k1-1)*tile_row+1 : t_r_end
                    for kk2 = (k2-1)*tile_col+1 : t_c_end
                        if im_edge(kk1,kk2) == 255
                            store_hist(im_num,hist_num) = store_hist(im_num,hist_num)+1;
                        end
                    end
                end
                hist_num = hist_num +1;                                    %For each tile of each edge image, count the number of edge pixels and save it in store_hist
            end
        end
        im_num = im_num + 1;
    end
end

%Store the distances between histograms of each two edge images
dis_matrix = zeros(30,30);

%Either Lp metrics or Cos metrics can be used for measurement
p=4;
for i = 1 : 30
    for j = 1 : 30
        if j ~= i
            dis_matrix(i,j) = norm(store_hist(i,:)-store_hist(j,:),p);     %Lp metrics with different values of p. If p=2, it's Euclidean distance
%             dis_matrix(i,j) = 1 - dot(store_hist(i,:),store_hist(j,:))/(norm(store_hist(i,:))*norm(store_hist(i,:)));
        end                                                                %replace Lp distance with Cos distance
    end
end

%check the top 5 most similar pictures of each picture
for i = 1 : 30
    s = mod(i,6)-1;
    if s<0
        s = s+6;
    end
    name = strcat(store_imname{ceil(i/6)},num2str(s),'.jpg');
    fprintf(['The top 5 most similar image to ',name,' are ']);
    d = abs(dis_matrix(i,:));
    A = sort(d);
    result = find(d <= A(6) & d ~= 0);
    for j = 1 : size(result,2)
        ss = mod(result(j),6)-1;
        if ss<0
            ss = ss + 6;
        end
        fprintf([strcat(store_imname{ceil(result(j)/6)},num2str(ss),'.jpg'),' ']);
    end
    fprintf('\n');
end