UnstoppableCurry / ncnn-android-yolov8-seg-Seal

yolov8-seg Detect and identify various types of seals (yolov8 实现 印章检测)
9 stars 7 forks source link

yolov8-seg 自制pt转onnx(之后会转ncnn)时出现的模型问题 #2

Open zhouqingf opened 6 months ago

UnstoppableCurry commented 6 months ago

zhouqingf commented 6 months ago

我目前遇到一个问题,使用官方的yolov8-seg.pt转的onnx 能够使用您的代码 ,但使用自己的pt无法实现,我预计是onnx转换的问题

UnstoppableCurry commented 6 months ago

看 readme 里的 转换教程

zhouqingf commented 6 months ago

微信图片编辑_20240306123800 此图片是使用官方pt转换的,是能够运行

UnstoppableCurry commented 6 months ago

https://github.com/Digital2Slave/ncnn-android-yolov8-seg/wiki/Convert-yolov8-model-to-ncnn-model

UnstoppableCurry commented 6 months ago

我这个是 seg 的不是检测的

zhouqingf commented 6 months ago

但是自己的训练的模型就无法,我检测到自己pt转换之后的ONNX与官方的有明显的区别 微信截图_20240306123833

UnstoppableCurry commented 6 months ago

上面哪个链接改了没, 链接里 算子的顺序 shape 是需要改动的,然后 类别数量要再代码里改

zhouqingf commented 6 months ago

我把刚才的代码重新整理了一下 import torch from ultralytics import YOLO from ultralytics.nn.modules.block import C2f from ultralytics.nn.modules.head import Detect, Segment

from ultralytics.utils.tal import make_anchors

def forward1(self, x): x = self.cv1(x) x = [x, x[:, self.c:, ...]] x.extend(m(x[-1]) for m in self.m) x.pop(1) print("asfasf1111") return self.cv2(torch.cat(x, 1))

C2f.forward = forward1

def forward2(self, x): print("fasfsafasf2222222222222222asf") shape = x[0].shape # BCHW for i in range(self.nl): x[i] = torch.cat((self.cv2i, self.cv3i), 1) if self.training: return x elif self.dynamic or self.shape != shape: self.anchors, self.strides = (x.transpose(0, 1) for x in make_anchors(x, self.stride, 0.5)) self.shape = shape x_cat = torch.cat([xi.view(shape[0], self.no, -1) for xi in x], 2) return x_cat

Detect.forward = forward2

def forward3(self, x): p = self.proto(x[0]) # mask protos bs = p.shape[0] # batch size

mc = torch.cat([self.cv4[i](x[i]).view(bs, self.nm, -1) for i in range(self.nl)], 2)  # mask coefficients
x = self.detect(self, x)
if self.training:
    return x, mc, p

print("fasfsafasf3333333333333asf")
return (torch.cat([x, mc], 1).permute(0, 2, 1), p.view(bs, self.nm, -1)) if self.export else (
    torch.cat([x[0], mc], 1), (x[1], mc, p))

Segment.forward = forward3

model = YOLO('best.pt')

success = model.export(format="onnx", opset=12, imgsz=640)

zhouqingf commented 6 months ago

在转换onnx时,使用自己训练的pt文件,Detect.forward是没有被调用,而使用官方的pt文件转化时,Detect.forward是被调用了的

UnstoppableCurry commented 6 months ago

https://github.com/UnstoppableCurry/ncnn-android-yolov8-seg-Seal/blob/master/app/src/main/jni/yolo.cpp 类别数量对齐你自定义的模型 static void generate_proposals(std::vector grid_strides, const ncnn::Mat& pred, float prob_threshold, std::vector& objects) { const int num_points = grid_strides.size(); const int num_class = 11; const int reg_max_1 = 16;

int Yolo::draw(cv::Mat& rgb, const std::vector& objects) { // static const char* class_names[] = { // "person", "bicycle", "car", "motorcycle", "airplane", "bus", "train", "truck", "boat", "traffic light", // "fire hydrant", "stop sign", "parking meter", "bench", "bird", "cat", "dog", "horse", "sheep", "cow", // "elephant", "bear", "zebra", "giraffe", "backpack", "umbrella", "handbag", "tie", "suitcase", "frisbee", // "skis", "snowboard", "sports ball", "kite", "baseball bat", "baseball glove", "skateboard", "surfboard", // "tennis racket", "bottle", "wine glass", "cup", "fork", "knife", "spoon", "bowl", "banana", "apple", // "sandwich", "orange", "broccoli", "carrot", "hot dog", "pizza", "donut", "cake", "chair", "couch", // "potted plant", "bed", "dining table", "toilet", "tv", "laptop", "mouse", "remote", "keyboard", "cell phone", // "microwave", "oven", "toaster", "sink", "refrigerator", "book", "clock", "vase", "scissors", "teddy bear", // "hair drier", "toothbrush" // };

static const char* class_names[] = {
      "Static Circle Seal",
      "Dynamic 1 Triangle Seal",
      "Dynamic 1 Circle Seal",
      "Dynamic 2 Circle Seal",
      "Dynamic 1 Elliptical Seal",
      "Dynamic 1 Square Seal",
      "Dynamic 2 Square Seal",
      "Static Elliptical Seal",
      "Dynamic Lozenge Seal",
      "Static Square Seal",
      "Dynamic 2 Triangle Seal",
};

// static const char* class_names[] = {"blur", "phone", "reflectLight", "reflection"}; static const unsigned char colors[12][3] = { {56, 0, 255}, {226, 255, 0}, {0, 94, 255}, {0, 37, 255}, {0, 255, 94}, {255, 226, 0}, {0, 18, 255}, {255, 151, 0}, {170, 0, 255}, {0, 255, 56}, {255, 0, 75}, {0, 75, 255},

};
UnstoppableCurry commented 6 months ago

模型 和配置文件发上来,我试试

zhouqingf commented 6 months ago

我再重新训练一下

zhouqingf commented 6 months ago
zhouqingf commented 6 months ago

刚刚在原来的电脑上训练的, 11

UnstoppableCurry commented 6 months ago

你的pt label 字典4个类 但是配置文件80个,我 这eport 也不成功 正在debug 同版本的u train 和export 应该是一致的

UnstoppableCurry commented 6 months ago

from ultralytics import YOLO

model_big = YOLO(r'E:\workspace\pycharm\yolo\原版\ultralytics-main\runs\segment\mod\yolov8-seg.yaml').load(

r'E:\workspace\pycharm\yolo\原版\ultralytics-main\runs\segment\mod\last.pt')

success = model_big.export(format="onnx", opset=12, simplify=True) RUN E:\workspace\pycharm\v8env\Scripts\python.exe E:/workspace/pycharm/yolo/原版/ultralytics-main/1.py WARNING no model scale passed. Assuming scale='n'.

               from  n    params  module                                       arguments                     

0 -1 1 464 ultralytics.nn.modules.conv.Conv [3, 16, 3, 2]
1 -1 1 4672 ultralytics.nn.modules.conv.Conv [16, 32, 3, 2]
2 -1 1 7360 ultralytics.nn.modules.block.C2f [32, 32, 1, True]
3 -1 1 18560 ultralytics.nn.modules.conv.Conv [32, 64, 3, 2]
4 -1 2 49664 ultralytics.nn.modules.block.C2f [64, 64, 2, True]
5 -1 1 73984 ultralytics.nn.modules.conv.Conv [64, 128, 3, 2]
6 -1 2 197632 ultralytics.nn.modules.block.C2f [128, 128, 2, True]
7 -1 1 295424 ultralytics.nn.modules.conv.Conv [128, 256, 3, 2]
8 -1 1 460288 ultralytics.nn.modules.block.C2f [256, 256, 1, True]
9 -1 1 164608 ultralytics.nn.modules.block.SPPF [256, 256, 5]
10 -1 1 0 torch.nn.modules.upsampling.Upsample [None, 2, 'nearest']
11 [-1, 6] 1 0 ultralytics.nn.modules.conv.Concat [1]
12 -1 1 148224 ultralytics.nn.modules.block.C2f [384, 128, 1]
13 -1 1 0 torch.nn.modules.upsampling.Upsample [None, 2, 'nearest']
14 [-1, 4] 1 0 ultralytics.nn.modules.conv.Concat [1]
15 -1 1 37248 ultralytics.nn.modules.block.C2f [192, 64, 1]
16 -1 1 36992 ultralytics.nn.modules.conv.Conv [64, 64, 3, 2]
17 [-1, 12] 1 0 ultralytics.nn.modules.conv.Concat [1]
18 -1 1 123648 ultralytics.nn.modules.block.C2f [192, 128, 1]
19 -1 1 147712 ultralytics.nn.modules.conv.Conv [128, 128, 3, 2]
20 [-1, 9] 1 0 ultralytics.nn.modules.conv.Concat [1]
21 -1 1 493056 ultralytics.nn.modules.block.C2f [384, 256, 1]
22 [15, 18, 21] 1 1004470 ultralytics.nn.modules.head.Segment [2, 32, 64, [64, 128, 256]]
YOLOv8-seg summary: 261 layers, 3264006 parameters, 3263990 gradients

Transferred 411/417 items from pretrained weights Ultralytics YOLOv8.0.201 Python-3.9.12 torch-1.8.1+cu111 CPU (12th Gen Intel Core(TM) i7-12700F) YOLOv8-seg summary (fused): 195 layers, 3258454 parameters, 0 gradients

PyTorch: starting from 'yolov8-seg.yaml' with input shape (1, 3, 320, 320) BCHW and output shape(s) ((1, 2100, 98), (1, 32, 6400)) (0.0 MB)

ONNX: starting export with onnx 1.15.0 opset 12... ONNX: simplifying with onnxsim 0.4.35... ONNX: export success 1.4s, saved as 'yolov8-seg.onnx' (12.5 MB)

Export complete (5.3s) Results saved to E:\workspace\pycharm\yolo\ultralytics-main Predict: yolo predict task=segment model=yolov8-seg.onnx imgsz=320
Validate: yolo val task=segment model=yolov8-seg.onnx imgsz=320 data=None
Visualize: https://netron.app

UnstoppableCurry commented 6 months ago

Ultralytics YOLO 🚀, AGPL-3.0 license

YOLOv8-seg instance segmentation model. For Usage examples see https://docs.ultralytics.com/tasks/segment

Parameters

nc: 2 # number of classes scales: # model compound scaling constants, i.e. 'model=yolov8n-seg.yaml' will call yolov8-seg.yaml with scale 'n'

[depth, width, max_channels]

n: [0.33, 0.25, 1024] s: [0.33, 0.50, 1024] m: [0.67, 0.75, 768] l: [1.00, 1.00, 512] x: [1.00, 1.25, 512]

YOLOv8.0n backbone

backbone:

[from, repeats, module, args]

  • [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
  • [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
  • [-1, 3, C2f, [128, True]]
  • [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
  • [-1, 6, C2f, [256, True]]
  • [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
  • [-1, 6, C2f, [512, True]]
  • [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
  • [-1, 3, C2f, [1024, True]]
  • [-1, 1, SPPF, [1024, 5]] # 9

YOLOv8.0n head

head:

  • [-1, 1, nn.Upsample, [None, 2, 'nearest']]

  • [[-1, 6], 1, Concat, [1]] # cat backbone P4

  • [-1, 3, C2f, [512]] # 12

  • [-1, 1, nn.Upsample, [None, 2, 'nearest']]

  • [[-1, 4], 1, Concat, [1]] # cat backbone P3

  • [-1, 3, C2f, [256]] # 15 (P3/8-small)

  • [-1, 1, Conv, [256, 3, 2]]

  • [[-1, 12], 1, Concat, [1]] # cat head P4

  • [-1, 3, C2f, [512]] # 18 (P4/16-medium)

  • [-1, 1, Conv, [512, 3, 2]]

  • [[-1, 9], 1, Concat, [1]] # cat head P5

  • [-1, 3, C2f, [1024]] # 21 (P5/32-large)

  • [[15, 18, 21], 1, Segment, [nc, 32, 256]] # Segment(P3, P4, P5)

UnstoppableCurry commented 6 months ago

model = YOLO('best.pt')

之前先 load yaml ,类别对齐一下

zhouqingf commented 6 months ago

33 谢谢大佬的帮助,类别对齐真的是没想到

UnstoppableCurry commented 6 months ago

ok

UnstoppableCurry commented 6 months ago

留下你的start~

dandyxxxx commented 4 months ago

类别对齐一下是指这样吗: model = YOLO('yolov8n-seg.yaml').load(f"runs/segment/yolov8n-seg/weights/best.pt") path = model.export(format="onnx", opset=12, simplify=True)

我现在用yolov8文档提到的那个crack-seg数据集来做,然后也是按照步骤修改代码然后转成ncnn,修改yolo.cpp中的类别为这样: static const char* class_names[] = { "crack", }; static const unsigned char colors[2][3] = { {56, 0, 255}, {226, 255, 0}, }; 发现检测出来的准确率中级差,现在不清楚是模型权重的问题还是哪一步出错了。

我的训练代码: model = YOLO('yolov8n-seg.yaml').load('yolov8n-seg.pt') results = model.train(data='datasets/crack-seg/data.yaml', epochs=100, imgsz=640, name='yolov8n-seg')

model = YOLO('yolov8n-seg.yaml').load('runs/segment/yolov8n-seg/weights/best.pt') path = model.export(format="onnx", opset=12, simplify=True)

dandyxxxx commented 4 months ago

类别对齐一下是指这样吗: model = YOLO('yolov8n-seg.yaml').load(f“runs/segment/yolov8n-seg/weights/best.pt”) path = model.export(format=“onnx”, opset=12, simplify=True)

我现在用yolov8文档提到的那个crack-seg数据集来做,然后也是按照步骤修改代码然后转成ncnn,修改yolo.cpp中的类别为这样: static const char* class_names[] = { “crack”, };静态常量无符号字符颜色[2][3] = { {56, 0, 255}, {226, 255, 0}, }; 发现检测出来的准确率中级差,现在不清楚是模型权重的问题还是哪一步出错了。

我的训练代码: model = YOLO('yolov8n-seg.yaml').load('yolov8n-seg.pt') results = model.train(data='datasets/crack-seg/data.yaml', epochs=100, imgsz=640, name='yolov8n-seg')

model = YOLO('yolov8n-seg.yaml').load('runs/segment/yolov8n-seg/weights/best.pt') 路径 = model.export(format=“onnx”, opset=12, simplify=True)

而且运行Android Studio时Logcat会提示错误E/cv::error(): OpenCV(4.6.0) Error: Assertion failed (!fixedSize()) in release, file /home/runner/work/opencv-mobile/opencv-mobile/opencv-4.6.0/modules/core/src/matrix_wrap.cpp, line 1667

zhouqingf commented 4 months ago

model = YOLO('yolov8n-seg.yaml').load('runs/segment/yolov8n-seg/weights/best.pt') 路径 = model.export(format=“onnx”, opset=12, simplify=True) 这行代码在转换格式的时候,参照的是这个文件yolov8n-seg.yaml 这个文件如果你没有修改过的话 是有一定的问题,原有类别是80个,而你使用的数据crack-seg是单类别 你可以试试复制yolov8n-seg.yaml并把其中的80类别改为1,重新导出模型

dandyxxxx commented 4 months ago

我尝试了修改类别为1,然后修改block.py中class C2f(nn.Module)和修改head.py中class Segment(Detect)。 我发现我的class Detect(nn.Module)的代码跟https://github.com/Digital2Slave/ncnn-android-yolov8-seg/wiki/Convert-yolov8-model-to-ncnn-model这里提到的代码不太一样我就没有修改了。 这样导出的模型运行在你这个项目上,同时修改了代码中对应的类别的参数为1,但是运行会闪退,同时会提示错误E/cv::error(): OpenCV(4.6.0) Error: Assertion failed (!fixedSize()) in release, file /home/runner/work/opencv-mobile/opencv-mobile/opencv-4.6.0/modules/core/src/matrix_wrap.cpp, line 1667。

会不会是训练或者导出时有什么参数没设置好呢?

zhouqingf commented 4 months ago

你需要先确认你的模型是目标侦测还是分割 目标侦测修改的内容与分割修改的内容是不一样的 分割的话需要修改三个部分 其中C2f与侦测一致 Detect的修改最后一步有一定的区别(换轴) 最后多一个Segment的修改 最后是在你导出ONNX格式时可视化,看看结构是否一致 你可以看上面的记录 一个是正常的 一个是错误的 当你的模型正确时,你再试试 闪退原因的话最好是仔细参考项目代码的修改

UnstoppableCurry commented 4 months ago

把权重发上来看一下就知道了。不过大家周末都在加班吗,都要睡了😄

dandyxxxx commented 4 months ago

非常感谢,我的问题解决了。

一开始是因为要修改class Detect,但是我文件中的Detect代码跟要修改的很不一样,我以为是不同的版本所有没有修改。后来直接替换为需要修改的后就可以了。

dandyxxxx commented 4 months ago

把权重发上来看一下就知道了。不过大家周末都在加班吗,都要睡了😄

在赶ddl了...

UnstoppableCurry commented 4 months ago

加油