可视化步骤
- 一、生成自定义权重对图片的预测类别坐标信息
 - 二、创建需要预测的文件夹
 - 三、可视化运行
 
一、生成自定义权重对图片的预测类别坐标信息
新建脚本文件/path/to/your/ultralytics/savetxt.py放入对应参数运行会得到一个个独立的/path/to/your/runs/detect/output/output1/labels坐标信息文件夹
请注意这是使用Ultralytics封装的脚本文件
from ultralytics import YOLO  
model = YOLO("/path/to/your/weights/best.pt")
model.predict(source="/path/to/your/test/image.jpg",conf=0.45, save=True,save_conf=True,save_txt=True,name='output') 
 
source后为要预测的图片数据集的的路径save=True为保存预测结果save_conf=True为保存坐标信息conf=0.45为目标置信区间是0.45save_txt=True为保存txt结果,但是当图片中预测不到任何物体时,不产生txt文件
二、创建需要预测的文件夹
注意一定要是文件夹(directory)
 且文件夹内图片数量和名称全部一一对应
- 被预测的图片文件夹:
/path/to/your/directory/images - 真实类别坐标信息文件夹:
/path/to/your/directory/labels - 预测类别坐标信息文件夹:
/path/to/your/directory/predict_labels 
将挑选的被预测图片放入第一个文件夹
 将步骤一生成的类别坐标信息放入第二个文件夹
 将被预测图片对应真实的类别坐标信息放入第三个文件
...
├── directory
│   ├── images
│   │   ├── 0000087_01140_d_0000004.jpg
│   │   ├── ...
│   ├── labels
│   │   ├── 0000087_01140_d_0000004.txt
│   │   ├── ...
│   ├── predict_labels
│   │   ├── 0000087_01140_d_0000004.txt
│   │   ├── ...
 
三、可视化运行
新建/path/to/your/detect.py填写下述代码
 再建立一个可视化结果输出文件夹/path/to/your/vis/
import os
import cv2
import tqdm
import shutil
import numpy as np
 
def xywh2xyxy(box):
    box[:, 0] = box[:, 0] - box[:, 2] / 2
    box[:, 1] = box[:, 1] - box[:, 3] / 2
    box[:, 2] = box[:, 0] + box[:, 2]
    box[:, 3] = box[:, 1] + box[:, 3]
    return box
 
def iou(box1, box2):
    x11, y11, x12, y12 = np.split(box1, 4, axis=1)
    x21, y21, x22, y22 = np.split(box2, 4, axis=1)
 
    xa = np.maximum(x11, np.transpose(x21))
    xb = np.minimum(x12, np.transpose(x22))
    ya = np.maximum(y11, np.transpose(y21))
    yb = np.minimum(y12, np.transpose(y22))
 
    area_inter = np.maximum(0, (xb - xa + 1)) * np.maximum(0, (yb - ya + 1))
 
    area_1 = (x12 - x11 + 1) * (y12 - y11 + 1)
    area_2 = (x22 - x21 + 1) * (y22 - y21 + 1)
    area_union = area_1 + np.transpose(area_2) - area_inter
 
    iou = area_inter / area_union
    return iou
 
def draw_box(img, box, color):
    cv2.rectangle(img, (int(box[0]), int(box[1])), (int(box[2]), int(box[3])), color, thickness=2) 
    # thickness设置检测框粗细
    return img
 
if __name__ == '__main__':
    postfixes = ['jpg', 'JPG']  # 定义要处理的后缀列表
    img_path = '/path/to/your/directory/images/0000087_01140_d_0000004.jpg'
    label_path = '/path/to/your/directory/labels/0000087_01140_d_0000004.txt'
    predict_path = '/path/to/your/directory/predict_labels/0000087_01140_d_0000004.txt'
    save_path = '/path/to/your/vis/' # 可视化结果保存的文件夹目录
    classes = ['pedestrian', 'people', 'bicycle', 'car'] # 你的自定义数据集类别
    detect_color, missing_color, error_color  = (0, 255, 0), (0, 0, 255), (255, 0, 0)#(g,b,r)# 不同检测结果下检测框颜色设置
    iou_threshold = 0.45 # 与步骤一的conf保持一致
    
    if os.path.exists(save_path):
        shutil.rmtree(save_path)
    os.makedirs(save_path, exist_ok=True)
 
    all_right_num, all_missing_num, all_error_num = 0, 0, 0
    with open('result.txt', 'w') as f_w:
        for filename in tqdm.tqdm(os.listdir(img_path)):
            postfix = filename.split('.')[-1]  # 获取文件名后缀
            if postfix.lower() in postfixes:  # 判断后缀是否在指定列表中
                image = cv2.imread(os.path.join(img_path, filename))
                if image is None:
                    print(f'image:{os.path.join(img_path, filename)} not found.', file=f_w)
                    continue
                h, w = image.shape[:2]
 
                path = filename[:-4]  # 去除文件后缀
 
                try:
                    with open(f'{predict_path}/{path}.txt') as f:
                        pred = np.array(list(map(lambda x:np.array(x.strip().split(), dtype=np.float32), f.readlines())))
                        pred[:, 1:5] = xywh2xyxy(pred[:, 1:5])
                        pred[:, [1, 3]] *= w
                        pred[:, [2, 4]] *= h
                        pred = list(pred)
                except:
                    pred = []
 
                try:
                    with open(f'{label_path}/{path}.txt') as f:
                        label = np.array(list(map(lambda x:np.array(x.strip().split(), dtype=np.float32), f.readlines())))
                        label[:, 1:] = xywh2xyxy(label[:, 1:])
                        label[:, [1, 3]] *= w
                        label[:, [2, 4]] *= h
                except:
                    print(f'label path:{label_path}/{path}.txt (not found or no target).', file=f_w)
 
                right_num, missing_num, error_num = 0, 0, 0
                label_id, pred_id = list(range(label.shape[0])), [] if len(pred) == 0 else list(range(len(pred)))
                for i in range(label.shape[0]):
                    if len(pred) == 0: break
                    ious = iou(label[i:i+1, 1:], np.array(pred)[:, 1:5])[0]
                    ious_argsort = ious.argsort()[::-1]
                    missing = True
                    for j in ious_argsort:
                        if ious[j] < iou_threshold: break
                        if label[i, 0] == pred[j][0]:
                            image = draw_box(image, pred[j][1:5], detect_color)
                            pred.pop(j)
                            missing = False
                            right_num += 1
                            break
 
                    if missing:
                        image = draw_box(image, label[i][1:5], missing_color)
                        missing_num += 1
 
                if len(pred):
                    for j in range(len(pred)):
                        image = draw_box(image, pred[j][1:5], error_color)
                        error_num += 1
 
                all_right_num, all_missing_num, all_error_num = all_right_num + right_num, all_missing_num + missing_num, all_error_num + error_num
                cv2.imwrite(f'{save_path}/{path}.{postfix}', image)
                print(f'name:{path} right:{right_num} missing:{missing_num} error:{error_num}', file=f_w)
        print(f'all_result: right:{all_right_num} missing:{all_missing_num} error:{all_error_num}', file=f_w)
 
总结起来需要自定义修改的地方如下
def draw_box(img, box, color):
    cv2.rectangle(img, (int(box[0]), int(box[1])), (int(box[2]), int(box[3])), color, thickness=2)
    # thickness设置检测框粗细
    return img
    
postfixes = ['jpg', 'JPG']  # 定义要处理的后缀列表
img_path = '/path/to/your/directory/images/0000087_01140_d_0000004.jpg'
label_path = '/path/to/your/directory/labels/0000087_01140_d_0000004.txt'
predict_path = '/path/to/your/directory/predict_labels/0000087_01140_d_0000004.txt'
save_path = '/path/to/your/vis/' # 可视化结果保存的文件夹目录
classes = ['pedestrian', 'people', 'bicycle', 'car'] # 你的自定义数据集类别
detect_color, missing_color, error_color  = (0, 255, 0), (0, 0, 255), (255, 0, 0)#(g,b,r)# 不同检测结果下检测框颜色设置
iou_threshold = 0.45 # 与步骤一的conf保持一致
 
不同颜色检测框代表的模型权重对于预测图片的检测情况
- 绿色:真正例(TP),指检测到的目标与实际目标之间的匹配,这意味着检测到的目标在位置和类别上都与实际目标匹配,即正确检出;
 - 蓝色:假正例(FP),指模型错误地将负例(非目标)样本预测为正例(目标),即误检;
 - 红色:假负例(FN),指模型未能检测到实际存在的目标,即漏检。
 
最终生成的图片位于:/path/to/your/vis/0000087_01140_d_0000004.jpg




















