边缘检测评估代码的使用

1. 前言

最近半年一直在做边缘检测的工作,主要是阅读最新的论文、复现别人的代码(很多论文作者都上传了完整的项目)、验证算法结果和比较算法性能。在这个过程中遇到了一个问题:如何量化评估边缘检测算法。在边缘检测的论文中,均是以ODS-F和OIS-F作为评价指标和优化目标(具体原理可以参考这篇博客《边缘检测评估指标》),所使用的核心代码是BSDS500数据集所附带的benchmark文件(注:该数据集的官网为BSDS,但是BSDS500数据集从官网下载不到了,只能下载到BSDS300和benchmark文件)。但是大部分博客都是介绍原理和部分核心代码,并没有完整的使用过程,因此我在搜寻网上的博客以及自己本地跑通之后,决定写下来记录一下,一是为自己以后的工作铺路,防止自己更换工作环境遗忘;另外是为一些同样做边缘检测的人做一些参考。
但是,由于当时跑通整个代码的流程完全是自己一点点对着bug来改、来修正的,所以有很多步骤我在跑通代码的时候就记不起来了(这就是我为什么没有当时就写下来),但至少现在还有记着的东西,有总比没有强。所以,我希望看到这篇博客的人,能够留下来你在运行代码时出现的报错,可能会对我的回忆有帮助,我也尽力去解决,然后逐步完善这篇博客。
本文参考:保姆级 边缘检测评价OIS、ODS、PR曲线绘制 ——在自己的数据集上

2. 边缘检测评估代码

代码语言:MATLAB
软件版本:MATLABR2021b(在我参考的那篇博客中建议使用2016之前的版本,但是似乎经过我对代码的修改,之后的版本也没什么问题)
前文提到,评估代码的核心是BSDS500提供的benchmark文件,事实证明基本所有的边缘检测算法均使用这套代码进行评估。如果你看过我上文提到的评估原理参考的博客《边缘检测评估指标》,你会发现里面要计算许多参数,而这套代码把这些计算过程均完整的编写成函数,成为了一个“库”,然后调用这些库函数进行最终的计算,同时还提供了绘制PR曲线的函数,可以同时绘制多个算法的PR曲线进行比较。另外,由于基于神经网络的边缘检测算法输出的边缘都比较粗,因此需要先进行非极大值抑制(NMS,具体原理可自行搜索)操作,然后再进行评估指标的计算。因此许多边缘检测算法的作者均将NMS和计算评估指标的操作集成在一个文件中,方便使用。我这里使用的是网上流传较多的一个代码:hed,eval文件夹中eval_edge.m即为评估代码。

2.1 代码的使用

2.1.1 代码环境的配置

经过我对代码的修改以及他人运行验证,该代码可以完美运行。
运行评估代码需要安装pdollar toolbox和pdollar_edges两个工具箱,在刚才下载的hed文件夹中已经包含了,即edges和toolbox.badacost.public两个文件夹,并且在eval_edge.m文件的开头位置将这两个工具箱的位置添加进了matlab系统路径。

2.1.2 NMS代码

eval_edge.m分为两个部分,Section 1是NMS操作,Section 2是评估指标计算操作。这里NMS操作用的是.mat格式的文件,这里我的建议是不要用png、jpg等格式的图片转mat格式!!!这样NMS出来的结果质量非常差!受PIDINET算法代码的启发,正确的做法是:在模型预测边缘的时候,和输出图片一样,直接输出一个mat格式的文件:

#(这只是核心代码,根据自己的项目添加)
import scipy.io as sio
results = model(image)
result = torch.squeeze(results[-1]).cpu().detach().numpy()
sio.savemat(os.path.join(mat_dir, '%s.mat' % img_name), {'img': result}) #路径根据自己的代码修改

将生成的mat文件放在“data/算法名称/mat”文件夹下,目录结构为:

├── data
│   ├── 算法名称              
│   │   ├── mat
│   │   │   └── 2018.mat
│	 │	   │	└── ...
│   │   └── nms
│   └── ...
├── edges                   
├── toolbox.badacost.public
└── edge_eval.m 

这样输出的mat文件中存储的数据结构和BSDS官方给的test中的mat文件的数据结构不太一样(我对mat格式文件不是很懂,感兴趣的可以输出一下看看),如果你直接运行NMS代码会报错,因此需要将NMS部分的代码修改为:

% Section 1: NMS process (formerly nms_process.m from HED repo).
disp('NMS process...')%输出字符串
mat_dir = fullfile(data_dir, 'mat'); %拼接文件路径
nms_dir = fullfile(data_dir, 'nms');
mkdir(nms_dir)

files = dir(mat_dir);%获得所有子文件夹和文件并返回结构体,第一行和第二行是当前目录和上一级目录
files = files(3:end,:);  % It means all files except ./.. are considered.
mat_names = cell(1,size(files, 1));%size(files, 1)返回files的行数,cell(1,n)返回1*n的元胞数组
nms_names = cell(1,size(files, 1));
for i = 1:size(files, 1)
    mat_names{i} = files(i).name;
    nms_names{i} = [files(i).name(1:end-4), '.png']; % Output PNG files.
end

for i = 1:size(mat_names,2)
    matObj = matfile(fullfile(mat_dir, mat_names{i})); % Read MAT files.
    varlist = who(matObj);%将文件名称存在元胞数组varlist中
    x = matObj.(char(varlist));
    if iscell(x)
        x=x{1}
        x = x.Boundaries;  % 提取 'Boundaries' 字段的数值矩阵
    end
    E=convTri(single(x),1);
    [Ox,Oy]=gradient2(convTri(E,4));
    [Oxx,~]=gradient2(Ox); [Oxy,Oyy]=gradient2(Oy);
    O=mod(atan(Oyy.*sign(-Oxy)./(Oxx+1e-5)),pi);
    E=edgesNmsMex(E,O,1,5,1.01,4);
    imwrite(uint8(E*255),fullfile(nms_dir, nms_names{i}))
end

这样输出的NMS结果就会保存到"data/算法名称/nms"文件夹中了。

2.1.3 评估代码

评估部分代码应该没有太大问题,可以直接使用,注意这里的gtDir是对应的真值mat格式的文件,比如你用BSDS的test文件夹中200张图片做的测试,就可以直接用BSDS官方给的真值文件进行计算,将文件路径改为你自己的路径即可,edgesEvalPlot函数是绘制PR曲线,在一张图上绘制多个算法的PR曲线可以参考plot-edge-pr-curves

% Section 2: Evaluate the edges (formerly EvalEdge.m from HED repo).
disp('Evaluate the edges...');
gtDir  = 'data/groundTruth/test';
resDir = fullfile(data_dir, 'nms');
edgesEvalDir('resDir',resDir,'gtDir',gtDir, 'thin', 1, 'pDistr',{{'type','parfor'}},'maxDist',0.0075);

figure; edgesEvalPlot(resDir,'想要显式的名称');
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Reborker

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值