如何在MATLAB中绘制基于内容的图像检索的Precision-Recall图?

时间:2014-09-12 00:51:51

标签: matlab image-processing cbir

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

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

1 个答案:

答案 0 :(得分:10)

Precision-Recall图表可以测量图像检索系统的准确性。它们也真正用于任何搜索引擎的表现,如文本或文档。它们也用于机器学习评估和性能,但ROC Curves是更常用的。

Precision-Recall图更适合文档和数据检索。对于此处的图像,给定查询图像,您将测量此图像与数据库中其余图像的相似程度。然后,您对每个与查询图像相关的数据库图像都有相似性度量,然后按降序排序这些相似性。对于一个好的检索系统,您可能希望所有最相关的图像(即您要搜索的图像)都出现在开头,而不相关的图像将出现在之后。

精密

精确度的定义是您检索的相关图像数量与检索到的不相关和相关图像总数之比。换句话说,假设A是检索到的相关图像的数量,B是检索到的不相关图像的总数。计算精度时,您可以查看前几个图像,此数量为A + B,因为相关和不相关图像的总数是您此时正在考虑的图像数量。因此,另一个定义精度定义为您从目前为止检索到的相关图像的数量与您抓取的数量之比:

Precision = A / (A + B)

提取

Recall的定义略有不同。这将评估您到目前为止已检索到的相关图像的数量已知总数,这是存在的相关图像的总数。因此,让我们再次看一下前几张图片。然后,您可以确定有多少相关图像,然后计算到目前为止从数据库中的所有相关图像中检索到的相关图像数量。这被定义为您总体检索的相关图像的比例。假设A再次是您从数据库中抓取的一堆相关图像的总数,而C表示相关图像的数量你的数据库。召回因此定义为:

Recall = A / C

如何在MATLAB中计算它实际上非常简单。您首先需要知道数据库中有多少相关图像。之后,您需要知道针对查询图像分配给每个数据库图像的相似性度量。计算完这些后,您需要知道哪些相似性度量映射到数据库中的相关图像。我在你的代码中没有看到,所以我会把它留给你。完成此操作后,您可以对相似度值进行排序,然后在经过排序的相似度值的位置对这些相关图像进行排序。然后使用它们来计算精度和召回率。

我将提供一个玩具示例,以便我可以向您展示图表的样子,因为您不清楚如何在此处计算您的相似之处。让我们说我在20个数据库中有5个图像,我和它们之间有一堆相似性值和查询图像:

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

另外,我知道图片[1 5 7 9 12]是我的相关图片。

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

现在让我们按降序顺序对相似度值进行排序,因为更高的值意味着更高的相似度。如果您正在计算相异度度量,请反过来:

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

locs现在将包含每个图片排名为的图像排名。具体来说,它们告诉您图像所属的相似位置。 sorted_sims将按降序排列相似性:

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

因此,第7幅图像是排名最高的图像,其次是第16幅图像是第二高的图像,依此类推。您现在需要做的是对于您知道相关的每个图像,您需要在排序后确定这些图像的位置。我们将浏览我们知道相关的每个图像ID,并找出它们在上述位置数组中的位置:

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

locations_final =

  5     4     1    10     3

让我们对它们进行排序,以便更好地理解这是在说什么:

locations_sorted = sort(locations_final)

locations_sorted = 

 1     3     4     5    10

上面的这些位置现在会告诉您顺序,其中会显示相关图片。这样,第一相关图像将首先出现,第二相关图像将出现在第三位置,第三相关图像出现在第四位置,依此类推。这些精确对应于Precision的部分定义。例如,在locations_sorted的最后一个位置,将需要十个图像来检索我们数据库中的所有相关图像(5)。同样,它需要五个图像来检索数据库中的四个相关图像。因此,您可以像这样计算精度:

precision = (1:num_relevant_images) ./ locations_sorted;

同样对于召回,它只是迄今为止从总数中检索到的图像的比例,因此它只是:

recall = (1:num_relevant_images) / num_relevant_images;

您的Precision-Recall图现在如下所示,其中x轴为Recall,y轴为Precision:

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;

这是我得到的图表:

enter image description here

您会注意到,在召回率为0.4到0.8之间,精度会有所提高。这是因为您已设法检索连续的图像链而不触及任何不相关的图像,因此您的精度自然会增加。在最后一张图片之后它会消失,因为在最终拍摄相关图像之前,您必须检索这么多不相关的图像。

您还会注意到精确度和召回率是反向相关的。因此,如果精度增加,则召回减少。同样,如果精度降低,则召回率会增加。

  • 第一部分是有道理的,因为如果您在开始时没有检索到那么多图像,那么您更有可能在结果中不包含不相关的图像,但与此同时,相关图像的数量相当于小。这就是为什么召回会在精度提高时减少的原因
  • 第二部分也有意义,因为当您不断尝试在数据库中检索更多图像时,您不可避免地能够检索所有相关图像,但您很可能会开始包含更多图像不相关的图像,这会降低您的精确度。

在理想的世界中,如果您的数据库中有N个相关图片,您可能希望在最N个最相似的位置看到所有这些图片。因此,这会使您的精确回忆图形成为在y = 1处悬停的平坦水平线,这意味着您已设法检索所有顶部位置中的所有图像,而无需访问任何不相关的图像。不幸的是,这种情况永远不会发生(或者至少现在不会发生......)因为试图找出CBIR的最佳功能仍然是一项持续的调查,而且我所看到的图像搜索引擎都没有设法得到这个完美。这仍然是目前存在的最广泛和最未解决的计算机视觉问题之一!


修改

您检索此代码以计算this post的直方图交点。他们有一种计算直方图交集的简洁方法:

enter image description here

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

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

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));

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

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

希望这有帮助!

相关问题