如何基于YOLOv8已检测的目标区域实现二次类别检测?
如何基于YOLOv8已检测的目标区域实现二次类别检测?
嘿,我完全懂你的需求——先定位到第一个目标,再在它的范围内做二次检测对吧?其实这个思路特别直接,核心就是把第一次检测出的目标区域从原图里抠出来,把这个裁剪后的小图像当成新的输入,传给检测模型(可以是同一个模型的其他类别,也可以是专门训练的第二个模型)就行。下面给你一步步拆解实操方法:
第一步:从原图中裁剪出已检测到的目标区域
你已经通过YOLOv8拿到了目标的坐标cords(格式是[x1, y1, x2, y2]),接下来只要用这个坐标从原图像里把对应区域切出来就行。这里要注意OpenCV的图像格式是(高, 宽, 通道),所以切片的时候要对应成[y1:y2, x1:x2]。
第二步:对裁剪后的区域执行二次检测
拿到裁剪后的小图后,就可以像第一次检测那样,用YOLOv8加载模型(如果是检测另一个类,要么用包含该类的模型,要么用专门训练的第二个模型),然后对小图做预测就行。
给你修改后的完整代码示例
我把你的代码做了扩展,加入了二次检测的逻辑,你可以根据自己的实际情况调整:
import cv2 from ultralytics import YOLO # 加载第一次检测的模型(检测myclassname的模型) primary_model = YOLO('runs/detect/train4/weights/best.pt') # 加载二次检测的模型——如果是同一个模型包含第二个类,就用上面的primary_model;如果是单独训练的,就换路径 secondary_model = YOLO('runs/detect/train_second_class/weights/best.pt') # 替换成你的二次检测模型路径 # 读取原图 image = cv2.imread("screenshot.png") # 第一次检测:定位目标区域 results = primary_model.predict(image, show=False, stream=True, classes=0, imgsz=512) for result in results: for box in result.boxes: class_id = result.names[box.cls[0].item()] if class_id == "myclassname": cords = box.xyxy[0].tolist() cords = [round(x) for x in cords] x1, y1, x2, y2 = cords print("第一次检测结果:") print("Object type:", class_id) print("Coordinates:", cords) print("Probability:", round(box.conf[0].item(), 2)) print("---") # 裁剪目标区域:注意OpenCV的图像维度是(y, x, channel) # 先确保坐标在图像范围内,避免索引越界 x1 = max(0, x1) y1 = max(0, y1) x2 = min(image.shape[1], x2) y2 = min(image.shape[0], y2) cropped_region = image[y1:y2, x1:x2] # 对裁剪后的区域做二次检测 print("开始二次检测...") secondary_results = secondary_model.predict(cropped_region, show=True, imgsz=512) # 如果是用同一个模型检测其他类,可以指定classes参数,比如classes=1(假设第二个类的id是1) # secondary_results = primary_model.predict(cropped_region, show=True, imgsz=512, classes=1) for sec_result in secondary_results: for sec_box in sec_result.boxes: sec_class_id = sec_result.names[sec_box.cls[0].item()] sec_cords = sec_box.xyxy[0].tolist() sec_cords = [round(x) for x in sec_cords] sec_conf = round(sec_box.conf[0].item(), 2) print("二次检测结果:") print("Object type:", sec_class_id) print("Coordinates(相对于裁剪区域):", sec_cords) print("Probability:", sec_conf) print("---")
一些注意事项
- 如果你的两个类别是在同一个YOLO模型里训练的,那不需要加载第二个模型,只要在二次检测的时候调整
classes参数,指定你要检测的第二个类的ID就行。 - 裁剪区域的时候一定要做坐标边界检查(
max(0, x1)和min(image.shape[1], x2)),避免因为目标靠近图像边缘导致索引越界报错。 - 如果二次检测的目标很小,可以适当调整
imgsz参数,让模型更精准地识别小目标。
备注:内容来源于stack exchange,提问作者GN Chishti
相关产品推荐
相关产品推荐

