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

Posted

技术标签:

【中文标题】如何在 MATLAB 中为基于内容的图像检索绘制 Precision-Recall 图?【英文标题】:How do I plot Precision-Recall graphs for Content-Based Image Retrieval in MATLAB? 【发布时间】:2014-11-06 02:10:54 【问题描述】:

我正在访问文件夹“c1”中的 10 张图像,并且我有查询图像。我已经实现了在单元格数组中加载图像的代码,然后我正在计算查询图像和文件夹“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);
    Seqi=I;


end
for i = 1 : length(srcFiles)  % loop for calculating histogram intersections
    A=Seqi;
    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

【问题讨论】:

你可以看this的回答了解详情。我还没有看到您关于分类问题的任何信息。 那么你如何在你的上下文中定义精确度和召回率? 啊,CBIR……我多么想念你。我给你写一个答案。等一下 @ParagS.Chandakkar - 这不是分类问题。这是一个基于内容的图像检索问题。它是关于测量一张图像与数据库中的图像的相似程度,然后根据这种相似性对它们进行排名。我想说这更像是一个模糊分类。 【参考方案1】:

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 现在将包含每个图像排名的图像ranks。具体来说,这些会告诉您图像属于哪个相似位置。 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 的最后一个位置,需要 10 张图像来检索我们数据库中的所有相关图像 (5)。同样,在数据库中检索四张相关图像需要 五张 图像。因此,您可以像这样计算精度:

precision = (1:num_relevant_images) ./ locations_sorted;

与召回类似,它只是到目前为止检索到的图像数量与总数的比率,因此它只是:

recall = (1:num_relevant_images) / num_relevant_images;

您的 Precision-Recall 图表现在如下所示,Recall 位于 x 轴,Precision 位于 y 轴:

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;

这是我得到的图表:

您会注意到,在 0.4 到 0.8 的召回率之间,准确率略有提高。这是因为您已经成功地检索了连续的图像链,而没有触及任何不相关的图像,因此您的精度自然会提高。在最后一张图片之后,它会下降很多,因为在最终找到相关图片之前,您必须检索很多不相关的图片。

您还会注意到准确率和召回率呈负相关。因此,如果精度提高,那么召回率就会降低。同样,如果精度降低,那么召回率就会增加。

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

在理想情况下,如果您的数据库中有N 相关图像,您会希望在最相似的N 顶部看到所有这些图像。因此,这将使您的精确召回图成为一条悬停在y = 1 的水平线,这意味着您已经成功地检索了所有顶部位置的所有图像,而无需访问任何不相关的图像。不幸的是,这永远不会发生(或者至少现在不会……)因为试图找出 CBIR 的最佳功能仍然是一项持续的调查,而且我所见过的任何图像搜索引擎都无法做到这一点完美的。这仍然是当今存在的最广泛和未解决的计算机视觉问题之一!


编辑

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

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

因此,我们需要修改您的代码,以便您为每个图像使用imhist。我们还可以指定一个附加参数,为您提供每个直方图将有多少个 bin。因此,您的代码将如下所示。我放置的每一行都会在每一行旁边有一个%// 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;),然后运行您的图像。您还需要知道哪些图像是相关图像,并且您必须更改我编写的代码以反映这一点。

希望这会有所帮助!

【讨论】:

感谢您的解释。我正在尝试使用上面编码的“直方图交集”来查找查询图像和数据库图像之间的相似性。但我不确定它是否给了我相似之处。你能告诉我,我如何使用直方图交集找到相似之处? @nikhilk 直方图交集根据定义是一种相似性度量。它告诉您两个直方图之间有多少重叠,并且可以通过其直方图来表征图像。因此,我不太清楚你想问什么。你想知道如何计算它吗? 是的,我想知道如何计算直方图交集。在上面的代码中。我已经给它打码了,你能告诉我它是否正确吗? @nikhilk - 不,看起来不像。你从哪里得到直方图交集的定义?另外,B 是您的查询图像,A 是您的数据库图像吗?您对上面提供的代码没有给出太多解释。 @nikhilk - (1) RGB 图像完全不同。您需要量化每个颜色平面,然后将量化转换为单个 1D bin 以进行索引。这无法在评论中回答,我鼓励您再发一篇文章。 (2) 我不需要看到 P-R 曲线,因为我很确定上面的代码有效。因此,请考虑接受我的回答,并在另一篇帖子中请求有关彩色图像的帮助。

以上是关于如何在 MATLAB 中为基于内容的图像检索绘制 Precision-Recall 图?的主要内容,如果未能解决你的问题,请参考以下文章

毕设题目:Matlab图像检索

图像检索基于matlab GUI Hu不变矩图像检索含Matlab源码 1508期

图像检索基于matlab HSV图像检索含Matlab源码 2410期

图像检索基于matlab小波变换DWT图像检索含Matlab源码 2404期

图像检索基于matlab GUI综合颜色和形状特征图像检索含Matlab源码 1370期

图像检索基于matlab GUI综合颜色和形状特征图像检索含Matlab源码 1370期