0


yolo v7 转rknn

上一篇:yolo v5-release6.0转rknn


一、训练

1.切换版本

git clone https://github.com/WongKinYiu/yolov7.git
cd yolov7
git checkout 44d8ab41780e24eba563b6794371f29db0902271

2.训练

v7的训练可以参考v5训练:yolov5 初识(ubuntu版)、yolov5 初识(win版)


二、pt2onnx

注意一下,opset_version=12
在这里插入图片描述

python export.py --weights="runs/train/exp/weights/best.pt" --simplify

三、onnx2rknn

1.RK356X虚拟环境配置

git clone https://github.com/rockchip-linux/rknn-toolkit2.git
cd rknn-toolkit2
conda create -n rknn-toolkit2 python=3.6
conda activate rknn-toolkit2
pip install doc/requirements_cp36-*.txt
# if install bfloat16 failed, please install numpy manually first. "pip install numpy==1.16.6"
pip install doc/requirements_cp36-*.txt
pip install packages/rknn_toolkit2-*-cp36-*.whl

2.rknn-toolkit2/example/onnx下创建自己的项目,例如myyolov7,如下:

(样式照搬官方已有实例:test.jpg为任意一张测试集里的数据,dataset.txt为量化数据集的路径(200~500张?我也不太确定,这里只用了1张),test.py为转换代码,需修改。)
在这里插入图片描述


3.修改test.py

直接上图:

1.输入的一些设置

在这里插入图片描述


2.输出的一些设置

在这里插入图片描述

由来:
用这个网站打开转换的onnx模型
在这里插入图片描述

然后找到模型的三个输出,进行如下图的操作:
在这里插入图片描述在这里插入图片描述
另外2个节点相同操作方法。


3.后处理的一些设置

anchors用yolov7训练的:
在这里插入图片描述
由来:
在这里插入图片描述


4.显示

在这里插入图片描述


四、 完整代码:

import os
import urllib
import traceback
import time
import sys
import numpy as np
import cv2
from rknn.api import RKNN

ONNX_MODEL ='/home/tm1/win/E/workspace/yolo/yolov7/runs/train/exp/weights/best.onnx'
RKNN_MODEL ='yolov7.rknn'
IMG_PATH ='./test.jpg'
DATASET ='./dataset.txt'

QUANTIZE_ON =True

BOX_THESH =0.45
NMS_THRESH =0.25
IMG_SIZE =640

CLASSES =["EarTag"]defsigmoid(x):return1/(1+ np.exp(-x))defxywh2xyxy(x):# Convert [x, y, w, h] to [x1, y1, x2, y2]
    y = np.copy(x)
    y[:,0]= x[:,0]- x[:,2]/2# top left x
    y[:,1]= x[:,1]- x[:,3]/2# top left y
    y[:,2]= x[:,0]+ x[:,2]/2# bottom right x
    y[:,3]= x[:,1]+ x[:,3]/2# bottom right yreturn y

defprocess(input, mask, anchors):
    anchors =[anchors[i]for i in mask]
    grid_h, grid_w =map(int,input.shape[0:2])

    box_confidence = sigmoid(input[...,4])
    box_confidence = np.expand_dims(box_confidence, axis=-1)

    box_class_probs = sigmoid(input[...,5:])

    box_xy = sigmoid(input[...,:2])*2-0.5

    col = np.tile(np.arange(0, grid_w), grid_w).reshape(-1, grid_w)
    row = np.tile(np.arange(0, grid_h).reshape(-1,1), grid_h)
    col = col.reshape(grid_h, grid_w,1,1).repeat(3, axis=-2)
    row = row.reshape(grid_h, grid_w,1,1).repeat(3, axis=-2)
    grid = np.concatenate((col, row), axis=-1)
    box_xy += grid
    box_xy *=int(IMG_SIZE / grid_h)

    box_wh =pow(sigmoid(input[...,2:4])*2,2)
    box_wh = box_wh * anchors

    box = np.concatenate((box_xy, box_wh), axis=-1)return box, box_confidence, box_class_probs

deffilter_boxes(boxes, box_confidences, box_class_probs):"""Filter boxes with box threshold. It's a bit different with origin yolov5 post process!

    # Arguments
        boxes: ndarray, boxes of objects.
        box_confidences: ndarray, confidences of objects.
        box_class_probs: ndarray, class_probs of objects.

    # Returns
        boxes: ndarray, filtered boxes.
        classes: ndarray, classes for boxes.
        scores: ndarray, scores for boxes.
    """
    box_classes = np.argmax(box_class_probs, axis=-1)
    box_class_scores = np.max(box_class_probs, axis=-1)
    pos = np.where(box_confidences[...,0]>= BOX_THESH)

    boxes = boxes[pos]
    classes = box_classes[pos]
    scores = box_class_scores[pos]return boxes, classes, scores

defnms_boxes(boxes, scores):"""Suppress non-maximal boxes.

    # Arguments
        boxes: ndarray, boxes of objects.
        scores: ndarray, scores of objects.

    # Returns
        keep: ndarray, index of effective boxes.
    """
    x = boxes[:,0]
    y = boxes[:,1]
    w = boxes[:,2]- boxes[:,0]
    h = boxes[:,3]- boxes[:,1]

    areas = w * h
    order = scores.argsort()[::-1]

    keep =[]while order.size >0:
        i = order[0]
        keep.append(i)

        xx1 = np.maximum(x[i], x[order[1:]])
        yy1 = np.maximum(y[i], y[order[1:]])
        xx2 = np.minimum(x[i]+ w[i], x[order[1:]]+ w[order[1:]])
        yy2 = np.minimum(y[i]+ h[i], y[order[1:]]+ h[order[1:]])

        w1 = np.maximum(0.0, xx2 - xx1 +0.00001)
        h1 = np.maximum(0.0, yy2 - yy1 +0.00001)
        inter = w1 * h1

        ovr = inter /(areas[i]+ areas[order[1:]]- inter)
        inds = np.where(ovr <= NMS_THRESH)[0]
        order = order[inds +1]
    keep = np.array(keep)return keep

defyolov5_post_process(input_data):
    masks =[[0,1,2],[3,4,5],[6,7,8]]
    yolov5_anchors =[[10,13],[16,30],[33,23],[30,61],[62,45],[59,119],[116,90],[156,198],[373,326]]

    yolov7_anchors =[[12,16],[19,36],[40,28],[36,75],[75,55],[72,146],[142,110],[192,243],[459,401]]

    boxes, classes, scores =[],[],[]forinput, mask inzip(input_data, masks):
        b, c, s = process(input, mask, yolov5_anchors)
        b, c, s = filter_boxes(b, c, s)
        boxes.append(b)
        classes.append(c)
        scores.append(s)

    boxes = np.concatenate(boxes)
    boxes = xywh2xyxy(boxes)
    classes = np.concatenate(classes)
    scores = np.concatenate(scores)

    nboxes, nclasses, nscores =[],[],[]for c inset(classes):
        inds = np.where(classes == c)
        b = boxes[inds]
        c = classes[inds]
        s = scores[inds]

        keep = nms_boxes(b, s)

        nboxes.append(b[keep])
        nclasses.append(c[keep])
        nscores.append(s[keep])ifnot nclasses andnot nscores:returnNone,None,None

    boxes = np.concatenate(nboxes)
    classes = np.concatenate(nclasses)
    scores = np.concatenate(nscores)return boxes, classes, scores

defdraw(image, boxes, scores, classes):"""Draw the boxes on the image.

    # Argument:
        image: original image.
        boxes: ndarray, boxes of objects.
        classes: ndarray, classes of objects.
        scores: ndarray, scores of objects.
        all_classes: all classes name.
    """for box, score, cl inzip(boxes, scores, classes):
        top, left, right, bottom = box
        print('class: {}, score: {}'.format(CLASSES[cl], score))print('box coordinate left,top,right,down: [{}, {}, {}, {}]'.format(top, left, right, bottom))
        top =int(top)
        left =int(left)
        right =int(right)
        bottom =int(bottom)

        cv2.rectangle(image,(top, left),(right, bottom),(255,0,0),2)
        cv2.putText(image,'{0} {1:.2f}'.format(CLASSES[cl], score),(top, left +10),
                    cv2.FONT_HERSHEY_SIMPLEX,0.6,(0,0,255),2)defletterbox(im, new_shape=(640,640), color=(0,0,0)):# Resize and pad image while meeting stride-multiple constraints
    shape = im.shape[:2]# current shape [height, width]ifisinstance(new_shape,int):
        new_shape =(new_shape, new_shape)# Scale ratio (new / old)
    r =min(new_shape[0]/ shape[0], new_shape[1]/ shape[1])# Compute padding
    ratio = r, r  # width, height ratios
    new_unpad =int(round(shape[1]* r)),int(round(shape[0]* r))
    dw, dh = new_shape[1]- new_unpad[0], new_shape[0]- new_unpad[1]# wh padding

    dw /=2# divide padding into 2 sides
    dh /=2if shape[::-1]!= new_unpad:# resize
        im = cv2.resize(im, new_unpad, interpolation=cv2.INTER_LINEAR)
    top, bottom =int(round(dh -0.1)),int(round(dh +0.1))
    left, right =int(round(dw -0.1)),int(round(dw +0.1))
    im = cv2.copyMakeBorder(im, top, bottom, left, right, cv2.BORDER_CONSTANT, value=color)# add borderreturn im, ratio,(dw, dh)if __name__ =='__main__':# Create RKNN object
    rknn = RKNN(verbose=True)# pre-process configprint('--> Config model')
    rknn.config(mean_values=[[0,0,0]], std_values=[[255,255,255]])print('done')# Load ONNX modelprint('--> Loading model')
    ret = rknn.load_onnx(model=ONNX_MODEL, outputs=['495','515','535'])# ret = rknn.load_onnx(ONNX_MODEL)if ret !=0:print('Load model failed!')
        exit(ret)print('done')# Build modelprint('--> Building model')
    ret = rknn.build(do_quantization=QUANTIZE_ON, dataset=DATASET)if ret !=0:print('Build model failed!')
        exit(ret)print('done')# Export RKNN modelprint('--> Export rknn model')
    ret = rknn.export_rknn(RKNN_MODEL)if ret !=0:print('Export rknn model failed!')
        exit(ret)print('done')# Init runtime environmentprint('--> Init runtime environment')
    ret = rknn.init_runtime()# ret = rknn.init_runtime('rk3566')if ret !=0:print('Init runtime environment failed!')
        exit(ret)print('done')# Set inputs
    img = cv2.imread(IMG_PATH)# img, ratio, (dw, dh) = letterbox(img, new_shape=(IMG_SIZE, IMG_SIZE))
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    img = cv2.resize(img,(IMG_SIZE, IMG_SIZE))# Inferenceprint('--> Running model')
    outputs = rknn.inference(inputs=[img])# np.save('./onnx_yolov5_0.npy', outputs[0])# np.save('./onnx_yolov5_1.npy', outputs[1])# np.save('./onnx_yolov5_2.npy', outputs[2])print('done')# post process
    input0_data = outputs[0]
    input1_data = outputs[1]
    input2_data = outputs[2]

    input0_data = input0_data.reshape([3,-1]+list(input0_data.shape[-2:]))
    input1_data = input1_data.reshape([3,-1]+list(input1_data.shape[-2:]))
    input2_data = input2_data.reshape([3,-1]+list(input2_data.shape[-2:]))

    input_data =list()
    input_data.append(np.transpose(input0_data,(2,3,0,1)))
    input_data.append(np.transpose(input1_data,(2,3,0,1)))
    input_data.append(np.transpose(input2_data,(2,3,0,1)))

    boxes, classes, scores = yolov5_post_process(input_data)

    img_1 = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)if boxes isnotNone:
        draw(img_1, boxes, scores, classes)# show output
    cv2.imshow("post process result", img_1)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

    rknn.release()

本文转载自: https://blog.csdn.net/wave789/article/details/126448389
版权归原作者 wave789 所有, 如有侵权,请联系我们删除。

“yolo v7 转rknn”的评论:

还没有评论