如何在MATLAB中绘制基于内容的图像检索的Precision-Recall图? [英] How do I plot Precision-Recall graphs for Content-Based Image Retrieval in MATLAB?

查看:242
本文介绍了如何在MATLAB中绘制基于内容的图像检索的Precision-Recall图?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在从文件夹c1访问10张图片,我有查询图片。我已经实现了在单元格数组中加载图像的代码,然后我将逐个计算查询图像与文件夹c1中每个图像之间的直方图交集。现在我想绘制精确回忆曲线,但我不知道如何编写代码以使用从直方图交叉点获得的数据获得精确回忆曲线。
我的代码:

  Inp1 = rgb2gray(imread('D:\ visionImages \c1 \\\。 PPM')); 
figure,imshow(Inp1),title('输入图像1');

srcFiles = dir('D:\ visionImages \c1 \ * .ppm'); %存在图像的文件夹
表示i = 1:length(srcFiles)
filename = strcat('D:\ visionImages \c1 \',srcFiles(i).name);
I = imread(filename);
I = rgb2gray(I);
Seq {i} = I;


结束
i = 1:长度(srcFiles)%循环用于计算直方图交叉点
A = Seq {i};
B = Inp1;
a = size(A,2); b =大小(B,2);
K =零(a,b); j = 1的
:a
Va = repmat(A(:,j),1,b);
K(j,:) = 0.5 *总和(Va + B - abs(Va - B));
结束
结束


解决方案

精确度 - 重新调用图表可以衡量图像检索系统的准确性。它们也用于任何搜索引擎的性能,如文本或文档。它们也用于机器学习评估和性能,但。他们有一种计算直方图交集的简洁方法:





n 是直方图中的总箱数。你必须使用它来获得良好的结果,但我们可以将其作为代码中的参数。上面的代码假设您有两个矩阵 A B 其中每列是直方图。你将生成一个 axb 的矩阵,其中 a A 和 b b 中的列数。此矩阵的行和列(i,j)告诉您中的i th 列之间的相似性/ code> B 中的 b j th 列。在您的情况下, A 将是一个列,表示查询图像的直方图。 B 将是一个10列矩阵,表示每个数据库图像的直方图。因此,我们将通过直方图交叉获得 1 x 10 的相似性度量数组。



因此,我们需要修改您的代码,以便您使用 imhist 。我们还可以指定一个附加参数,该参数可以为您提供每个直方图将具有的箱数。因此,您的代码将如下所示。我放置的每一个新行都会在每行旁边有一个%// NEW 注释。

  INP1 = rgb2gray(imread( 'd:\visionImages\c1\1.ppm')); 
figure,imshow(Inp1),title('输入图像1');
num_bins = 32; %// NEW - 我在这里指定了32个bin。自己玩这个

A = imhist(Inp1,num_bins); %// NEW - 计算直方图

srcFiles = dir('D:\ visionImages \c1 \ * .ppm'); %存在图像的文件夹
B =零(num_bins,length(srcFiles)); %// NEW - 存储数据库图像的直方图
表示i = 1:length(srcFiles)
filename = strcat('D:\ visionImages \ c1 \',srcFiles(i).name );
I = imread(filename);
I = rgb2gray(I);
B(:,i)= imhist(I,num_bins); %// NEW - 将每个直方图放在单独的
%//列
结束
%// NEW - 直接从网站上获取
%//但仅修改一个直方图在'A`
b =大小(B,2);
Va = repmat(A,1,b);
K = 0.5 *总和(Va + B - abs(Va - B));






请注意我已复制代码网站,但我修改了它,因为 A 中只有一个图像,因此有一些代码是不必要的。



K 现在应该是 1 x 10 直方图交叉点相似性数组。然后,您将使用 K 并将 sims 分配给此变量(即 sims = K; )在我上面编写的代码中,然后运行你的图像。您还需要知道哪些图像是相关图像,并且您必须更改我编写的代码以反映这一点。



希望这会有所帮助!


I am accessing 10 images from a folder "c1" and I have query image. I have implemented code for loading images in cell array and then I'm calculating histogram intersection between query image and each image from folder "c1" one-by-one. Now i want to draw precision-recall curve but i am not sure how to write code for getting "precision-recall curve" using the data obtained from histogram intersection. My code:

Inp1=rgb2gray(imread('D:\visionImages\c1\1.ppm'));
figure, imshow(Inp1), title('Input image 1');

srcFiles = dir('D:\visionImages\c1\*.ppm');  % the folder in which images exists
for i = 1 : length(srcFiles)
    filename = strcat('D:\visionImages\c1\',srcFiles(i).name);
    I = imread(filename);
    I=rgb2gray(I);
    Seq{i}=I;


end
for i = 1 : length(srcFiles)  % loop for calculating histogram intersections
    A=Seq{i};
    B=Inp1;
    a = size(A,2); b = size(B,2); 
    K = zeros(a, b);
    for j = 1:a
    Va = repmat(A(:,j),1,b);
    K(j,:) = 0.5*sum(Va + B - abs(Va - B));
    end  
end

解决方案

Precision-Recall graphs measure the accuracy of your image retrieval system. They're also used in the performance of any search engine really, like text or documents. They're also used in machine learning evaluation and performance, though ROC Curves are what are more commonly used.

Precision-Recall graphs are more suitable for document and data retrieval. For the case of images here, given your query image, you are measuring how similar this image is with the rest of the images in your database. You then have similarity measures for each of the database images in relation to your query image and then you sort these similarities in descending order. For a good retrieval system, you would want the images that are the most relevant (i.e. what you are searching for) to all appear at the beginning, while the irrelevant images would appear after.

Precision

The definition of Precision is the ratio of the number of relevant images you have retrieved to the total number of irrelevant and relevant images retrieved. In other words, supposing that A was the number of relevant images retrieved and B was the total number of irrelevant images retrieved. When calculating precision, you take a look at the first several images, and this amount is A + B, as the total number of relevant and irrelevant images is how many images you are considering at this point. As such, another definition Precision is defined as the ratio of how many relevant images you have retrieved so far out of the bunch that you have grabbed:

Precision = A / (A + B)

Recall

The definition of Recall is slightly different. This evaluates how many of the relevant images you have retrieved so far out of a known total, which is the the total number of relevant images that exist. As such, let's say you again take a look at the first several images. You then determine how many relevant images there are, then you calculate how many relevant images that have been retrieved so far out of all of the relevant images in the database. This is defined as the ratio of how many relevant images you have retrieved overall. Supposing that A was again the total number of relevant images you have retrieved out of a bunch you have grabbed from the database, and C represents the total number of relevant images in your database. Recall is thus defined as:

Recall = A / C


How you calculate this in MATLAB is actually quite easy. You first need to know how many relevant images are in your database. After, you need to know the similarity measures assigned to each database image with respect to the query image. Once you compute these, you need to know which similarity measures map to which relevant images in your database. I don't see that in your code, so I will leave that to you. Once you do this, you then sort on the similarity values then you go through where in the sorted similarity values these relevant images occur. You then use these to calculate your precision and recall.

I'll provide a toy example so I can show you what the graph looks like as it isn't quite clear on how you're calculating your similarities here. Let's say I have 5 images in a database of 20, and I have a bunch of similarity values between them and a query image:

rng(123); %// Set seed for reproducibility
num_images = 20;
sims = rand(1,num_images);

sims =

Columns 1 through 13

0.6965    0.2861    0.2269    0.5513    0.7195    0.4231    0.9808    0.6848    0.4809    0.3921    0.3432    0.7290    0.4386

Columns 14 through 20

0.0597    0.3980    0.7380    0.1825    0.1755    0.5316    0.5318

Also, I know that images [1 5 7 9 12] are my relevant images.

relevant_IDs = [1 5 7 9 12];
num_relevant_images = numel(relevant_IDs);

Now let's sort the similarity values in descending order, as higher values mean higher similarity. You'd reverse this if you were calculating a dissimilarity measure:

[sorted_sims, locs] = sort(sims, 'descend');

locs will now contain the image ranks that each image ranked as. Specifically, these tell you which position in similarity the image belongs to. sorted_sims will have the similarities sorted in descending order:

sorted_sims =

Columns 1 through 13

0.9808    0.7380    0.7290    0.7195    0.6965    0.6848    0.5513    0.5318    0.5316    0.4809    0.4386    0.4231    0.3980

Columns 14 through 20

0.3921    0.3432    0.2861    0.2269    0.1825    0.1755    0.0597

locs =

 7    16    12     5     1     8     4    20    19     9    13     6    15    10    11     2     3    17    18    14

Therefore, the 7th image is the highest ranked image, followed by the 16th image being the second highest image and so on. What you need to do now is for each of the images that you know are relevant, you need to figure out where these are located after sorting. We will go through each of the image IDs that we know are relevant, and figure out where these are located in the above locations array:

locations_final = arrayfun(@(x) find(locs == x, 1), relevant_IDs)

locations_final =

  5     4     1    10     3

Let's sort these to get a better understand of what this is saying:

locations_sorted = sort(locations_final)

locations_sorted = 

 1     3     4     5    10

These locations above now tell you the order in which the relevant images will appear. As such, the first relevant image will appear first, the second relevant image will appear in the third position, the third relevant image appears in the fourth position and so on. These precisely correspond to part of the definition of Precision. For example, in the last position of locations_sorted, it would take ten images to retrieve all of the relevant images (5) in our database. Similarly, it would take five images to retrieve four relevant images in the database. As such, you would compute precision like this:

precision = (1:num_relevant_images) ./ locations_sorted;

Similarly for recall, it's simply the ratio of how many images were retrieved so far from the total, and so it would just be:

recall = (1:num_relevant_images) / num_relevant_images;

Your Precision-Recall graph would now look like the following, with Recall on the x-axis and Precision on the y-axis:

plot(recall, precision, 'b.-');
xlabel('Recall');
ylabel('Precision');
title('Precision-Recall Graph - Toy Example');
axis([0 1 0 1.05]); %// Adjust axes for better viewing
grid;

This is the graph I get:

You'll notice that between a recall ratio of 0.4 to 0.8 the precision is increasing a bit. This is because you have managed to retrieve a successive chain of images without touching any of the irrelevant ones, and so your precision will naturally increase. It goes way down after the last image, as you've had to retrieve so many irrelevant images before finally hitting a relevant image.

You'll also notice that precision and recall are inversely related. As such, if precision increases, then recall decreases. Similarly, if precision decreases, then recall will increase.

  • The first part makes sense because if you don't retrieve that many images in the beginning, you have a greater chance of not including irrelevant images in your results but at the same time, the amount of relevant images is rather small. This is why recall would decrease when precision would increase
  • The second part also makes sense because as you keep trying to retrieve more images in your database, you'll inevitably be able to retrieve all of the relevant ones, but you'll most likely start to include more irrelevant images, which would thus drive your precision down.

In an ideal world, if you had N relevant images in your database, you would want to see all of these images in the top N most similar spots. As such, this would make your precision-recall graph a flat horizontal line hovering at y = 1, which means that you've managed to retrieve all of your images in all of the top spots without accessing any irrelevant images. Unfortunately, that's never going to happen (or at least not for now...) as trying to figure out the best features for CBIR is still an on-going investigation, and no image search engine that I have seen has managed to get this perfect. This is still one of the most broadest and unsolved computer vision problems that exist today!


Edit

You retrieved this code to compute histogram intersection from this post. They have a neat way of computing histogram intersection as:

n is the total number of bins in your histogram. You'll have to play around with this to get good results, but we can leave that as a parameter in your code. The code above assumes that you have two matrices A and B where each column is a histogram. You'll generate a matrix that is of a x b, where a is the number of columns in A and b is the number of columns in b. The row and column of this matrix (i,j) tells you the similarity between the ith column in A with the b jth column in B. In your case, A would be a single column which denotes the histogram of your query image. B would be a 10 column matrix that denotes the histograms for each of the database images. Therefore, we will get a 1 x 10 array of similarity measures through histogram intersection.

As such, we need to modify your code so that you're using imhist for each of the images. We can also specify an additional parameter that gives you how many bins each histogram will have. Therefore, your code will look like this. Each new line that I have placed will have a %// NEW comment beside each line.

Inp1=rgb2gray(imread('D:\visionImages\c1\1.ppm'));
figure, imshow(Inp1), title('Input image 1');
num_bins = 32; %// NEW - I'm specifying 32 bins here.  Play around with this yourself

A = imhist(Inp1, num_bins); %// NEW - Calculate histogram

srcFiles = dir('D:\visionImages\c1\*.ppm');  % the folder in which images exists
B = zeros(num_bins, length(srcFiles)); %// NEW - Store histograms of database images
for i = 1 : length(srcFiles)
    filename = strcat('D:\visionImages\c1\',srcFiles(i).name);
    I = imread(filename);
    I=rgb2gray(I);
    B(:,i) = imhist(I, num_bins); %// NEW - Put each histogram in a separate
                                  %// column              
end
%// NEW - Taken directly from the website
%// but modified for only one histogram in `A`
b = size(B,2); 
Va = repmat(A, 1, b);
K = 0.5*sum(Va + B - abs(Va - B));


Take note that I have copied the code from the website, but I have modified it because there is only one image in A and so there is some code that isn't necessary.

K should now be a 1 x 10 array of histogram intersection similarities. You would then use K and assign sims to this variable (i.e. sims = K;) in the code I have written above, then run through your images. You also need to know which images are relevant images, and you'd have to change the code I've written to reflect that.

Hope this helps!

这篇关于如何在MATLAB中绘制基于内容的图像检索的Precision-Recall图?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆