File size: 4,084 Bytes
71e7eab
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
import gradio as gr
import cv2
import numpy as np
import os
import tempfile
from ultralytics import YOLO

# 加载YOLOv8模型
model_path = "docgenome_object_detection_yolov8.pt"
model = YOLO(model_path)

def detect_and_visualize(image):
    """
    对上传的图像进行目标检测并可视化结果
    
    Args:
        image: 上传的图像
        
    Returns:
        annotated_image: 带有检测框的图像
        yolo_annotations: YOLO格式的标注内容
    """
    # 运行检测
    results = model(image)
    
    # 获取第一帧的结果
    result = results[0]
    
    # 创建图像副本用于可视化
    annotated_image = image.copy()
    
    # 准备YOLO格式的标注内容
    yolo_annotations = []
    
    # 获取图像尺寸
    img_height, img_width = image.shape[:2]
    
    # 在原图上绘制检测结果
    for box in result.boxes:
        # 获取边界框坐标
        x1, y1, x2, y2 = box.xyxy[0].cpu().numpy()
        x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2)
        
        # 获取置信度
        conf = float(box.conf[0])
        
        # 获取类别ID和名称
        cls_id = int(box.cls[0])
        cls_name = result.names[cls_id]
        
        # 为每个类别生成不同的颜色
        color = tuple(np.random.randint(0, 255, 3).tolist())
        
        # 绘制边界框
        cv2.rectangle(annotated_image, (x1, y1), (x2, y2), color, 2)
        
        # 准备标签文本
        label = f'{cls_name} {conf:.2f}'
        
        # 计算标签大小
        (label_width, label_height), _ = cv2.getTextSize(label, cv2.FONT_HERSHEY_SIMPLEX, 0.5, 1)
        
        # 绘制标签背景
        cv2.rectangle(annotated_image, (x1, y1-label_height-5), (x1+label_width, y1), color, -1)
        
        # 绘制标签文本
        cv2.putText(annotated_image, label, (x1, y1-5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1)
        
        # 转换为YOLO格式 (x_center, y_center, width, height) 归一化到0-1
        x_center = (x1 + x2) / (2 * img_width)
        y_center = (y1 + y2) / (2 * img_height)
        width = (x2 - x1) / img_width
        height = (y2 - y1) / img_height
        
        # 添加到YOLO标注列表
        yolo_annotations.append(f"{cls_id} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}")
    
    # 将YOLO标注转换为字符串
    yolo_annotations_str = "\n".join(yolo_annotations)
    
    return annotated_image, yolo_annotations_str

def save_yolo_annotations(yolo_annotations_str):
    """
    保存YOLO标注到临时文件并返回文件路径
    
    Args:
        yolo_annotations_str: YOLO格式的标注字符串
        
    Returns:
        file_path: 保存的标注文件路径
    """
    # 创建临时文件
    temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".txt")
    temp_file_path = temp_file.name
    
    # 写入标注内容
    with open(temp_file_path, "w") as f:
        f.write(yolo_annotations_str)
    
    return temp_file_path

# 创建Gradio界面
with gr.Blocks(title="YOLOv8目标检测可视化") as demo:
    gr.Markdown("# YOLOv8目标检测可视化")
    gr.Markdown("上传图像,使用YOLOv8模型进行目标检测,并下载YOLO格式的标注。")
    
    with gr.Row():
        with gr.Column():
            input_image = gr.Image(label="上传图像", type="numpy")
            detect_btn = gr.Button("开始检测")
        
        with gr.Column():
            output_image = gr.Image(label="检测结果")
            yolo_annotations = gr.Textbox(label="YOLO标注", lines=10)
            download_btn = gr.Button("下载YOLO标注")
            download_file = gr.File(label="下载文件")
    
    # 设置点击事件
    detect_btn.click(
        fn=detect_and_visualize,
        inputs=[input_image],
        outputs=[output_image, yolo_annotations]
    )
    
    download_btn.click(
        fn=save_yolo_annotations,
        inputs=[yolo_annotations],
        outputs=[download_file]
    )

# 启动应用
if __name__ == "__main__":
    demo.launch()