计算mAP的第一步就是使用detector.c中的validate_detector,利用验证集图片计算一堆的结果,然后存在result文件夹中的txt文件中。
如果你使用的不是coco或者voc数据集,根据源码,将会使用你自定义的type:
char *type = option_find_str(options, "eval", "voc");
所以建议在data文件中增加一行配置:
eval = YOUR_TYPE
如果type为coco,将会保存成json文件;如果type为imagenet,将会将所有的结果保存到imagenet-detection.txt文件中。如果不配置,也不会产生什么影响,依然会就会默认使用comp4_det_test_[classname].txt。只是为了保证工程的完整性建议修改。
另外,建议将源码中的outfile初始值修改一下,将validate_detector函数中的
if(!outfile) outfile = "comp4_det_test_";
改为:
if(!outfile) outfile = "";
再编译。这样的结果是result中的文件保存的文件名就为[classname].txt,使用Python函数voc_eval.py在计算的时候,
通过
R = [obj for obj in recs[imagename] if obj['name'] == classname]
过获取每个类型的文件中匹配到目标的信息,否则obj[‘name’],即recs[imagename][i][‘name’]=comp4_det_test_[classname],这个if等式永远无法相等,就算的AP和mAP都将是nan.
当然,不想该detector.c,也可以使用Python语句
obj['name'].replace(‘comp4_det_test_’,’’)
将comp4_det_test_去掉。
如果你的数据集类型个数不是80个,建议在validate_detector函数源码
int classes = l.classes;
后面增加
char *classesnum = option_find_str(options, "classes", "80");
classes = atoi(classesnum);
否者,在生成结果文件的过程中会出现“段错误”,这是因为根据源码:
if(!outfile) outfile = "comp4_det_test_";
fps = calloc(classes, sizeof(FILE *));
for(j = 0; j < classes; ++j){
snprintf(buff, 1024, "%s/%s%s.txt", prefix, outfile, names[j]);
fps[j] = fopen(buff, "w");
}
实际类型个数少,而class仍然按80计算,就会导致多出来的类型没有办法生成对应的文件。
def voc_eval(detpath,
annopath,
imagesetfile,
classname,
cachedir,
ovthresh=0.5,
use_07_metric=False):
中有多个参数,其中detpath是结果文件路径,在Python中设置问xxx/results/{}.txt。这个{}啥意思呢?因为在voc_eval中通过:
detfile = detpath.format(classname)
获得路径名,format(classname)用于根据classname这个字符串,对路径名进行填充。
annopath是标签文件路径,即Annotations文件夹中的xml文件,采用xxx/images_data/Annotations/{}.xml,和detpath设置是一个道理。
classname中存储的是存储验证集的文件名的文件路径,一般放在xxx/images_data/ImageSets/Main/文件夹下,这里的文件名就是将YOLO配置文件valia_data.txt中的路径和文件名后缀都去掉,如valia_data.txt中存储的是
app/cptest/images_data/JPEGImages/174_15890312979608698.jpg
在此文件中存储的就是
174_15890312979608698
注意,一定要一个文件名放一行。
classname是通过
class_name = sub_files[i].split(".txt")[0]
获得的,就是存储结果的文件名。这个class_name如果和文件名不一致,处理方法前面已经说过了。
cachedir就是缓存标签的路径,一般设置为‘.’,表示不设置
ovthresh为确定认为命中目标,针对class的置信度所使用的阈值,一般默认设置为0.5,可以根据实际情况进行设置。
use_07_metric表示是否使用VOC07的11点计算法,默认为Flase.
由于voc_eval是使用Python2编写的,当你使用Python3调用时候
(1)print ‘’的语法改为print()
(2)import cPickle改为import pickle
代码中cPickle.dump和cPickle.load进行相应修改
以上就是计算mAP会遇到的问题和解决办法。