最近在研究边缘提取,复现了文章Richer Convolutional Features for Edge Detection的代码,在做评估的时候遇到了一些问题,不知道在边缘检测中精确率和召回率到底是怎么计算的,终于搞明白后决定记录下来。本篇博客的记录所有出现的代码都源于这里。
一般取β=1,此时F-Measure的取值为:
论文中使用的也是该公式。
在目标检测、分类中,我们使用TP 、TN 、FP 、FN来计算Precision(精确度)和Recall(召回率):
精确率表示:预测为正例的结果中有多少是真的正例。强调预测的准确性。
召回率表示:所有真的正例中有多少被预测为正例。强调把多少真正的正例召唤回来。
在边缘检测中判断预测边界像素是否被正确预测需用到一个概念“距离容差”,它的作用是对预测结果tolerant,允许预测与真实边界图存在小的定位错误。
在correspondPixels算法中距离容差通过一个参数maxDist表示,代码默认该参数设置为0.0075。在自己求这个距离容差时,可以使用maxDist乘自己图片的大小(高或宽)。若你的图片为256481,则在行方向上允许2560.0075≈2像素的距离容差,在列方向上允许481*0.0075≈4像素的距离容差。也可以更改maxDist的值。
有一些参数必须要知道:
E1:所有手工标注的真值边缘图(该image的groundTruth有多少个boundaries,就有多少个真值边缘图,我认为也可称为子边界图。例如BSDS500数据集中test集中的图片2018.jpg对应的groundTruth有5个边缘图)进行二值化后求“并”的结果(我认为这个结果可以称为总边界图)。有一个边缘图对应的像素点大于阈值就为1,否则为0。
举例说明:假如一张3*3的图片有三个真值边界图(在某一阈值下),
那么得到的E1就是:
计算过程如下:
matchE:预测的边缘点在所有真值map中有至少一个的对应点为边缘点就表示预测正确(也就是说在3个真值中,只要有一个与预测边缘点相对应,就可以认为预测正确)。预测正确的边缘点为1,否则为0。所以TP=matchE。
matchG:你预测的边缘点在真值中也为边缘点的点数(从0到真实边缘图
数)。在上例中,每一个像素可取的值为0-3。
计算过程如下:
可以看出,从matchG到matchE就是对每个元素进行二值化的结果,matchG中的非零值设为1,0值保持0.
allG:在真值中把对应点预测为边缘点的点数(从0到真实边缘图数)。上例
中可取的值为0-3。
计算过程:
这几个变量都是二维矩阵,大小等于输入图像的高和宽。
此时,通过计算四个值:
在上例中:
cntR(k) =3 sumR(k)=7 cntP(k)=2 sumP(k)=5
求Precision:cntP /sumP
求Recall:cntR/ sumR
通过上一步计算P和R,最后得到的有用的参数:[thrs cntR sumR cntP sumP], thrs表示阈值。每张图片会有一个[id]_evl.txt文件。有99行,分别对应99个不同阈值和相应的cntR sumR cntP sumP值。对于每一个阈值求相应的Precision和Recall就可画出PR曲线。
将每张图片对应的txt文件读出来后,首先计算每一张图片的R、P、F,它们都是T行一列的矩阵,其中T为阈值个数。
代码:
function [R,P,F] = computeRPF(cntR,sumR,cntP,sumP)
% compute precision, recall and F measure given cnts and sums
R=cntR./max(eps,sumR);
P=cntP./max(eps,sumP);
F=2*P.*R./max(eps,P+R);
end
这样就能找到使F值最大的阈值k,也就是该张图片的最佳阈值。将得到的结果保存在eval_bdry_img.txt内。
代码:
function [bstR,bstP,bstF,bstT] = findBestRPF(T,R,P)
% linearly interpolate to find best thr for optimizing F
if(numel(T)==1), bstT=T; bstR=R; bstP=P;
bstF=2*P.*R./max(eps,P+R); return; end
A=linspace(0,1,100); B=1-A; bstF=-1;
for j = 2:numel(T)
Rj=R(j).*A+R(j-1).*B; Pj=P(j).*A+P(j-1).*B; Tj=T(j).*A+T(j-1).*B;
Fj=2.*Pj.*Rj./max(eps,Pj+Rj); [f,k]=max(Fj);
if(f>bstF), bstT=Tj(k); bstR=Rj(k); bstP=Pj(k); bstF=f; end
end
end
如果看不懂的话,可以参考一下我自己记录时画的图:
对每张图片计算[R,P,F] = computeRPF(cntR1,sumR1,cntP1,sumP1); [~,k]=max(F);这样就能找到使F值最大的阈值k,在计算PR曲线时得到的[id]_evl.txt文件中就能读出相应的cntR1(k),sumR1(k),cntP1(k),sumP1(k)。找到使每张图片F值最大的cntR,sumR,cntP,sumP,然后分别求和,使用computeRPF(cntR,sumR,cntP,sumP)求出对应的P、R、F就是OIS所需参数。
直接按照阈值将所有图片的cntR,sumR,cntP,sumP分别求和,使用computeRPF(cntR,sumR,cntP,sumP)得到不同阈值下的T、R、P,然后利用findBestRPF(T,R,P)找到F取到最大值的那一组。对应的T就是ODS方法所取得应用于所有图片的阈值。
平均准确率,是PR曲线的积分(即PR曲线下方的面积)。由于PR曲线很难积分,通常在PR曲线上采样求均值。
代码:
k=k(end:-1:1);
R=R(k);
P=P(k);
T=T(k);
F=F(k);
AP=0;
if(numel(R)>1),
AP=interp1(R,P,0:.01:1);%插值,来提高精确度
AP=sum(AP(~isnan(AP)))/100; %求均值
End
论文中没有说这个指标,但是代码写到了,代码计算如下:
[~,o]=unique(P); R50=interp1(P(o),R(o),max(P(o(1)),.5));
记录到此结束了,若有错误请提出并见谅~
另外提供几个我参考的比较好的博客:
https://www.cnblogs.com/jiangnanyanyuchen/p/13868320.html
https://blog.csdn.net/AAAAshin/article/details/108042346