yolov8自己的best.pt文件在代码中调用之后出现问题

yolov8对屏幕进行截图识别,用了网上找的代码,把里面的 yolov8n.pt换成自己训练的best.pt之后完全检测不准(替换之前可以检测官方预训练模型里面的东西,很准)。不知道是哪里出了问题。
我测试过输入图片和视频,都没有问题,权重文件是能用的,可就是这个循环截图程序检测不对东西。
求指点,谢谢!

这里是PRTSCR.py:

import cv2
import mss
import numpy as np

class PRTSCR:

  """

  parameters

  ----------

    screen_resolution : Tuple[int, int]

      屏幕宽高,分别为x,y

    capture_region : Tuple[float, float]

      实际截图范围,分别为x,y,(1.0, 1.0)表示全屏检测,越低检测范围越小(始终保持屏幕中心为中心)

    window_name : str

      显示窗口名

    exit_code : int

      结束窗口的退出键值,为键盘各键对应的ASCII码值,默认是ESC键

  """


  def __init__(self, screen_resolution=(2560, 1440), capture_region=(0.5, 0.5), window_name='test', exit_code=0x1B):

    self.screen_capture = mss.mss() # 实例化mss,并使用高效模式


    self.screen_width = screen_resolution[0] # 屏幕的宽

    self.screen_height = screen_resolution[1] # 屏幕的高


    self.capture_region = capture_region # 捕获区域


    self.screen_center_x, self.screen_center_y = self.screen_width // 2, self.screen_height // 2 # 屏幕中心点坐标


    # 截图区域

    self.capture_width, self.capture_height = int(self.screen_width * self.capture_region[0]), int(

      self.screen_height * self.capture_region[1]) # 宽高


    self.capture_left, self.capture_top = int(

      0 + self.screen_width // 2 * (1. - self.capture_region[0])), int(

      0 + self.screen_height // 2 * (1. - self.capture_region[1])) # 原点


    self.display_window_width, self.display_window_height = self.screen_width // 3, self.screen_height // 3 # 显示窗口大小


    self.monitor_settings = {

      'left': self.capture_left,

      'top': self.capture_top,

      'width': self.capture_width,

      'height': self.capture_height

    }


    self.window_name = window_name

    self.exit_code = exit_code

    self.img = None


  def grab_screen_mss(self, monitor=None):

    if monitor is None:

      monitor = self.monitor_settings

    # cap.grab截取图片,np.array将图片转为数组,cvtColor将BRGA转为BRG,去掉了透明通道

    return cv2.cvtColor(np.array(self.screen_capture.grab(monitor)), cv2.COLOR_BGRA2BGR)

下面是运行的程序forecast.py:

import cv2

import os

import numpy as np

from ultralytics import YOLO

from PIL import Image, ImageDraw, ImageFont

from PRTSCR import PRTSCR



def run(sc):

  # 实例化 YOLO 模型

  #model = YOLO("yolov8n.pt")
  model = YOLO("/home/sdcynic/yolov8/ultralytics-main/datasets/runs/detect/train5/weights/best.pt")
  # 设置字体
  fontStyle = ImageFont.truetype("/home/sdcynic/yolov8/ultralytics-main/datasets/font/simsun.ttc", 48, encoding="utf-8") # 中文字体文件


  # 循环体

  while True:

    # 截屏

    img = Image.fromarray(np.uint8(sc.grab_screen_mss()))

    # 实例化一个图像绘制对象

    draw = ImageDraw.Draw(img)

    # 利用模型进行图像预测

    results = model.predict(source=img, conf=0.25, iou=0.75)


    # 遍历结果,detection

    for result in results:

      # detection

      if len(result.boxes.xyxy) > 0:

        boxes_conf = np.array(result.boxes.conf.tolist())

        # 确定检测结果的数量

        boxes_conf_n = len(boxes_conf)

        if boxes_conf_n > 0:

          boxes_xyxy = result.boxes.xyxy.tolist()

          boxes_cls = result.boxes.cls.tolist()

          boxes_xy_center = []

          for i, box_xyxy in enumerate(boxes_xyxy):

            draw.rectangle(box_xyxy, outline=(0, 0, 255), width=5)

            class_label = str(int(boxes_cls[i]))#获取目标的类别标签

            draw.text((int(box_xyxy[0]), int(box_xyxy[1]) - 20), class_label, (0, 0, 255),font=fontStyle)


            boxes_xy_center.append((((box_xyxy[0] + box_xyxy[2]) / 2) + sc.capture_left,((box_xyxy[1] + box_xyxy[3]) / 2) + sc.capture_top))


    cv2.namedWindow(sc.window_name, cv2.WINDOW_NORMAL) # cv2.WINDOW_NORMAL 根据窗口大小设置图片大小

    cv2.resizeWindow(sc.window_name, sc.display_window_width, sc.display_window_height)

    cv2.imshow(sc.window_name, np.array(img))


    if cv2.waitKey(1) & 0XFF == sc.exit_code: # 默认:ESC

      cv2.destroyAllWindows()

      os._exit(0)




if __name__ == '__main__':

  sc = PRTSCR(capture_region=(0.5, 0.5))

  run(sc)


修改一下 通道转换模式就可以了。 感谢。


  return cv2.cvtColor(np.array(self.screen_capture.grab(monitor)), cv2.COLOR_BGRA2RGB)

检查权重文件路径:确保自己训练的权重文件 best.pt 的路径是正确的。您可以使用绝对路径或相对路径,但需要确保路径是正确的。

回答部分参考、引用ChatGpt以便为您提供更准确的答案:

根据提供的代码,你替换了原来的yolov8n.pt权重文件为自己训练的best.pt文件,但是在循环截图程序中发现检测结果不准确。可能的原因有以下几点:

  1. 版本不匹配:你使用的是YOLOv8模型,但是训练和测试使用的库和代码中并没有明确的版本信息。确保训练和测试环境中使用的版本是一致的,包括YOLO的版本和相关的依赖库版本。
  2. 训练数据不足:自己训练的best.pt权重文件可能在训练数据量不足的情况下产生过拟合现象。如果训练数据量较小,模型可能无法充分学习到目标的特征,导致检测不准确。尝试增加训练数据量或使用数据增强技术来改善模型的泛化能力。
  3. 参数设置不准确:在代码中,你使用了固定的置信度阈值和IOU阈值进行预测结果的筛选,分别为0.25和0.75。这些阈值的选择可能不适合你的数据集和应用场景。尝试调整这些阈值,找到适合你数据集的最佳阈值,以获得更准确的检测结果。
  4. 图像预处理不准确:在代码中,你使用grab_screen_mss()函数进行截图,然后将截图转换为PILImage对象进行预测。确保截图和预处理的过程没有引入错误,例如图像的大小、颜色通道等是否与模型训练时的输入数据一致。

综上所述,你可以检查以上几个方面,包括版本匹配、训练数据量、参数设置和图像预处理等,来解决你的问题。如果仍然无法解决,建议逐步调试和排查代码,查看是否有其他错误或问题影响了检测结果的准确性。

这几个方向你一一排查一下:
1.即使是自己训练出的权重文件,在训练过程中也可能出现过拟合或欠拟合等问题,导致最终的模型参数效果不如官方预训练模型。可以尝试重新训练模型,或者使用其他的预训练权重文件。
2.如果你用的是官方提供的 YOLOv8 模型,而自己训练的权重文件是基于另一个网络结构训练的,那么就会造成网络结构与权重文件不匹配的问题,需要确保网络结构和权重文件是相匹配的。
3.测试数据集与训练数据集不一致。如果你用的测试数据集和训练数据集有很大的差异,那么训练出来的模型就可能无法正确识别测试数据集中的目标物体,并导致检测不准确。
4.调整模型的阈值参数。YOLO 模型使用置信度阈值来确定识别结果是否正确,如果阈值设置太高,可能会导致部分正确的结果被误判为错误。你可以尝试调低阈值参数进行测试。
5.确认目标类别是否正确。在自己训练的模型中,可能会使用和官方预训练模型不同的目标类别,例如自己训练的模型可能有更多或更少的类别。你需要确认自己训练的模型中包含的目标类别是否与测试时的实际类别相符。
6.检查模型训练时的数据集是否充足和标注是否正确。如果训练数据集过小或标注不正确,可能会导致模型无法正确识别。
7.根据具体情况进一步排查问题。你可以尝试在推理时输出模型的中间结果,例如特征图等,以便更深入地了解问题所在。同时,你也可以参考其他识别准确率相对较高的代码,尝试对比分析问题所在。

从题主的描述来看,能够运行只是结果不对的话,这个时候可能的问题为:
(1) 自己训练的模型后处理层参数是否和官方的一致,比如nms阈值等设置是否一样,甚至后处理层是否 一样?
(2) 模型训练时候图像处理超参和预测时候使用的参数是否一样,通常 均值和std 不一样,容易导致效果较差
(3) 图像预处理流程是否一样,比如resizing 的方式等等
(4) 其它可能问题,比如版本问题等
可以从上述几个方面尝试区核对排查,通常都能解决

opencv python截图功能的实现方法


import cv2
import numpy as np
import matplotlib.pyplot as plt
i = w = h = f1 = f2 = ew = eh = 0

def cut(event, x, y, flags, param):
  global i,w,h, f1,f2,ew,eh
  img = 0
  #这一个if的作用是,当鼠标左键按下,记录开始的位置
  if event == cv2.EVENT_LBUTTONDOWN:
    f1 = 1
    h = x
    w = y
    print("w = ", w, "h = ", h)
  #这一步的作用是当鼠标滑动时,并且左键是按下的时候,就画一个框框,并且记录左后一个位置
  if event == cv2.EVENT_MOUSEMOVE and flags == cv2.EVENT_FLAG_LBUTTON:
    img = frame.copy()
    cv2.rectangle(img, (h,w), (x,y), (255,0,0),5)
    cv2.imshow("frame", img)
    f2 = 1
    eh = x
    ew = y
  #当执行了以上的两步时候,并且左键是松开的,就可以进行截出一张图片。
  if f1 == 1 and f2 == 1 and event == cv2.EVENT_LBUTTONUP:
    #下面两个if是向各个方向上截图的考虑
    if ew < w:
      w,ew = ew,w
    if eh < h:
      eh,h = h, eh
    i += 1
    f1 = f2 = 0
    img = frame[w:ew, h:eh]
    path = "C:/test2/" + "%d"%i+".jpg"
    cv2.imwrite(path,img)
#这时创建一个对像
cap = cv2.VideoCapture("C:/test2/bbb.mp4")
#这是命名一个窗口,与下面的鼠标结合,鼠标会在这个窗口中产生效果
cv2.namedWindow("frame",cv2.WINDOW_NORMAL)
cv2.setMouseCallback("frame",cut)
while True:
 #读取图片
  ret, frame = cap.read()
  if ret == False:
    break
  cv2.imshow("frame", frame)
  #如果输入'c',就进行切割。
  if cv2.waitKey(10) == ord("c"):
    cv2.waitKey(0)
  if cv2.waitKey(10) == ord('q'):
    break

关于这个问题,可能有以下几个原因导致检测不准:

  1. best.pt权重文件可能没有和您的配置文件匹配,导致模型结构和参数不一致。您可以尝试在检测时同时指定您的权重文件和配置文件,例如:
    detect.py --source 0 --weights your_weights.pt --cfg your_config.yaml

  2. best.pt权重文件可能没有收敛到最佳状态,导致模型泛化能力不足。您可以尝试继续训练您的模型,或者调整一些超参数,例如学习率、批量大小、数据增强等。

  3. 数据集可能没有足够的多样性或者质量,导致模型在屏幕截图上表现不佳。您可以尝试增加一些与屏幕截图相似的数据,或者对数据进行清洗和标注。

  4. 屏幕截图可能有一些噪声或者变形,导致模型无法正确识别目标。您可以尝试调整一下您的截图区域、分辨率、色彩等参数。