版权声明:希望我的博客可以为别人带去知识与便利,让那些像我曾经一样迷茫的小伙伴不再迷茫~ https://blog.csdn.net/qq_34374664/article/details/81395159
get_para.py
# coding-utf-8
import IoU
# 本模块获取参数,网上规则众多,这里采用https://blog.csdn.net/qq_34374664/article/details/81368316的方法,他是翻译FDDB的官方文档
# 此函数获得对应阈值的TP,FP,TT
def get_para(threshold, iou_threshold = 0.3):
#gt = open('/home/kk17/PythonProject/dataset/FDDB/ellipseList.txt', 'r')
#dt = open('/home/kk17/PythonProject/dataset/FDDB/results.txt', 'r')
gt = open('ellipseList.txt', 'r')
dt = open('results.txt', 'r')
# print(dt)
dt_page = dt.readlines()
dt_page_len = len(dt_page)
gt_page = gt.readlines()
# gt_page_len = len(gt_page)
dt_i = 0
gt_i = 0
tp = 0
fp = 0
tt = 0 # 代表真实值就是1的样本数量
while dt_i < dt_page_len:
# print(gt_page[gt_i])
# input()
gt_string_len = len(gt_page[gt_i])
# print(gt_string_len)
if gt_string_len < 11: # ///
continue
if (gt_page[gt_i][0] == '2') & (gt_page[gt_i][1] == '0') & (gt_page[gt_i][2] == '0') & (
(gt_page[gt_i][3] == '2') | (gt_page[gt_i][3] == '3')):
gt_i = gt_i + 1
gt_face_num = int(gt_page[gt_i].split('\n')[0])
tt = tt + gt_face_num
# gt_i = gt_i + gt_face_num + 1 # 移动gt列表的下标
# print(gt_face_num)
if gt_face_num == 0:
gt_i = gt_i + 1
continue
dt_string_len = len(dt_page[dt_i])
if dt_string_len < 11: # 要加上长度判断 如果遇到是脸的个数,那样会小于4,所以下面代码会产生越界,python判断语句好像不能false直接退出
continue # ///
if (dt_page[dt_i][0] == '2') & (dt_page[dt_i][1] == '0') & (dt_page[dt_i][2] == '0') & ((dt_page[dt_i][3] == '2') | (dt_page[dt_i][3] == '3')):
dt_i = dt_i + 1
dt_face_num = int(dt_page[dt_i].split('\n')[0])
# dt_i = dt_i + dt_face_num + 1 # 移动dt列表的下标
# print(face_num)
if dt_face_num == 0: # ///
dt_i = dt_i + 1
gt_i = gt_i + gt_face_num + 1
continue
for di in range(1, dt_face_num+1):
dt_rectangle = dt_page[dt_i+di].split('\n')[0]
dt_rectangle = dt_rectangle.split(' ')
# print(dt_rectangle)
for gi in range(1, gt_face_num + 1):
gt_ellipse = gt_page[gt_i+gi].split('\n')[0]
gt_ellipse = gt_ellipse.split(' ')
iou = IoU.iou(float(dt_rectangle[0]), float(dt_rectangle[1]), float(dt_rectangle[2]), float(dt_rectangle[3]), float(gt_ellipse[0]),
float(gt_ellipse[1]), float(gt_ellipse[2]), float(gt_ellipse[3]), float(gt_ellipse[4]))
if iou >= iou_threshold:
if float(dt_rectangle[4]) >= threshold:
tp = tp + 1
if iou < iou_threshold:
if float(dt_rectangle[4]) >= threshold:
fp = fp + 1
gt_i = gt_i + gt_face_num + 1
dt_i = dt_i + dt_face_num + 1
return tp, fp, tt
draw_cure.py
# coding-utf-8
import numpy as np
import get_para
import matplotlib.pyplot as plt
def draw_roc():
tpr = []
fp = []
for threshold in np.arange(0, 1, 0.02):
para = get_para.get_para(threshold)
tpr.append(para[0] / para[2])
fp.append(para[1])
print(para)
plt.plot(fp, tpr)
plt.show()
draw_roc()
IoU.py
# coding-utf-8
# 将椭圆转换成与坐标轴平行的矩形,具体规则是椭圆的中心也是矩形的中心,矩形的长对应着椭圆长的两倍,同理宽
# ps:本应考虑角度从而更准确的画出矩形框,但是因为角度都是-2,2,不是很理解,暂时没有加入这个步骤
def ellipse_to_rectangle(major_axis_radius, minor_axis_radius, angle, center_x, center_y):
rectangle = [center_x + minor_axis_radius, center_y + major_axis_radius, minor_axis_radius * 2, major_axis_radius * 2] # 左上角x,y,长宽
return rectangle
# 计算IoU与转换函数封装在一起, 这里可以用数组,为了体现逻辑关系以及变量意义直接变量,并且就两个图形,变量不会太多
def iou(detection_x, detection_y, detection_w, detection_h, major_axis_radius, minor_axis_radius,
angle, center_x, center_y):
gt_x, gt_y, gt_w, gt_h = ellipse_to_rectangle(major_axis_radius, minor_axis_radius, angle, center_x, center_y)
two_rectangle_x = [gt_x, gt_x+gt_w, detection_x, detection_x+detection_w] # 对角线上的坐标
two_rectangle_y = [gt_y, gt_y-gt_h, detection_y, detection_y-detection_h]
two_rectangle_x.sort() # 排序
two_rectangle_y.sort()
if (two_rectangle_y[3] - two_rectangle_y[0] >= gt_h+detection_h) | (two_rectangle_x[3] - two_rectangle_x[0] >= gt_w + detection_w):
return 0
Intersection = (two_rectangle_x[2] - two_rectangle_x[1]) * (two_rectangle_y[2] - two_rectangle_y[1])
Union = gt_w*gt_h + detection_w*detection_h - Intersection
return Intersection / Union