实现原理
通过计算真实框和检测框的交并比,如果交并比大于阈值T,并且标签判断准确,即模型检测准确。
交并比的计算原理如下图所示。
代码运行条件
- 首先需要人工对测试样本,进行标记生成xml文件,作为模型评价的标准。
- 利用模型对测试集进行测试, 并生成xml文件。
xml文件的生成参考:https://blog.csdn.net/qq_42661919/article/details/122428259?spm=1001.2014.3001.5502
- 注意 要保证同一张图像的人工标定生成的xml文件和模型测试生成的xml文件名要保持一致(两个文件夹的文件名和文件数量也要相等)。
完整代码
import xml.etree.ElementTree as ET
import os
# 解析xml文件
def convert_annotation(full_file):
tree = ET.parse(full_file)
root = tree.getroot()
countBox = []
for obj in root.iter('object'):
labelName=obj.find('name').text
# print (labelName)
xmlbox = obj.find('bndbox')
b = [int(float(xmlbox.find('xmin').text)), int(float(xmlbox.find('ymin').text)),
int(float(xmlbox.find('xmax').text)), int(float(xmlbox.find('ymax').text)),labelName]
countBox.append(b)
return countBox
# 计算测试box和真实box的交并,利用阈值进行判定是否检测准确。
def computerPrecisionAndRecall(T,test_box, label_box):
# 代表检测 正确的数目
count = 0
labelsum = len(label_box)
testsum = len(test_box)
for i, _list1 in enumerate(label_box):
for j, _list2 in enumerate(test_box):
# 第一个框
#左上角横坐标
x1_1 = int(_list1[0])
#左上角纵坐标
y1_1 = int(_list1[1])
#右下角横坐标
x2_1 = int(_list1[2])
#右下角纵坐标
y2_1 = int(_list1[3])
s1 = (x2_1 - x1_1) * (y2_1 - y1_1)
# 第二个框
x1_2 = int(_list2[0])
y1_2 = int(_list2[1])
x2_2 = int(_list2[2])
y2_2 = int(_list2[3])
s2 = (x2_2 - x1_2) * (y2_2 - y1_2)
# 找相交部分
xmin = max(x1_1, x1_2)
ymin = max(y1_1, y1_2)
xmax = min(x2_1, x2_2)
ymax = min(y2_1, y2_2)
#计算交并比
IOU = (ymax - ymin) * (xmax - xmin) / min(s1, s2)
#此情况表示 未相交
if xmin >= xmax or ymin >= ymax:
continue
#判断交并大于阈值,并且标签判断正确,判定为检测正确。
elif IOU >= T and _list1[4]==_list2[4]:
text_box.remove(_list2)
count += 1
continue
return [labelsum, testsum, count]
if __name__ == "__main__":
#模型测试生成的xml文件的文件夹路径。
test_file=r"/home/yaoteam/yolov4-improve/testData/yolov5_xml"
#人工标定生成的xml文件的文件夹路径。
label_file=r"/home/yaoteam/yolov4-improve/testData/MaualLabel"
xml_names=os.listdir(test_file)
#标注总样本label_sum,测试总样本test_sum,检测到的总数目find_sum,精确率precision,召回率recall
label_sum=0
test_sum=0
find_sum=0
#交并比阈值T
T=0.6
for xml_name in xml_names:
text_xml_path = os.path.join(test_file,xml_name)
maual_labeling_path = os.path.join(label_file,xml_name)
text_box = convert_annotation(text_xml_path)
label_box = convert_annotation(maual_labeling_path)
label_item_sum, test_item_sum, find_item_sum = computerPrecisionAndRecall(T,text_box, label_box)
label_sum+=label_item_sum
test_sum+=test_item_sum
find_sum+=find_item_sum
precision=round((find_sum/test_sum)*100,2)
recall=round((find_sum/label_sum)*100,2)
print("正样本检测为正样本的数目:",find_sum)
print("人工标记的样本总数:",label_sum)
print ("模型检测到的正样本总数",test_sum)
print ("精确率:",precision,"%")
print ("召回率:",recall,"%")