基本思想:仍然是身份证分割,因为上一个篇博客的效果不好,所以操刀改mm系列的框架,并进行ncnn和mnn的c++的部署开发
mmcv_full 1.6.1+mmrotate v0.3.2测试没有问题
mmcv_full1.4.6+mmrotate v0.3.0版本如果报错 ,需要删掉/home/ubuntu/v0.3.0/mmrotate/mmrotate/models/dense_head/oriented_reppoints_head.py报错提示的引用包chamfer_distance
mmrotate源码和mnn源码使用20220813之前日期的测试没有问题,
第一步下载源码
ubuntu@ubuntu-Super-Server:~/sxj731533730$ git clone https://github.com/open-mmlab/mmrotate.git
Cloning into 'mmrotate'...
remote: Enumerating objects: 23529, done.
remote: Total 23529 (delta 0), reused 0 (delta 0), pack-reused 23529
Receiving objects: 100% (23529/23529), 35.29 MiB | 3.54 MiB/s, done.
Resolving deltas: 100% (16443/16443), done.
ubuntu@ubuntu-Super-Server:~/sxj731533730$ cd mmrotate/
ubuntu@ubuntu-Super-Server:~/sxj731533730/mmrotate$ pip3 install -r requirements.txt
第二步:下载模型和测试
ubuntu@ubuntu-Super-Server:~/sxj731533730/mmrotaten$ mkdir model
ubuntu@ubuntu-Super-Server:~/sxj731533730/mmrotate$ cd model/
ubuntu@ubuntu-Super-Server:~/sxj731533730/mmrotate/model$ cat ../configs/kfiou/README.md
ubuntu@ubuntu-Super-Server:~/sxj731533730/mmrotate/model$ axel -n 100 https://download.openmmlab.com/mmrotate/v0.1.0/kfiou/r3det_kfiou_ln_r50_fpn_1x_dota_oc/r3det_kfiou_ln_r50_fpn_1x_dota_oc-8e7f049d.pth
ubuntu@ubuntu-Super-Server:~/sxj731533730/mmrotate/model$ pip install mmcv-full==1.4.6 -f https://download.openmmlab.com/mmcv/dist/cu113/torch1.10.0/index.html
然后修改一下测试程序
ubuntu@ubuntu-Super-Server:~/sxj731533730/mmrotate/demo$ python3 image_demo.py demo.jpg ../configs/kfiou/r3det_kfiou_ln_
r50_fpn_1x_dota_oc.py ../model/r3det_kfiou_ln_r50_fpn_1x_dota_oc-8e7f049d.pth sxj731533730.jpg
第三步:首先开始造数据集,比如我只标注了四张身份证图片,且为4个坐标点图 一个反面 三个反面 一个正面 三个正面的 (正面的图就不上了)
标注方式参考官网解释 https://captain-whu.github.io/DOTA/index.html
x1, y1, x2, y2, x3, y3, x4, y4:四边形的四个顶点的坐标 顶点按顺时针顺序排列,第一个起点为左上第一个点
使用的labelme 标注的,也可以使用rolabelimg标注~
使用旋转代码,进行生成批量角度图片
# -*- coding: utf-8 -*-
import os
import sys
import json
import io
import random
import re
import cv2
import numpy as np
from random import choice
import math
source_path = r'A'
destination_path = r'B'
angle=[]
for item in range(0,360,15):
angle.append(item)
for angle_item in angle:
article_info = {}
data_json = json.loads(json.dumps(article_info))
data_json['version'] = '5.0.1'
data_json['flags'] = {}
data_json["lineColor"] = [
0,
255,
0,
128
]
data_json["fillColor"] = [
255,
0,
0,
128
]
def file_name(file_dir):
L = []
for root, dirs, files in os.walk(file_dir):
for file in files:
if os.path.splitext(file)[1] == '.json':
L.append(os.path.join(root, file))
return L
def rotation_point(img, angle,pts):
cols = img.shape[1]
rows = img.shape[0]
M = cv2.getRotationMatrix2D((cols / 2, rows / 2), angle, 1)
heightNew = int(cols * math.fabs(math.sin(math.radians(angle))) + rows * math.fabs(math.cos(math.radians(angle))))
widthNew = int(rows * math.fabs(math.sin(math.radians(angle))) + cols * math.fabs(math.cos(math.radians(angle))))
M[0, 2] += (widthNew - cols) / 2
M[1, 2] += (heightNew - rows) / 2
img = cv2.warpAffine(img, M, (widthNew, heightNew))
pts = cv2.transform(np.asarray(pts, dtype=np.float64).reshape((-1, 1, 2)), M)
return img,pts
for name in enumerate(file_name(source_path)):
shape_json = []
m_path = name[1]
dir = os.path.dirname(m_path)
file_json = io.open(m_path, 'r', encoding='utf-8')
json_data = file_json.read()
data = json.loads(json_data)
data_json['imageData'] = None
data_name = data['imagePath']
data_path = os.path.join(dir ,data_name)
object_name = os.path.splitext(data['imagePath'])[0]
data_new_json_name =None
list_point=[]
for i in range(len(data['shapes'])):
m_name_0 = data['shapes'][i]['label']
print('m_name_0=', m_name_0)
item_point = []
for j in range(len(data['shapes'][i]['points'])):
print(data['shapes'][i]['points'][j][0],data['shapes'][i]['points'][j][1])
item_point.append([data['shapes'][i]['points'][j][0],data['shapes'][i]['points'][j][1]])
data_json_fill_color=None
data_json_rec = data['shapes'][i]['shape_type']
img = cv2.imread(data_path)
im_rotate,item_point = rotation_point(img, angle_item,np.asarray(item_point))
item_point=np.squeeze(item_point).tolist()
print(item_point)
(filename, extension) = os.path.splitext(data_name)
data_new_picture_name = os.path.join(destination_path ,filename+ ".".join([str(angle_item), "jpg"]))
data_new_json_name = os.path.join(destination_path , filename+".".join([str(angle_item), "json"]))
data_json['imagePath'] = filename + ".".join([str(angle_item) , "jpg"])
cv2.imwrite(data_new_picture_name, im_rotate)
im_rotate = cv2.imread(data_new_picture_name)
data_json['imageWidth'] = im_rotate.shape[1]
data_json['imageHeight'] = im_rotate.shape[0]
shape_json_item = {"label": m_name_0,
"points": item_point, "shape_type": data_json_rec}
shape_json.append(shape_json_item)
data_json['shapes'] = shape_json
data_info = json.dumps(data_json, ensure_ascii=False)
fp = open(data_new_json_name, "w+")
json.dump(data_info, fp, ensure_ascii=False, indent=4)
fp.close()
fp = open(data_new_json_name, "r")
for x in fp.readlines():
y = x.replace("\\\"", "\"")
z = y.replace("\"{", "{")
w = z.replace("}\"", "}")
fp.close()
fp = open(data_new_json_name, "w+")
fp.write(w)
fp.close()
只贴两张
第四步:训练我们自己的数据集
ubuntu@ubuntu-Super-Server:~/sxj731533730/mmrotate$ mkdir -p kfiouDataSets
里面是标准的jpg和json(labelme标注的格式)
ubuntu@ubuntu-Super-Server:~/sxj731533730/mmrotate/kfiouDataSets$ tree -L 1
├── trainDataset #里面含有jpg和对用json文件
└── valDataset #里面含有jpg和对用json文件
└── testDataset #里面含有jpg和对用json文件
3 directories, 0 files
生成 DOTA数据集(参考附录作者修改了下面脚本) labelme2dota.py
生成方式格式 每个图片目标对应一个txt 解释权 https://captain-whu.github.io/DOTA/index.html
x1, y1, x2, y2, x3, y3, x4, y4, category, difficult
x1, y1, x2, y2, x3, y3, x4, y4, category, difficult
category: 标签名字
difficult:表示标签检测的难易程度 (1表示困难,0表示不困难)
转换脚本 labelme2dota ,我担心顺时针排序代码写的有问题,也做了反向转换验证,因为 mmrotate 代码里训练需要png 图片 还是不动代码了 改图片格式吧
import json
import os
from glob import glob
import argparse
import numpy as np
import shutil
from PIL import Image
import cv2
# convert labelme json to DOTA txt format
# convert DOTA json to lableme txt format
def custombasename(fullname):
return os.path.basename(os.path.splitext(fullname)[0])
def order_points_new(pts): # clock -https://zhuanlan.zhihu.com/p/10643062
# sort the points based on their x-coordinates
xSorted = pts[np.argsort(pts[:, 0]), :]
# grab the left-most and right-most points from the sorted
# x-roodinate points
leftMost = xSorted[:2, :]
rightMost = xSorted[2:, :]
if leftMost[0, 1] != leftMost[1, 1]:
leftMost = leftMost[np.argsort(leftMost[:, 1]), :]
else:
leftMost = leftMost[np.argsort(leftMost[:, 0])[::-1], :]
(tl, bl) = leftMost
if rightMost[0, 1] != rightMost[1, 1]:
rightMost = rightMost[np.argsort(rightMost[:, 1]), :]
else:
rightMost = rightMost[np.argsort(rightMost[:, 0])[::-1], :]
(tr, br) = rightMost
# return the coordinates in top-left, top-right,
# bottom-right, and bottom-left order
return np.array([tl, tr, br, bl], dtype="float32")
parser = argparse.ArgumentParser(
formatter_class=argparse.ArgumentDefaultsHelpFormatter
)
parser.add_argument('--input_dir', default=r'C:\Users\PHILIPS\Desktop\source', type=str,
help='input annotated directory')
parser.add_argument('--output_images', default=r'C:\Users\PHILIPS\Desktop\datasets\images', type=str,
help='input annotated directory')
parser.add_argument('--output_dir', default=r'C:\Users\PHILIPS\Desktop\datasets\labelTxt', type=str, help='output dataset directory')
parser.add_argument('--verify_dir', default=r'C:\Users\PHILIPS\Desktop\datasets\verify', type=str,
help='verify dataset directory')
parser.add_argument('--verify', default=True, type=bool, help='verify')
parser.add_argument('--labels', default=r'labels.txt', type=str, help='labels annotated directory')
args = parser.parse_args()
if not os.path.exists(args.output_dir):
os.makedirs(args.output_dir)
if not os.path.exists(args.output_images):
os.makedirs(args.output_images)
print('Creating dataset:', args.output_dir)
file_list = glob(os.path.join(args.input_dir, ".".join(["*", "json"])))
for i in range(len(file_list)):
with open(file_list[i]) as f:
label_str = f.read()
label_dict = json.loads(label_str) # json文件读入dict
# 输出 txt 文件的路径
out_file = os.path.join(args.output_dir, ".".join([custombasename(file_list[i]), 'txt']))
# 写入 poly 四点坐标 和 label
fout = open(out_file, 'w')
out_str = ''
# np.array(box, dtype="int")
for shape_dict in label_dict['shapes']:
points = shape_dict['points']
item_points = []
for p in points:
item_points.append([p[0], p[1]])
item_points = order_points_new(np.array(item_points, dtype="float"))
for p in item_points.tolist():
out_str += (str(p[0]) + ' ' + str(p[1]) + ' ')
out_str += shape_dict['label'] + ' 0\n'
fout.write(out_str)
fout.close()
print('%d/%d' % (i + 1, len(file_list)))
print("labelme2dota...")
if args.verify:
if not os.path.exists(args.verify_dir):
os.makedirs(args.verify_dir)
txt_list = glob(os.path.join(args.output_dir, ".".join(["*", "txt"])))
for i in range(len(txt_list)):
(filepath, tempfilename) = os.path.split(txt_list[i])
(filename, extension) = os.path.splitext(tempfilename)
sourcePath = None
image_filename = None
if os.path.exists(os.path.join(args.input_dir, ".".join([filename, "jpg"]))):
sourcePath = os.path.join(args.input_dir, ".".join([filename, "jpg"]))
image_filename = ".".join([filename, "png"])
elif os.path.exists(os.path.join(args.input_dir, ".".join([filename, "png"]))):
sourcePath = os.path.join(args.input_dir, ".".join([filename, "png"]))
image_filename = ".".join([filename, "png"])
if sourcePath is None:
print("check photo type")
continue
targetPath = os.path.join(args.verify_dir,image_filename)
targetpng = os.path.join(args.output_images, image_filename)
shutil.copy(sourcePath, targetPath)
shutil.copy(sourcePath, targetpng)
img = Image.open(sourcePath)
imgSize = img.size # 大小/尺寸
w = img.width # 图片的宽
h = img.height # 图片的高
data = {}
data['imagePath'] = image_filename
data['flags'] = {}
data['imageWidth'] = w
data['imageHeight'] = h
data['imageData'] = None
data['version'] = "5.0.1"
data["shapes"] = []
with open(txt_list[i]) as f:
label_str = f.readlines()
for label_item in label_str:
line_char = label_item.split("\n")[0].split(' ')
points = [[eval(line_char[0]), eval(line_char[1])], [eval(line_char[2]), eval(line_char[3])],
[eval(line_char[4]), eval(line_char[5])], [eval(line_char[6]), eval(line_char[7])]]
itemData = {'points': []}
itemData['points'].extend(points)
itemData["flag"] = {}
itemData["group_id"] = None
itemData["shape_type"] = "polygon"
itemData["label"] = line_char[-2]
data["shapes"].append(itemData)
jsonName = ".".join([filename, "json"])
jsonPath = os.path.join(args.verify_dir, jsonName)
with open(jsonPath, "w") as f:
json.dump(data, f)
print(jsonName)
print("dota2labelme...")
执行命令,最好在本地用该脚本,熟悉一下转换方式
ubuntu@ubuntu-Super-Server:~/sxj731533730/mmrotate/yolactDataSets$ sudo vim labels.txt
ubuntu@ubuntu-Super-Server:~/sxj731533730/mmrotate/yolactDataSets$ cat labels.txt
card
ubuntu@ubuntu-Super-Server:~/sxj731533730/mmrotate$ python3 labelme2dota.py --input_dir kfiouDataSets/trainDataset/ --output_dir kfiouDataSets/train --verify false --labels kfiouDataSets/labels.txt
ubuntu@ubuntu-Super-Server:~/sxj731533730/mmrotate$ python3 labelme2dota.py --input_dir kfiouDataSets/valDataset/ --output_dir kfiouDataSets/val --verify false --labels kfiouDataSets/labels.txt
ubuntu@ubuntu-Super-Server:~/sxj731533730/mmrotate$ python3 labelme2dota.py --input_dir kfiouDataSets/testDataset/ --output_dir kfiouDataSets/test --verify false --labels kfiouDataSets/labels.txt
划分训练和验证 测试集
import os
from glob import glob
import shutil
import random
ann_txt=r"C:\Users\PHILIPS\Desktop\dest"
train_annfile=r"C:\Users\PHILIPS\Desktop\train_annfile"
test_annfile=r"C:\Users\PHILIPS\Desktop\test_annfile"
val_annfile=r"C:\Users\PHILIPS\Desktop\val_annfile"
train_num=0.8
test_num=0.2
val_num=0.2
if not os.path.exists(train_annfile):
os.makedirs(train_annfile)
if not os.path.exists(test_annfile):
os.makedirs(test_annfile)
if not os.path.exists(val_annfile):
os.makedirs(val_annfile)
txt_list = glob(os.path.join(ann_txt, ".".join(["*", "txt"])))
train_list = random.sample(txt_list, int(train_num*len(txt_list)))
val_list = random.sample(txt_list, int(val_num*len(txt_list)))
test_list = random.sample(txt_list, int(test_num*len(txt_list)))
for idx,item in enumerate(txt_list):
source_file_txt=os.path.join(ann_txt,item)
if item in train_list:
shutil.copy(source_file_txt, train_annfile)
elif item in val_list:
shutil.copy(source_file_txt, val_annfile)
else:
shutil.copy(source_file_txt, test_annfile)
print("copy txt into file")
print("complish")
整个目录结构
ubuntu@ubuntu-Super-Server:~/sxj731533730/mmrotate$ tree -L 1
.
├── CITATION.cff
├── configs
├── demo
├── docker
├── docs
├── generate.py
├── kfiouDataSets
├── LICENSE
├── MANIFEST.in
├── mmrotate
├── model
├── model-index.yml
├── README.md
├── README_zh-CN.md
├── requirements
├── requirements.txt
├── resources
├── setup.cfg
├── setup.py
├── tests
└── tools
11 directories, 10 files
修改配置文件参数和增加参数,目录
ubuntu@ubuntu-Super-Server:~/sxj731533730/mmrotate/kfiouDataSets$ tree -L 1
.
├── labels.txt
├── source
├── test_annfile
├── train_annfile
└── val_annfile
4 directories, 1 file
修改配置文件
home/ubuntu/sxj731533730/mmrotate/configs/_base_/datasets/dotav1.py
变更数据集的根目录和训练集 测试集 验证集的目录
# dataset settings
dataset_type = 'DOTADataset'
data_root = '/home/ubuntu/sxj731533730/mmrotate/kfiouDataSets/'
。。。。。
data = dict(
samples_per_gpu=2,
workers_per_gpu=2,
train=dict(
type=dataset_type,
#classes=('card',),
ann_file=data_root + 'train_annfile/',
img_prefix=data_root + 'source/',
pipeline=train_pipeline),
val=dict(
type=dataset_type,
#classes=('card',),
ann_file=data_root + 'val_annfile/',
img_prefix=data_root + 'source/',
pipeline=test_pipeline),
test=dict(
type=dataset_type,
#classes=('card',),
ann_file=data_root + 'test_annfile/',
img_prefix=data_root + 'source/',
pipeline=test_pipeline))
修改一下标签
ubuntu@ubuntu-Super-Server:~/sxj731533730/mmrotate$ sudo vim mmrotate/datasets/dota.py
class DOTADataset(CustomDataset):
"""DOTA dataset for detection.
Args:
ann_file (str): Annotation file path.
pipeline (list[dict]): Processing pipeline.
version (str, optional): Angle representations. Defaults to 'oc'.
difficulty (bool, optional): The difficulty threshold of GT.
"""
'''
CLASSES = ('plane', 'baseball-diamond', 'bridge', 'ground-track-field',
'small-vehicle', 'large-vehicle', 'ship', 'tennis-court',
'basketball-court', 'storage-tank', 'soccer-ball-field',
'roundabout', 'harbor', 'swimming-pool', 'helicopter')
'''
CLASSES=('card',) # need to add ,
修改配置文件
ubuntu@ubuntu-Super-Server:~/sxj731533730/mmrotate$ sudo vim configs/r3det/r3det_r50_fpn_1x_dota_oc.py
ubuntu@ubuntu-Super-Server:~/sxj731533730/mmrotate$ sudo vim configs/kfiou/r3det_kfiou_ln_r50_fpn_1x_dota_oc.py
num_classes=1 #
建立一个存储日志和模型的文件夹
ubuntu@ubuntu-Super-Server:~/sxj731533730/mmrotate$ mkdir run
第五步:开始训练模型
ubuntu@ubuntu-Super-Server:~/sxj731533730/mmrotate$ python3 tools/train.py configs/kfiou/r3det_kfiou_ln_r50_fpn_1x_dota_oc.py --work-dir=run
训练的过程
2022-03-22 06:21:11,014 - mmrotate - INFO - workflow: [('train', 1)], max: 12 epochs
2022-03-22 06:21:11,014 - mmrotate - INFO - Checkpoints will be saved to /home/ubuntu/sxj731533730/mmrotate/run by HardDiskBackend.
2022-03-22 06:21:35,543 - mmrotate - INFO - Epoch [1][50/330] lr: 9.967e-04, eta: 0:31:57, time: 0.491, data_time: 0.050, memory: 3442, s0.loss_cls: 1.1651, s0.loss_bbox: 6.7060, sr0.loss_cls: 1.1758, sr0.loss_bbox: 6.2110, loss: 15.2579, grad_norm: 8.4750
2022-03-22 06:21:57,744 - mmrotate - INFO - Epoch [1][100/330] lr: 1.163e-03, eta: 0:30:03, time: 0.444, data_time: 0.005, memory: 3442, s0.loss_cls: 0.9773, s0.loss_bbox: 6.1366, sr0.loss_cls: 0.4372, sr0.loss_bbox: 5.9701, loss: 13.5212, grad_norm: 26.8998
2022-03-22 06:22:19,983 - mmrotate - INFO - Epoch [1][150/330] lr: 1.330e-03, eta: 0:29:11, time: 0.445, data_time: 0.005, memory: 3442, s0.loss_cls: 0.3552, s0.loss_bbox: 5.9312, sr0.loss_cls: 0.2589, sr0.loss_bbox: 5.9402, loss: 12.4856, grad_norm: 18.0854
2022-03-22 06:22:42,092 - mmrotate - INFO - Epoch [1][200/330] lr: 1.497e-03, eta: 0:28:32, time: 0.442, data_time: 0.005, memory: 3442, s0.loss_cls: 0.2930, s0.loss_bbox: 5.8729, sr0.loss_cls: 0.2286, sr0.loss_bbox: 5.9325, loss: 12.3271, grad_norm: 15.2396
2022-03-22 06:23:04,421 - mmrotate - INFO - Epoch [1][250/330] lr: 1.663e-03, eta: 0:28:02, time: 0.447, data_time: 0.005, memory: 3442, s0.loss_cls: 0.2843, s0.loss_bbox: 5.8343, sr0.loss_cls: 0.2799, sr0.loss_bbox: 5.8648, loss: 12.2633, grad_norm: 12.3675
2022-03-22 06:23:26,901 - mmrotate - INFO - Epoch [1][300/330] lr: 1.830e-03, eta: 0:27:37, time: 0.450, data_time: 0.005, memory: 3442, s0.loss_cls: 0.2462, s0.loss_bbox: 5.7725, sr0.loss_cls: 0.0950, sr0.loss_bbox: 5.8509, loss: 11.9646, grad_norm: 9.6189
2022-03-22 06:24:04,773 - mmrotate - INFO - Epoch [2][50/330] lr: 2.097e-03, eta: 0:25:11, time: 0.491, data_time: 0.049, memory: 3442, s0.loss_cls: 0.1637, s0.loss_bbox: 5.6981, sr0.loss_cls: 0.0575, sr0.loss_bbox: 5.8003, loss: 11.7196, grad_norm: 6.5400
......
2022-03-23 01:48:42,354 - mmrotate - INFO -
+-------+-----+------+--------+-------+
| class | gts | dets | recall | ap |
+-------+-----+------+--------+-------+
| card | 50 | 53 | 1.000 | 1.000 |
+-------+-----+------+--------+-------+
| mAP | | | | 1.000 |
+-------+-----+------+--------+-------+
2022-03-23 01:48:42,385 - mmrotate - INFO - Exp name: r3det_kfiou_ln_r50_fpn_1x_dota_oc.py
2022-03-23 01:48:42,386 - mmrotate - INFO - Epoch(val) [12][28] mAP: 1.0000
第l六步:测试一下 我只训练12次而已
ubuntu@ubuntu-Super-Server:~/sxj731533730/mmrotate$ python3 demo/image_demo.py kfiouDataSets/source/cap_output_00_03_30_30210.jpg configs/kfiou/r3det_kfiou_ln_r50_fpn_1x_dota_oc.py run/epoch_12.pth demo/sxj731533730.jpg
将身份证生成分割图片写入本地显示 (还未训练好,继续训练中)
第七步:转mmrotate模型到onnx过程中遇到了涉及到mmcv函数,好难啊,官方暂时没提供转换脚本,只能抄袭mmdetection~
(1)先修改一下
mmrotate/models/detectors/r3det.py
def forward_dummy(self, img):
.....
return outs,rois #返回两个变量
(2)补充一个函数,用于onnx的输出结果和测试
def simple_test_onnx(self, img_meta,outs,rois, rescale=False):
"""Test function without test time augmentation.
Args:
imgs (list[torch.Tensor]): List of multiple images
img_metas (list[dict]): List of image information.
rescale (bool, optional): Whether to rescale the results.
Defaults to False.
Returns:
list[list[np.ndarray]]: BBox results of each image and classes. \
The outer list corresponds to each image. The inner list \
corresponds to each class.
"""
bbox_inputs = outs + (img_meta, self.test_cfg, rescale)
print(self.refine_head[-1])
bbox_list = self.refine_head[-1].get_bboxes(*bbox_inputs, rois=rois)
bbox_results = [
rbbox2result(det_bboxes, det_labels,
self.refine_head[-1].num_classes)
for det_bboxes, det_labels in bbox_list
]
return bbox_results
(3)修改一下mmcv的源码,否则无法转成onnx模型,读一下源代码,因为只做前向传播推理,可以简单处理一下,以转模型成功为基准
D:\Python39\Lib\site-packages\mmcv\ops\rotated_feature_align.py
或者linux 路径 ubuntu@ubuntu:~/.local/lib/python3.8/site-packages/mmcv/ops$ sudo vim rotated_feature_align.py
原mmcv源代码
def rotated_feature_align(features,
best_rbboxes,
spatial_scale=1 / 8,
points=1):
return RotatedFeatureAlignFunction.apply(features, best_rbboxes,spatial_scale, points)
mmcv修改后,记得转完模型,还原回去。。。别影响训练 实际把forward 函数的backward删掉了
def rotated_feature_align(features,
best_rbboxes,
spatial_scale=1 / 8,
points=1):
spatial_scale = spatial_scale
points = points
assert points in [1, 5]
output = torch.zeros_like(features)
ext_module.rotated_feature_align_forward(
features,
best_rbboxes,
output,
spatial_scale=spatial_scale,
points=points)
return output
然后使用转换脚本进行convertonnx.py
import mmcv
import numpy as np
import torch
from mmcv.ops import RoIPool
from mmcv.parallel import collate, scatter
from mmcv.runner import load_checkpoint
from mmdet.core import get_classes
from mmdet.datasets import replace_ImageToTensor
from mmdet.datasets.pipelines import Compose
from mmdet.models import build_detector
from argparse import ArgumentParser
from mmdet.apis import inference_detector, init_detector
import torch
# import trochvision
import torch.utils.data
import argparse
import onnxruntime
import os
import cv2
import numpy as np
from onnxruntime.datasets import get_example
import mmrotate # noqa: F401
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
def getConfig(imgs, model):
if isinstance(imgs, (list, tuple)):
is_batch = True
else:
imgs = [imgs]
is_batch = False
cfg = model.cfg
device = next(model.parameters()).device # model device
if isinstance(imgs[0], np.ndarray):
cfg = cfg.copy()
# set loading pipeline type
cfg.data.test.pipeline[0].type = 'LoadImageFromWebcam'
cfg.data.test.pipeline = replace_ImageToTensor(cfg.data.test.pipeline)
test_pipeline = Compose(cfg.data.test.pipeline)
datas = []
for img in imgs:
# prepare data
if isinstance(img, np.ndarray):
# directly add img
data = dict(img=img)
else:
# add information into dict
data = dict(img_info=dict(filename=img), img_prefix=None)
# build the data pipeline
data = test_pipeline(data)
datas.append(data)
data = collate(datas, samples_per_gpu=len(imgs))
# just get the actual data from DataContainer
data['img_metas'] = [img_metas.data[0] for img_metas in data['img_metas']]
img_metas = data['img_metas'][0]
return img_metas
def torch2onnx(args, model):
img_metas = getConfig(args.img, model)
model.forward = model.forward_dummy
model.to(device)
input_names = ["input"] # 模型输入的name
# output_names = ["output","prob"] # 模型输出的name
from torch.autograd import Variable
input = cv2.imread(args.img)
(new_h,new_w)=(1024,1024) # 配置文件
h, w = input.shape[:2]
img_mmcv_scale_factor = max(new_h, new_w) / max(h, w)
(new_h, new_w)=(img_mmcv_scale_factor*h,img_mmcv_scale_factor*w)
h_scale = new_h / h
w_scale = new_w / w
scale_factor = np.array([w_scale, h_scale, w_scale, h_scale,1],
dtype=np.float32)
inputr = cv2.resize(input, (int(new_w), int(new_h))) # hwc bgr
input = cv2.cvtColor(inputr, cv2.COLOR_BGR2RGB) # hwc rgb
# [0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
input = np.transpose(input, (2, 0, 1)).astype(np.float32) # chw rgb
# input=input/255.0
print("befor the input[0,0,0]:{}".format(input[0, 0, 0]))
print("the size of input[0,...] is {}".format(input[0, ...].shape))
print("the size of input[1,...] is {}".format(input[1, ...].shape))
print("the size of input[2,...] is {}".format(input[2, ...].shape))
input[0, ...] = (input[0, ...] - 123.675) / 58.395 # la
input[1, ...] = (input[1, ...] - 116.28) / 57.12
input[2, ...] = (input[2, ...] - 103.53) / 57.375
# 'mean': array([123.675, 116.28, 103.53], dtype=float32), 'std': array([58.395, 57.12, 57.375], dtype=float32)
print("after input[0,0,0]:{}".format(input[0, 0, 0]))
now_image1 = Variable(torch.from_numpy(input))
dummy_input = now_image1.unsqueeze(0).to(device)
# vutils.save_image(dummy_input, r'G:\mmrotate\mmrotate\models\detectors\dummy_input.jpg', normalize=True)
print("====", dummy_input, type(dummy_input))
torch.onnx.export(model, dummy_input, args.onnx_model_path, input_names=input_names,
export_params=True,
keep_initializers_as_inputs=True,
do_constant_folding=True,
verbose=False,
opset_version=11)
example_model = get_example(args.onnx_model_path)
session = onnxruntime.InferenceSession(example_model)
input_name = session.get_inputs()[0].name
result = session.run([], {input_name: dummy_input.data.cpu().numpy()})
print("outs=", result)
a0 = torch.tensor(result[0]).to(device)
a1 = torch.tensor(result[1]).to(device)
a2 = torch.tensor(result[2]).to(device)
a3 = torch.tensor(result[3]).to(device)
a4 = torch.tensor(result[4]).to(device)
a = [a0, a1, a2, a3, a4]
b0 = torch.tensor(result[5]).to(device)
b1 = torch.tensor(result[6]).to(device)
b2 = torch.tensor(result[7]).to(device)
b3 = torch.tensor(result[8]).to(device)
b4 = torch.tensor(result[9]).to(device)
b = [b0, b1, b2, b3, b4]
outs = (a, b)
c0 = torch.tensor(result[10]).to(device)
b0_scale_factor = c0.new_tensor(scale_factor)
b0_scale_factor= c0 / b0_scale_factor
c0 = b0_scale_factor
c1 = torch.tensor(result[11]).to(device)
c2 = torch.tensor(result[12]).to(device)
c3 = torch.tensor(result[13]).to(device)
c4 = torch.tensor(result[14]).to(device)
c = [c0, c1, c2, c3, c4]
c = [c[idx] / item.new_tensor(scale_factor) for idx,item in enumerate(c)]
rois = [c]
result_ = model.simple_test_onnx(img_metas, outs, rois, False)
model.show_result(
args.img, result_[0], score_thr=args.score_thr, out_file=args.onnxoutput)
def main():
"""Test a single image."""
parser = ArgumentParser()
parser.add_argument('--img', default=r"F:\mmrotate\demo\demo.jpg",
help='Image file')
parser.add_argument('--config', default=r"F:\mmrotate\configs\kfiou\r3det_kfiou_ln_r50_fpn_1x_dota_oc.py",
help='Config file')
parser.add_argument('--checkpoint', default=r"F:\mmrotate\model\r3det_kfiou_ln_r50_fpn_1x_dota_oc-8e7f049d.pth",
help='Checkpoint file')
parser.add_argument('--onnx_model_path',
default=r"F:\mmrotate\model\r3det_kfiou_ln_r50_fpn_1x_dota_oc-8e7f049d.onnx",
help='onnx_model_path')
parser.add_argument('--device', default='cuda:0', help='Device used for inference')
parser.add_argument('--output', default=r'ptsxj731533730.jpg', help='Output image')
parser.add_argument('--onnxoutput', default=r'onnxsxj731533730.jpg', help='Output image')
parser.add_argument('--score-thr', type=float, default=0.3, help='bbox score threshold')
args = parser.parse_args()
# build the model from a config file and a checkpoint file
model = init_detector(args.config, args.checkpoint, device=args.device)
# test a single image
result = inference_detector(model, args.img)
print("result=", result)
# show the results
model.show_result(
args.img, result, score_thr=args.score_thr, out_file=args.output)
torch2onnx(args, model)
#D:\Python39\Lib\site-packages\mmcv\ops
if __name__ == '__main__':
main()
第八步、比对一下数据; pth 模型输出 ,存在差异,但是结果图是正确的~
onnx模型测试图
第九步、先转mnn模型,测试,
D:\MNN\buildMinGW>python -m onnxsim G:\mmrotate\model\r3det_kfiou_ln_r50_fpn_1x_dota_oc-8e7f049d.onnx G:\mmrotate\model\r3det_kfiou_ln_r50_fpn_1x_dota_oc-8e7f049d_sim.onnx
Simplifying...
Checking 0/3...
Checking 1/3...
Checking 2/3...
Ok!
D:\MNN\buildMinGW>MNNConvert -f ONNX --modelFile G:\mmrotate\model\r3det_kfiou_ln_r50_fpn_1x_dota_oc-8e7f049d_sim.onnx --MNNModel G:\mmrotate\model\r3det_kfiou_ln_r50_fpn_1x_dota_oc-8e7f049d_sim.mnn --bizCode MNN
Start to Convert Other Model Format To MNN Model...
[11:38:18] D:\MNN\tools\converter\source\onnx\onnxConverter.cpp:30: ONNX Model ir version: 6
Start to Optimize the MNN Net...
inputTensors : [ input, ]
outputTensors: [ 1233, 1406, 1579, 1752, 1925, 1962, 1963, 1980, 1981, 1998, 1999, 2016, 2017, 2034, 2035, ]
Converted Success!
先完成第一步,数据对上
py的onnx输出结果
测试代码 ,使用mnn的数据输出 只用前5个数据比对一下就好
#include <iostream>
#include <ostream>
#include <random>
#include <vector>
#include <opencv2/opencv.hpp>
#include <iostream>
#include<opencv2/core.hpp>
#include<opencv2/imgproc.hpp>
#include<opencv2/highgui.hpp>
#include<MNN/Interpreter.hpp>
#include<MNN/ImageProcess.hpp>
#define IMAGE_TARGET 1024
int main(int argc, char **argv) {
std::vector<std::vector<float>> vec_hm, vec_wh, vec_reg, vec_cls_theta, vec_hmax;
cv::Mat img = cv::imread("G:\\mmrotate\\demo\\demo.jpg");
int img_width = img.cols;
int img_height = img.rows;
std::vector<float> meanVals ={ - 123.675f*(1.0f / 58.395), -116.28f*(1.0f / 57.12) , -103.53f*(1.0f / 57.375)};;
std::vector<float> normVals= { 1.0f / 58.395,1.0f / 57.12,1.0f / 57.375};
cv::Mat img_color;
cv::cvtColor(img.clone(),img_color,cv::COLOR_BGR2RGB);
cv::Mat img_resized;
cv::resize(img_color, img_resized, cv::Size(IMAGE_TARGET, IMAGE_TARGET));
auto net = std::shared_ptr<MNN::Interpreter>(MNN::Interpreter::createFromFile("G:\\mmrotate\\model\\r3det_kfiou_ln_r50_fpn_1x_dota_oc-8e7f049d_sim.mnn"));//创建解释器
std::cout << "Interpreter created" << std::endl;
MNN::ScheduleConfig config;
config.numThread = 8;
config.type = MNN_FORWARD_CPU;
auto session = net->createSession(config);//创建session
std::cout << "session created" << std::endl;
auto inTensor = net->getSessionInput(session, NULL);
auto outTensor = net->getSessionInput(session, NULL);
auto _Tensor = MNN::Tensor::create<float>({1,3,IMAGE_TARGET,IMAGE_TARGET}, NULL, MNN::Tensor::CAFFE);
if(_Tensor->elementSize()!=3*IMAGE_TARGET*IMAGE_TARGET)
{
std::cout<<_Tensor->elementSize()<<" "<<img_resized.channels()*img_resized.cols*img_resized.rows<<std::endl;
std::cout<<"input shape not equal image shape"<<std::endl;
return -1;
}
std::vector<cv::Mat> rgbChannels(3);
cv::split(img_resized, rgbChannels);
for (auto i = 0; i < rgbChannels.size(); i++) {
rgbChannels[i].convertTo(rgbChannels[i], CV_32FC1, normVals[i], meanVals[i]);
for(int j=0;j<rgbChannels[i].rows;j++) {
for (int k = 0; k < rgbChannels[i].cols; k++) {
_Tensor->host<float>()[i*IMAGE_TARGET*IMAGE_TARGET+j*IMAGE_TARGET+k] =rgbChannels[i].at<float>(j, k);
//printf("%f ",rgbChannels[i].at<float>(j, k)); //debug 比對圖片數據
}
}
}
inTensor->copyFromHostTensor(_Tensor);
//推理
net->runSession(session);
std::cout<<std::endl;
auto rois_net_a0= net->getSessionOutput(session, "1962");
MNN::Tensor rois_tensor_a0(rois_net_a0, rois_net_a0->getDimensionType());
rois_net_a0->copyToHostTensor(&rois_tensor_a0);
auto rois_ptr_a0 = rois_tensor_a0.host<float>();
std::cout<<"1962 = "<<rois_tensor_a0.height()<<" "<<rois_tensor_a0.width()<<" "<<rois_tensor_a0.channel()<<" "<<rois_tensor_a0.elementSize()<<std::endl;
for (int i = 0; i < rois_tensor_a0.elementSize(); i++) {
if(i==5) break;
std::cout<<rois_ptr_a0[i]<<" ";
}
std::cout<<std::endl;
auto rois_net_a1= net->getSessionOutput(session, "1980");
MNN::Tensor rois_tensor_a1(rois_net_a1, rois_net_a1->getDimensionType());
rois_net_a1->copyToHostTensor(&rois_tensor_a1);
auto rois_ptr_a1 = rois_tensor_a1.host<float>();
std::cout<<"1980 = "<<rois_tensor_a1.height()<<" "<<rois_tensor_a1.width()<<" "<<rois_tensor_a1.channel()<<" "<<rois_tensor_a1.elementSize()<<std::endl;
for (int i = 0; i < rois_tensor_a1.elementSize(); i++) {
if(i==5) break;
std::cout<<rois_ptr_a1[i]<<" ";
}
std::cout<<std::endl;
auto rois_net_a2= net->getSessionOutput(session, "1998");
MNN::Tensor rois_tensor_a2(rois_net_a2, rois_net_a2->getDimensionType());
rois_net_a2->copyToHostTensor(&rois_tensor_a2);
auto rois_ptr_a2 = rois_tensor_a2.host<float>();
std::cout<<"1998 = "<<rois_tensor_a2.height()<<" "<<rois_tensor_a2.width()<<" "<<rois_tensor_a2.channel()<<" "<<rois_tensor_a2.elementSize()<<std::endl;
for (int i = 0; i < rois_tensor_a2.elementSize(); i++) {
if(i==5) break;
std::cout<<rois_ptr_a2[i]<<" ";
}
std::cout<<std::endl;
auto rois_net_a3= net->getSessionOutput(session, "2016");
MNN::Tensor rois_tensor_a3(rois_net_a3, rois_net_a3->getDimensionType());
rois_net_a3->copyToHostTensor(&rois_tensor_a3);
auto rois_ptr_a3 = rois_tensor_a3.host<float>();
std::cout<<"2017 = "<<rois_tensor_a3.height()<<" "<<rois_tensor_a3.width()<<" "<<rois_tensor_a3.channel()<<" "<<rois_tensor_a3.elementSize()<<std::endl;
for (int i = 0; i < rois_tensor_a3.elementSize(); i++) {
if(i==5) break;
std::cout<<rois_ptr_a3[i]<<" ";
}
std::cout<<std::endl;
auto rois_net_a4= net->getSessionOutput(session, "2034");
MNN::Tensor rois_tensor_a4(rois_net_a4, rois_net_a4->getDimensionType());
rois_net_a4->copyToHostTensor(&rois_tensor_a4);
auto rois_ptr_a4 = rois_tensor_a4.host<float>();
std::cout<<"2034 = "<<rois_tensor_a4.height()<<" "<<rois_tensor_a4.width()<<" "<<rois_tensor_a4.channel()<<" "<<rois_tensor_a4.elementSize()<<std::endl;
for (int i = 0; i < rois_tensor_a4.elementSize(); i++) {
if(i==5) break;
std::cout<<rois_ptr_a4[i]<<" ";
}
std::cout<<std::endl;
auto rois_net_b0= net->getSessionOutput(session, "1963");
MNN::Tensor rois_tensor_b0(rois_net_b0, rois_net_b0->getDimensionType());
rois_net_b0->copyToHostTensor(&rois_tensor_b0);
auto rois_ptr_b0 = rois_tensor_b0.host<float>();
std::cout<<"1963 = "<<rois_tensor_b0.height()<<" "<<rois_tensor_b0.width()<<" "<<rois_tensor_b0.channel()<<" "<<rois_tensor_b0.elementSize()<<std::endl;
for (int i = 0; i < rois_tensor_b0.elementSize(); i++) {
if(i==5) break;
std::cout<<rois_ptr_b0[i]<<" ";
}
std::cout<<std::endl;
auto rois_net_b1= net->getSessionOutput(session, "1981");
MNN::Tensor rois_tensor_b1(rois_net_b1, rois_net_b1->getDimensionType());
rois_net_b1->copyToHostTensor(&rois_tensor_b1);
auto rois_ptr_b1 = rois_tensor_b1.host<float>();
std::cout<<"1981 = "<<rois_tensor_b1.height()<<" "<<rois_tensor_b1.width()<<" "<<rois_tensor_b1.channel()<<" "<<rois_tensor_b1.elementSize()<<std::endl;
for (int i = 0; i < rois_tensor_b1.elementSize(); i++) {
if(i==5) break;
std::cout<<rois_ptr_b1[i]<<" ";
}
std::cout<<std::endl;
auto rois_net_b2= net->getSessionOutput(session, "1999");
MNN::Tensor rois_tensor_b2(rois_net_b2, rois_net_b2->getDimensionType());
rois_net_b2->copyToHostTensor(&rois_tensor_b2);
auto rois_ptr_b2 = rois_tensor_b2.host<float>();
std::cout<<"1999 = "<<rois_tensor_b2.height()<<" "<<rois_tensor_b2.width()<<" "<<rois_tensor_b2.channel()<<" "<<rois_tensor_b2.elementSize()<<std::endl;
for (int i = 0; i < rois_tensor_b2.elementSize(); i++) {
if(i==5) break;
std::cout<<rois_ptr_b2[i]<<" ";
}
std::cout<<std::endl;
auto rois_net_b3= net->getSessionOutput(session, "2017");
MNN::Tensor rois_tensor_b3(rois_net_b3, rois_net_b3->getDimensionType());
rois_net_b3->copyToHostTensor(&rois_tensor_b3);
auto rois_ptr_b3 = rois_tensor_b3.host<float>();
std::cout<<"2017 = "<<rois_tensor_b3.height()<<" "<<rois_tensor_b3.width()<<" "<<rois_tensor_b3.channel()<<" "<<rois_tensor_b3.elementSize()<<std::endl;
for (int i = 0; i < rois_tensor_b3.elementSize(); i++) {
if(i==5) break;
std::cout<<rois_ptr_b3[i]<<" ";
}
std::cout<<std::endl;
auto rois_net_b4= net->getSessionOutput(session, "2035");
MNN::Tensor rois_tensor_b4(rois_net_b4, rois_net_b4->getDimensionType());
rois_net_b4->copyToHostTensor(&rois_tensor_b4);
auto rois_ptr_b4 = rois_tensor_b4.host<float>();
std::cout<<"2035 = "<<rois_tensor_b4.height()<<" "<<rois_tensor_b4.width()<<" "<<rois_tensor_b4.channel()<<" "<<rois_tensor_b4.elementSize()<<std::endl;
for (int i = 0; i < rois_tensor_b4.elementSize(); i++) {
if(i==5) break;
std::cout<<rois_ptr_b4[i]<<" ";
}
std::cout<<std::endl;
auto rois_net_c0= net->getSessionOutput(session, "1233");
MNN::Tensor rois_tensor_c0(rois_net_c0, rois_net_c0->getDimensionType());
rois_net_c0->copyToHostTensor(&rois_tensor_c0);
auto rois_ptr_c0 = rois_tensor_c0.host<float>();
std::cout<<"1233 = "<<rois_tensor_c0.height()<<" "<<rois_tensor_c0.width()<<" "<<rois_tensor_c0.channel()<<" "<<rois_tensor_c0.elementSize()<<std::endl;
for (int i = 0; i < rois_tensor_c0.elementSize(); i++) {
if(i==5) break;
std::cout<<rois_ptr_c0[i]<<" ";
}
std::cout<<std::endl;
auto rois_net_c1= net->getSessionOutput(session, "1406");
MNN::Tensor rois_tensor_c1(rois_net_c1, rois_net_c1->getDimensionType());
rois_net_c1->copyToHostTensor(&rois_tensor_c1);
auto rois_ptr_c1 = rois_tensor_c1.host<float>();
std::cout<<"1406 = "<<rois_tensor_c1.height()<<" "<<rois_tensor_c1.width()<<" "<<rois_tensor_c1.channel()<<" "<<rois_tensor_c1.elementSize()<<std::endl;
for (int i = 0; i < rois_tensor_c1.elementSize(); i++) {
if(i==5) break;
std::cout<<rois_ptr_c1[i]<<" ";
}
std::cout<<std::endl;
auto rois_net_c2= net->getSessionOutput(session, "1579");
MNN::Tensor rois_tensor_c2(rois_net_c2, rois_net_c2->getDimensionType());
rois_net_c2->copyToHostTensor(&rois_tensor_c2);
auto rois_ptr_c2 = rois_tensor_c2.host<float>();
std::cout<<"1579 = "<<rois_tensor_c2.height()<<" "<<rois_tensor_c2.width()<<" "<<rois_tensor_c2.channel()<<" "<<rois_tensor_c2.elementSize()<<std::endl;
for (int i = 0; i < rois_tensor_c2.elementSize(); i++) {
if(i==5) break;
std::cout<<rois_ptr_c2[i]<<" ";
}
std::cout<<std::endl;
auto rois_net_c3= net->getSessionOutput(session, "1752");
MNN::Tensor rois_tensor_c3(rois_net_c3, rois_net_c3->getDimensionType());
rois_net_c3->copyToHostTensor(&rois_tensor_c3);
auto rois_ptr_c3 = rois_tensor_c3.host<float>();
std::cout<<"1752 = "<<rois_tensor_c3.height()<<" "<<rois_tensor_c3.width()<<" "<<rois_tensor_c3.channel()<<" "<<rois_tensor_c3.elementSize()<<std::endl;
for (int i = 0; i < rois_tensor_c3.elementSize(); i++) {
if(i==5) break;
std::cout<<rois_ptr_c3[i]<<" ";
}
std::cout<<std::endl;
auto rois_net_c4= net->getSessionOutput(session, "1925");
MNN::Tensor rois_tensor_c4(rois_net_c4, rois_net_c4->getDimensionType());
rois_net_c4->copyToHostTensor(&rois_tensor_c4);
auto rois_ptr_c4 = rois_tensor_c4.host<float>();
std::cout<<"1925 = "<<rois_tensor_c4.height()<<" "<<rois_tensor_c4.width()<<" "<<rois_tensor_c4.channel()<<" "<<rois_tensor_c4.elementSize()<<std::endl;
for (int i = 0; i < rois_tensor_c4.elementSize(); i++) {
if(i==5) break;
std::cout<<rois_ptr_c4[i]<<" ";
}
// 写的尽量不依赖MNN ,还要进行NCNN的转化
//cv::imshow("image", img);
// cv::imwrite("image.jpg", img);
// cv::waitKey(0);
return 0;
}
测试结果
F:\untitled12\cmake-build-debug\untiled2.exe
Interpreter created
session created
1962 = 128 128 15 245760
-4.39439 -5.24617 -5.18704 -5.12905 -4.93742
1980 = 64 64 15 61440
-4.21322 -4.90304 -4.8548 -4.88889 -4.98375
1998 = 32 32 15 15360
-4.14835 -4.77178 -4.73817 -4.63989 -4.54071
2017 = 16 16 15 3840
-4.25359 -5.01801 -5.07386 -5.17409 -5.20806
2034 = 8 8 15 960
-4.23796 -4.98971 -4.95354 -4.98515 -5.0024
1963 = 128 128 5 81920
-0.0302005 0.00219762 0.00354933 0.00171571 0.00321476
1981 = 64 64 5 20480
-0.0328103 0.0025497 -0.000417736 0.00785263 0.0128756
1999 = 32 32 5 5120
-0.0317866 0.00656122 0.0161173 0.0156595 0.0134422
2017 = 16 16 5 1280
-0.0194252 0.00759413 0.00278557 -0.00387253 -0.00116776
2035 = 8 8 5 320
-0.0312997 0.00519017 0.00391664 0.00136454 -0.000162137
1233 = 1 1 5 81920
-2.13289 -0.66669 21.7076 11.6278 -0.0438018
1406 = 1 1 5 20480
-0.9342 -1.13472 102.071 55.0583 -0.0763953
1579 = 1 1 5 5120
-6.1721 -4.72425 64.9247 79.673 0.716497
1752 = 1 1 5 1280
3.56645 -1.43359 217.386 93.2715 -0.111636
1925 = 1 1 5 320
-14.4982 -8.48447 415.77 186.24 -0.0219311
Process finished with exit code 0
第十步、完整的代码测试 模型
链接:https://pan.baidu.com/s/1lYkzuR85vLGixgtuhFceAA
提取码:u700
我使用的window11+mingw32+clion测试
cmakelists.txt
cmake_minimum_required(VERSION 3.10)
project(untiled2)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fopenmp -w")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -fopenmp -w")
set(CMAKE_CXX_STANDARD 11)
include_directories(${CMAKE_SOURCE_DIR}/include)
include_directories(${CMAKE_SOURCE_DIR}/include/MNN)
set(OpenCV_DIR "D:\\Opencv440\\buildMinGW")#改为mingw-bulid的位置
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/")
find_package(OpenCV REQUIRED)
add_library(libmnn-static STATIC IMPORTED cmake-build-debug/main.cpp cmake-build-debug/main.h)
set_target_properties(libmnn-static PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/lib/libMNN.a)
add_executable(untiled2 polyiou.cpp main.cpp )
target_link_libraries(untiled2 ${OpenCV_LIBS} libmnn-static)
测试目录
代码自己优化吧 其中polyio.h抄40、使用BBAVectors-Oriented-Object-Detection 进行旋转目标检测,并使用mnn和ncnn进行部署
#include <iostream>
#include <ostream>
#include <random>
#include <vector>
#include <opencv2/opencv.hpp>
#include<MNN/Interpreter.hpp>
#include<MNN/ImageProcess.hpp>
#include "polyiou.h"
#define IMAGE_TARGET 1024
struct Ploy {
float p1_0;
float p1_1;
float p2_0;
float p2_1;
float p3_0;
float p3_1;
float p4_0;
float p4_1;
Ploy() : p1_0(0), p1_1(0), p2_0(0), p2_1(0), p3_0(0), p3_1(0), p4_0(0), p4_1(0) {}
Ploy(float p1_0, float p1_1, float p2_0, float p2_1, float p3_0, float p3_1, float p4_0, float p4_1) : p1_0(p1_0),
p1_1(p1_1),
p2_0(p2_0),
p2_1(p2_1),
p3_0(p3_0),
p3_1(p3_1),
p4_0(p4_0),
p4_1(p4_1) {}
};
struct BBox {
int idx;
float conf;
Ploy ploy;
BBox() : idx(0), conf(0), ploy(0, 0, 0, 0, 0, 0, 0, 0) {}
BBox(int idx, float conf, Ploy ploy) : idx(idx), conf(conf), ploy(ploy) {}
};
double mysoftmax(double num) {
return exp(num);
}
double mysigmoid(double num) {
return 1 / (1 + exp(-num));
}
template<typename T>
void softmax(const typename ::std::vector<T> &v, typename ::std::vector<T> &s) {
double sum = 0.0;
transform(v.begin(), v.end(), s.begin(), mysoftmax);
sum = accumulate(s.begin(), s.end(), sum);
for (size_t i = 0; i < s.size(); ++i)
s.at(i) /= sum;
}
template<typename T>
void sigmoid(const typename ::std::vector<T> &v, typename ::std::vector<T> &s) {
transform(v.begin(), v.end(), s.begin(), mysigmoid);
}
void cls_score_softmax(std::vector<float> &vec_cls_scores, std::vector<float> &item_cls_scores) {
item_cls_scores = vec_cls_scores;
softmax(vec_cls_scores, item_cls_scores);
}
void cls_score_sigmoid(std::vector<float> &vec_cls_scores, std::vector<float> &item_cls_scores) {
item_cls_scores = vec_cls_scores;
sigmoid(vec_cls_scores, item_cls_scores);
}
void dim_permute(std::vector<float> vec_cls_scores, std::vector<float> &item_cls_score, int w_h_dim) {
for (int i = 0; i < w_h_dim; i++) {
for (int j = i; j < vec_cls_scores.size(); j += w_h_dim) {
item_cls_score.push_back(vec_cls_scores[j]);
}
}
}
void process_top_k(std::vector<float> scores, int top_K, std::vector<float> &scores_K, std::vector<int> &index_K) {
std::vector<int> idx(scores.size());
std::iota(idx.begin(), idx.end(), 0);
std::sort(idx.begin(), idx.end(),
[&scores](int index_1, int index_2) { return scores[index_1] > scores[index_2]; });
// 获取K值
int k_num = std::min<int>(scores.size(), top_K);
int idx_j = 0;
for (int j = 0; j < k_num; ++j) {
idx_j = idx[j];
index_K.push_back(idx_j);
scores_K.push_back(scores[idx_j]);
}
}
float norm_angle(float angle, std::string angle_range) {
if (angle_range == "oc") {
return angle;
} else if (angle_range == "le135") {
return fmod((angle + M_PI / 4), M_PI) - M_PI / 4;
} else if (angle_range == "le90") {
return fmod((angle + (M_PI) / 2), M_PI) - M_PI / 2;
}
std::cout << "Not yet implemented." << std::endl;
return 0;
}
void bbox_coder_decode(std::vector<float> top_k_anchors,
std::vector<float> top_k_bbox_pred,
std::vector<float> &bbox_coder,
int bbox_preds_channels,
int img_width,
int img_height,
float wh_ratio_clip = 16.0f / 1000.0f,
bool add_ctr_clamp = false,
int ctr_clamp = 32,
bool proj_xy = false,
std::string angle_range = "oc",
bool edge_swap = false) {
// G:\mmrotate\mmrotate\core\bbox\coder\delta_xywh_rbbox_coder.py
float dx_width;
float dy_height;
float dw;
float dh;
float gx;
float gy;
float ga;
for (int i = 0; i < top_k_bbox_pred.size(); i += bbox_preds_channels) {
float dx = top_k_bbox_pred[i];
float dy = top_k_bbox_pred[i + 1];
float dw = top_k_bbox_pred[i + 2];
float dh = top_k_bbox_pred[i + 3];
float da = top_k_bbox_pred[i + 4];
float px = top_k_anchors[i];
float py = top_k_anchors[i + 1];
float pw = top_k_anchors[i + 2];
float ph = top_k_anchors[i + 3];
float pa = top_k_anchors[i + 4];
float dx_width = pw * dx;
float dy_height = ph * dy;
float max_ratio = abs(log(wh_ratio_clip));
if (add_ctr_clamp) {
dx_width = (dx_width >= -ctr_clamp) ? dx_width : -ctr_clamp;
dx_width = (dx_width <= ctr_clamp) ? dx_width : ctr_clamp;
dy_height = (dy_height >= -ctr_clamp) ? dy_height : -ctr_clamp;
dy_height = (dy_height <= ctr_clamp) ? dy_height : ctr_clamp;
dw = (dw <= max_ratio) ? dw : max_ratio;
dh = (dh <= max_ratio) ? dh : max_ratio;
} else {
dw = (dw <= max_ratio) ? dw : max_ratio;
dw = (dw >= -max_ratio) ? dw : -max_ratio;
dh = (dh <= max_ratio) ? dh : max_ratio;
dh = (dh >= -max_ratio) ? dh : -max_ratio;
}
float gw = pw * exp(dw);
float gh = ph * exp(dh);
if (proj_xy) {
gx = dx * pw * cos(pa) - dy * ph * sin(pa) + px;
gy = dx * pw * sin(pa) + dy * ph * cos(pa) + py;
} else {
gx = px + dx_width;
gy = py + dy_height;
ga = norm_angle(pa + da, angle_range);
}
// if max_shape is not None:
{
gx = (gx >= 0) ? gx : 0;
gx = (gx <= img_width - 1) ? gx : img_width - 1;
gy = (gy >= 0) ? gy : 0;
gy = (gy <= img_height - 1) ? gy : img_height - 1;
}
if (edge_swap) {
float w_regular = gw > gh ? gw : gh;
float h_regular = gw > gh ? gh : gw;
float theta_regular = gw > gh ? ga : ga + M_PI / 2;
theta_regular = norm_angle(theta_regular, angle_range);
bbox_coder.push_back(gx);
bbox_coder.push_back(gy);
bbox_coder.push_back(gw);
bbox_coder.push_back(gh);
bbox_coder.push_back(ga);
} else {
bbox_coder.push_back(gx);
bbox_coder.push_back(gy);
bbox_coder.push_back(gw);
bbox_coder.push_back(gh);
bbox_coder.push_back(ga);
}
}
}
// 进行iou计算
float iou(Ploy &r1, Ploy &r2) {
std::vector<double> p;
p.push_back(r1.p1_0);
p.push_back(r1.p1_1);
p.push_back(r1.p2_0);
p.push_back(r1.p2_1);
p.push_back(r1.p3_0);
p.push_back(r1.p3_1);
p.push_back(r1.p4_0);
p.push_back(r1.p4_1);
std::vector<double> q;
q.push_back(r2.p1_0);
q.push_back(r2.p1_1);
q.push_back(r2.p2_0);
q.push_back(r2.p2_1);
q.push_back(r2.p3_0);
q.push_back(r2.p3_1);
q.push_back(r2.p4_0);
q.push_back(r2.p4_1);
double iou = iou_poly(p, q);
p.clear();
std::vector<double>().swap(p);
q.clear();
std::vector<double>().swap(q);
return iou;
}
// 进行nms计算
void single_class_non_max_suppression(std::vector<Ploy> ploys, std::vector<float> confs, std::vector<Ploy> &ans,
std::vector<int> &keep_idx, float conf_thresh, float iou_thresh) {
if (ploys.size() == 0) {
return;
}
std::vector<BBox> bboxes;
BBox bbox;
for (int i = 0; i < (int) ploys.size(); ++i) {
bboxes.push_back(BBox(i, confs[i], ploys[i]));
}
// 对bbox的conf进行降序排序
sort(bboxes.begin(), bboxes.end(), [&](const BBox &a, const BBox &b) {
return a.conf > b.conf;
});
while (!bboxes.empty()) {
bbox = bboxes[0];
if (bbox.conf < conf_thresh) {
break;
}
keep_idx.emplace_back(bbox.idx);
bboxes.erase(bboxes.begin());
// 让conf最高的bbox与其他剩余的bbox进行iou计算
int size = bboxes.size();
for (int i = 0; i < size; ++i) {
float iou_ans = iou(bbox.ploy, bboxes[i].ploy);
if (iou_ans > iou_thresh) {
bboxes.erase(bboxes.begin() + i);
size = bboxes.size();
i = i - 1;
}
}
}
for (const int number : keep_idx) {
ans.push_back(ploys[number]);
}
}
void convet_point(std::vector<float> mutil_point,
float &p1_0,
float &p1_1,
float &p2_0,
float &p2_1,
float &p3_0,
float &p3_1,
float &p4_0,
float &p4_1
) {
float xc = mutil_point[0];
float yc = mutil_point[1];
float w = mutil_point[2];
float h = mutil_point[3];
float ag = mutil_point[4];
float wx = w / 2 * cos(ag);
float wy = w / 2 * sin(ag);
float hx = -h / 2 * sin(ag);
float hy = h / 2 * cos(ag);
p1_0 = xc - wx - hx;
p1_1 = yc - wy - hy;
p2_0 = xc + wx - hx;
p2_1 = yc + wy - hy;
p3_0 = xc + wx + hx;
p3_1 = yc + wy + hy;
p4_0 = xc - wx + hx;
p4_1 = yc - wy + hy;
}
void ext_module_nms_rotated(std::vector<std::vector<float>> dim_mlvl_bbox,
std::vector<float> dim_mlvl_score,
std::vector<int> order_K,
std::vector<int> &keep_idx,
float nms_iou_thr,
bool multi_label = false) {
// nms.py
std::cout << dim_mlvl_bbox.size() << " " << " " << dim_mlvl_score.size() << std::endl;
std::vector<Ploy> pts0_item;
std::vector<Ploy> ans;
for (int i = 0; i < dim_mlvl_bbox.size(); i++) {
float p1_0 = 0, p1_1 = 0, p2_0 = 0, p2_1 = 0, p3_0 = 0, p3_1 = 0, p4_0 = 0, p4_1 = 0;
convet_point(dim_mlvl_bbox[i], p1_0, p1_1, p2_0, p2_1, p3_0, p3_1, p4_0, p4_1);
pts0_item.push_back(Ploy(p1_0, p1_1, p2_0, p2_1, p3_0, p3_1, p4_0, p4_1));
}
single_class_non_max_suppression(pts0_item, dim_mlvl_score, ans, keep_idx, 0.3, nms_iou_thr);
pts0_item.clear();
std::vector<Ploy>().swap(pts0_item);
ans.clear();
std::vector<Ploy>().swap(ans);
}
void nms_rotated(std::vector<std::vector<float>> dim_mlvl_bbox,
std::vector<float> dim_mlvl_score,
std::vector<int> &keep_inds,
float nms_iou_thr,
bool clockwise = true) {
if (dim_mlvl_bbox[0].size() == 0) {
return;
}
std::vector<int> order_K;
std::vector<float> scores_K;
process_top_k(dim_mlvl_score, dim_mlvl_score.size(), scores_K, order_K);
ext_module_nms_rotated(dim_mlvl_bbox, dim_mlvl_score, order_K, keep_inds, nms_iou_thr);
}
void multiclass_nms_rotated(std::vector<std::vector<float>> multi_bbox,
std::vector<std::vector<float>> mlvl_score,
std::vector<int> mlvl_data_shape,
std::vector<std::vector<float>> &keep_box,
std::vector<float> &keep_score,
std::vector<int> &keep_label,
float score_thr = 0.05,
float nms_iou_thr = 0.1,
int max_num = 2000,
bool score_factors = false,
bool return_inds = false) {
std::vector<std::vector<float>> dim_mlvl_bbox;
std::vector<float> temp_dim_mlvl_bbox;
std::vector<std::vector<float>> dets_;
std::vector<float> dim_mlvl_score;
std::vector<int> dim_mlvl_label;
std::vector<int> dim_mlvl_inds;
float max_coordinate = -1;
int num_classes = mlvl_score[0].size() - 1;
if (multi_bbox[0].size() > 5) { ;
} else { ;
}
for (int i = 0; i < mlvl_score.size(); i++) {
int length = mlvl_score[i].size() - 1;
for (int j = 0; j < length; j++) {
if (mlvl_score[i][j] > score_thr) {
dim_mlvl_score.push_back(mlvl_score[i][j]);
dim_mlvl_inds.push_back(i * length + j);
dim_mlvl_label.push_back(j);
auto item = multi_bbox[(i * length + j) / num_classes];
auto maxPosition = max_element(item.begin(), item.end());
max_coordinate = std::max(max_coordinate, item[maxPosition - item.begin()]);
dim_mlvl_bbox.push_back(item);
}
}
}
if (dim_mlvl_bbox.size() == 0) {
for (int i = 0; i < dim_mlvl_bbox.size(); i++) {
for (int j = 0; j < dim_mlvl_bbox[i].size(); j++) {
temp_dim_mlvl_bbox.push_back(dim_mlvl_bbox[i][j]);
}
temp_dim_mlvl_bbox.push_back(dim_mlvl_score[i]);
dets_.push_back(temp_dim_mlvl_bbox);
temp_dim_mlvl_bbox.clear();
std::vector<float>().swap(temp_dim_mlvl_bbox);
}
if (return_inds) {
return; //dets, labels, inds
} else {
return;//dets, labels, inds
}
}
std::vector<int> keep;
nms_rotated(dim_mlvl_bbox, dim_mlvl_score, keep, nms_iou_thr);
std::cout << "kip_dim= " << keep.size() << std::endl;
if (max_num > 0) {
if (keep.size() > max_num) {
keep.resize(max_num);
}
}
for (int i = 0; i < keep.size(); i++) {
keep_box.push_back(dim_mlvl_bbox[keep[i]]);
keep_score.push_back(dim_mlvl_score[keep[i]]);
keep_label.push_back(dim_mlvl_label[keep[i]]);
}
std::cout << keep_box.size() << " " << keep_score.size() << " " << keep_label.size() << std::endl;
dim_mlvl_bbox.clear();
std::vector<std::vector<float>>().swap(dim_mlvl_bbox);
temp_dim_mlvl_bbox.clear();
std::vector<float>().swap(temp_dim_mlvl_bbox);
dets_.clear();
std::vector<std::vector<float>>().swap(dets_);
dim_mlvl_score.clear();
std::vector<float>().swap(dim_mlvl_score);
dim_mlvl_label.clear();
std::vector<int>().swap(dim_mlvl_label);
dim_mlvl_inds.clear();
std::vector<int>().swap(dim_mlvl_inds);
}
void get_bboxes_single(
std::vector<std::vector<float>> vec_cls_scores,
std::vector<std::vector<float>> vec_bbox_preds,
std::vector<std::vector<float>> vec_rois,
std::vector<int> scores_shape_0,
std::vector<std::vector<float>> &keep_box,
std::vector<float> &keep_score,
std::vector<int> &keep_label,
int img_width,
int img_height,
int nms_pre,
int cls_out_channels,
int bbox_preds_channels,
int rois_channels,
bool rescale,
bool with_nms,
bool use_sigmoid_cls,
float scale_factor[],
float score_thr,
float iou_thr,
int max_pre_img) {
std::vector<std::vector<float>> mlvl_bboxes;
std::vector<std::vector<float>> mlvl_scores;
std::vector<float> item_cls_score;
std::vector<float> item_bbox_pred;
std::vector<float> item_s_cls_score;
std::vector<int> topk_inds;
std::vector<float> scores_K;
std::vector<float> max_scores;
std::vector<float> top_k_anchors;
std::vector<float> top_k_bbox_pred;
std::vector<float> top_k_scores;
std::vector<float> bbox_coder;
std::vector<std::vector<float>> mlvl_bbox;
std::vector<std::vector<float>> mlvl_score;
std::vector<int> mlvl_data_shape;
std::vector<float> item_temp;
for (int i = 0; i < vec_cls_scores.size(); i++) {
dim_permute(vec_cls_scores[i], item_cls_score, vec_cls_scores[i].size() / cls_out_channels); //1,2,0
dim_permute(vec_bbox_preds[i], item_bbox_pred, vec_bbox_preds[i].size() / bbox_preds_channels); //1,2,0
//item_cls_score 16384 15 仍然拉伸成1维数据
// item_bbox_pred 5 仍然拉伸成1维数据
if (use_sigmoid_cls) {
cls_score_sigmoid(item_cls_score, item_s_cls_score);
} else {
cls_score_softmax(item_cls_score, item_s_cls_score);
}
if (nms_pre > 0 && scores_shape_0[i] > nms_pre) {
if (use_sigmoid_cls) {
for (int j = 0; j < item_s_cls_score.size() / cls_out_channels; j++) {
auto maxPosition = max_element(item_s_cls_score.begin() + j * cls_out_channels,
item_s_cls_score.begin() + (j + 1) * cls_out_channels);
max_scores.push_back(item_s_cls_score[maxPosition - item_s_cls_score.begin()]);
}
process_top_k(max_scores, nms_pre, scores_K, topk_inds);
for (int m = 0; m < topk_inds.size(); m++) {
int index = topk_inds[m];
for (int n = 0; n < rois_channels; n++) {
top_k_anchors.push_back(vec_rois[i][index * rois_channels + n]);
}
for (int n = 0; n < bbox_preds_channels; n++) {
top_k_bbox_pred.push_back(item_bbox_pred[index * bbox_preds_channels + n]);
}
for (int n = 0; n < cls_out_channels; n++) {
top_k_scores.push_back(item_s_cls_score[index * cls_out_channels + n]);
}
}
topk_inds.clear();
std::vector<int>().swap(topk_inds);
scores_K.clear();
std::vector<float>().swap(scores_K);
max_scores.clear();
std::vector<float>().swap(max_scores);
}
mlvl_data_shape.push_back(nms_pre);
} else {
top_k_anchors = vec_rois[i];
top_k_bbox_pred = item_bbox_pred;
top_k_scores = item_s_cls_score;
mlvl_data_shape.push_back(scores_shape_0[i]);
}
bbox_coder_decode(top_k_anchors, top_k_bbox_pred, bbox_coder, bbox_preds_channels, img_width, img_height);
mlvl_bbox.push_back(bbox_coder);
mlvl_score.push_back(top_k_scores);
top_k_anchors.clear();
std::vector<float>().swap(top_k_anchors);
bbox_coder.clear();
std::vector<float>().swap(bbox_coder);
top_k_scores.clear();
std::vector<float>().swap(top_k_scores);
top_k_bbox_pred.clear();
std::vector<float>().swap(top_k_bbox_pred);
item_cls_score.clear();
std::vector<float>().swap(item_cls_score);
item_bbox_pred.clear();
std::vector<float>().swap(item_bbox_pred);
item_s_cls_score.clear();
std::vector<float>().swap(item_s_cls_score);
}
mlvl_bboxes = mlvl_bbox;
mlvl_scores = mlvl_score;
if (rescale) {
mlvl_bboxes.clear();
std::vector<std::vector<float>>().swap(mlvl_bboxes);
// angle should not be rescaled
for (int i = 0; i < mlvl_bbox.size(); i++) {
for (int j = 0; j < mlvl_bbox[i].size(); j += bbox_preds_channels) {
for (int k = 0; k < bbox_preds_channels - 1; k++) {
item_temp.push_back(mlvl_bbox[i][j + k] / scale_factor[k]);
}
item_temp.push_back(mlvl_bbox[i][j + bbox_preds_channels - 1]);
}
mlvl_bboxes.push_back(item_temp);
item_temp.clear();
std::vector<float>().swap(item_temp);
}
}
if (use_sigmoid_cls) {
mlvl_scores.clear();
std::vector<std::vector<float>>().swap(mlvl_scores);
for (int i = 0; i < mlvl_score.size(); i++) {
for (int j = 0; j < mlvl_score[i].size(); j += cls_out_channels) {
for (int k = 0; k < cls_out_channels; k++) {
item_temp.push_back(mlvl_score[i][j + k]);
};
item_temp.push_back(0);
}
mlvl_scores.push_back(item_temp);
item_temp.clear();
std::vector<float>().swap(item_temp);
}
cls_out_channels = cls_out_channels + 1;
}
mlvl_bbox.clear();
std::vector<std::vector<float>>().swap(mlvl_bbox);
//cat data
for (int i = 0; i < mlvl_bboxes.size(); i++) {
for (int j = 0; j < mlvl_bboxes[i].size(); j += bbox_preds_channels) {
for (int k = 0; k < bbox_preds_channels; k++) {
item_temp.push_back(mlvl_bboxes[i][j + k]);
}
mlvl_bbox.push_back(item_temp);
item_temp.clear();
std::vector<float>().swap(item_temp);
}
}
mlvl_score.clear();
std::vector<std::vector<float>>().swap(mlvl_score);
for (int i = 0; i < mlvl_scores.size(); i++) {
for (int j = 0; j < mlvl_scores[i].size(); j += cls_out_channels) { // 扩展了0维空间
for (int k = 0; k < cls_out_channels; k++) {
item_temp.push_back(mlvl_scores[i][j + k]);
}
mlvl_score.push_back(item_temp);
item_temp.clear();
std::vector<float>().swap(item_temp);
}
}
if (with_nms) {
multiclass_nms_rotated(mlvl_bbox,
mlvl_score,
mlvl_data_shape,
keep_box,
keep_score,
keep_label,
score_thr,
iou_thr,
max_pre_img);
} else {
// 引用已经回传数据
}
item_cls_score.clear(); //有点习惯了 释放,其实局部变量没有必要
std::vector<float>().swap(item_cls_score);
item_bbox_pred.clear();
std::vector<float>().swap(item_bbox_pred);
item_s_cls_score.clear();
std::vector<float>().swap(item_s_cls_score);
topk_inds.clear();
std::vector<int>().swap(topk_inds);
scores_K.clear();
std::vector<float>().swap(scores_K);
max_scores.clear();
std::vector<float>().swap(max_scores);
top_k_anchors.clear();
std::vector<float>().swap(top_k_anchors);
top_k_bbox_pred.clear();
std::vector<float>().swap(top_k_bbox_pred);
top_k_scores.clear();
std::vector<float>().swap(top_k_scores);
bbox_coder.clear();
std::vector<float>().swap(bbox_coder);
mlvl_bbox.clear();
std::vector<std::vector<float>>().swap(mlvl_bbox);
mlvl_score.clear();
std::vector<std::vector<float>>().swap(mlvl_score);
mlvl_data_shape.clear();
std::vector<int>().swap(mlvl_data_shape);
mlvl_bboxes.clear();
std::vector<std::vector<float>>().swap(mlvl_bboxes);
mlvl_scores.clear();
std::vector<std::vector<float>>().swap(mlvl_scores);
}
int main(int argc, char **argv) {
cv::Mat img = cv::imread("F:\\mmrotate\\demo\\demo.jpg");
const char *classes[] = {"plane", "baseball-diamond", "bridge", "ground-track-field",
"small-vehicle", "large-vehicle", "ship", "tennis-court",
"basketball-court", "storage-tank", "soccer-ball-field",
"roundabout", "harbor", "swimming-pool", "helicopter" };
std::vector<float> meanVals = {-123.675f * (1.0f / 58.395), -116.28f * (1.0f / 57.12), -103.53f * (1.0f / 57.375)};;
std::vector<float> normVals = {1.0f / 58.395, 1.0f / 57.12, 1.0f / 57.375};
cv::Mat img_color;
cv::cvtColor(img.clone(), img_color, cv::COLOR_BGR2RGB);
int new_h=1024.0;
int new_w=1024.0;
int img_width = img.cols;
int img_height = img.rows;
float img_mmcv_scale_factor = std::max(new_w*1.0f, new_h*1.0f) / std::max(img_height*1.0f, img_width*1.0f);
new_h=img_mmcv_scale_factor*img_height;
new_w=img_mmcv_scale_factor*img_width;
float h_scale = new_h / (img_height*1.0f);
float w_scale = new_w / (img_width*1.0f);
float scale_factor[] = {w_scale, h_scale, w_scale, h_scale};
cv::Mat img_resized;
cv::resize(img_color, img_resized, cv::Size(new_w, new_h));
auto net = std::shared_ptr<MNN::Interpreter>(MNN::Interpreter::createFromFile(
"F:\\mmrotate\\model\\r3det_kfiou_ln_r50_fpn_1x_dota_oc-8e7f049d_sim.mnn"));//创建解释器
std::cout << "Interpreter created" << std::endl;
MNN::ScheduleConfig config;
config.numThread = 8;
config.type = MNN_FORWARD_CPU;
auto session = net->createSession(config);//创建session
std::cout << "session created" << std::endl;
auto inTensor = net->getSessionInput(session, NULL);
auto outTensor = net->getSessionInput(session, NULL);
auto _Tensor = MNN::Tensor::create<float>({1, 3, new_w, new_h}, NULL, MNN::Tensor::CAFFE);
if (_Tensor->elementSize() != 3 * new_w * new_h) {
std::cout << _Tensor->elementSize() << " " << img_resized.channels() * img_resized.cols * img_resized.rows
<< std::endl;
std::cout << "input shape not equal image shape" << std::endl;
return -1;
}
std::vector<cv::Mat> rgbChannels(3);
cv::split(img_resized, rgbChannels);
for (auto i = 0; i < rgbChannels.size(); i++) {
rgbChannels[i].convertTo(rgbChannels[i], CV_32FC1, normVals[i], meanVals[i]);
for (int j = 0; j < rgbChannels[i].rows; j++) {
for (int k = 0; k < rgbChannels[i].cols; k++) {
_Tensor->host<float>()[i * new_w * new_h + j * new_w +
k] = rgbChannels[i].at<float>(j, k);
//printf("%f ",rgbChannels[i].at<float>(j, k)); //debug 比對圖片數據
}
}
}
inTensor->copyFromHostTensor(_Tensor);
//推理
net->runSession(session);
char* cls_id0="1962";
char* cls_id1="1980";
char* cls_id2="1998";
char* cls_id3="2016";
char* cls_id4="2034";
char* bbox_id0="1963";
char* bbox_id1="1981";
char *bbox_id2="1999";
char *bbox_id3="2017";
char *bbox_id4="2035";
char* rois_id0="1233";
char* rois_id1="1406";
char *rois_id2="1579";
char *rois_id3="1752";
char *rois_id4="1925";
/*
char* cls_id0="1967";//"1962";
char* cls_id1="1985";//"1980";
char* cls_id2="2003";//"1998";
char* cls_id3="2021";//"2016";
char* cls_id4="2039";//"2034";
char* bbox_id0="1968";//"1963";
char* bbox_id1="1986";//"1981";
char *bbox_id2="2004";//"1999";
char *bbox_id3="2022";//"2017";
char *bbox_id4="2040";//"2035";
char* rois_id0="1238";//"1233";
char* rois_id1="1411";//"1406";
char *rois_id2="1584";//"1579";
char *rois_id3="1757";//"1752";
char *rois_id4="1930";//"1925";
*/
std::vector<std::vector<float>> vec_cls_scores;
std::vector<int> scores_shape_0;
std::vector<float> vec_temp;
int cls_out_channels = 0;
std::cout << std::endl;
auto cls_scores_a0 = net->getSessionOutput(session, cls_id0);
MNN::Tensor cls_scores_tensor_a0(cls_scores_a0, cls_scores_a0->getDimensionType());
cls_scores_a0->copyToHostTensor(&cls_scores_tensor_a0);
auto cls_scores_ptr_a0 = cls_scores_tensor_a0.host<float>();
std::cout << std::string(cls_id0) << cls_scores_tensor_a0.height() << " " << cls_scores_tensor_a0.width() << " "
<< cls_scores_tensor_a0.channel() << " " << cls_scores_tensor_a0.elementSize() << std::endl;
cls_out_channels = cls_scores_tensor_a0.channel();
for (int i = 0; i < cls_scores_tensor_a0.elementSize(); i++) {
vec_temp.push_back(cls_scores_ptr_a0[i]);
}
scores_shape_0.push_back(cls_scores_tensor_a0.height() * cls_scores_tensor_a0.width());
vec_cls_scores.push_back(vec_temp);
vec_temp.clear();
std::vector<float>().swap(vec_temp);
std::cout << std::endl;
auto cls_scores_a1 = net->getSessionOutput(session, cls_id1);
MNN::Tensor cls_scores_tensor_a1(cls_scores_a1, cls_scores_a1->getDimensionType());
cls_scores_a1->copyToHostTensor(&cls_scores_tensor_a1);
auto cls_scores_ptr_a1 = cls_scores_tensor_a1.host<float>();
std::cout << std::string(cls_id1) << cls_scores_tensor_a1.height() << " " << cls_scores_tensor_a1.width() << " "
<< cls_scores_tensor_a1.channel() << " " << cls_scores_tensor_a1.elementSize() << std::endl;
for (int i = 0; i < cls_scores_tensor_a1.elementSize(); i++) {
vec_temp.push_back(cls_scores_ptr_a1[i]);
}
scores_shape_0.push_back(cls_scores_tensor_a1.height() * cls_scores_tensor_a1.width());
vec_cls_scores.push_back(vec_temp);
vec_temp.clear();
std::vector<float>().swap(vec_temp);
std::cout << std::endl;
auto cls_scores_net_a2 = net->getSessionOutput(session, cls_id2);
MNN::Tensor cls_scores_tensor_a2(cls_scores_net_a2, cls_scores_net_a2->getDimensionType());
cls_scores_net_a2->copyToHostTensor(&cls_scores_tensor_a2);
auto cls_scores_ptr_a2 = cls_scores_tensor_a2.host<float>();
std::cout << std::string(cls_id2) << cls_scores_tensor_a2.height() << " " << cls_scores_tensor_a2.width() << " "
<< cls_scores_tensor_a2.channel() << " " << cls_scores_tensor_a2.elementSize() << std::endl;
for (int i = 0; i < cls_scores_tensor_a2.elementSize(); i++) {
vec_temp.push_back(cls_scores_ptr_a2[i]);
}
scores_shape_0.push_back(cls_scores_tensor_a2.height() * cls_scores_tensor_a2.width());
vec_cls_scores.push_back(vec_temp);
vec_temp.clear();
std::vector<float>().swap(vec_temp);
std::cout << std::endl;
auto cls_scores_net_a3 = net->getSessionOutput(session, cls_id3);
MNN::Tensor cls_scores_tensor_a3(cls_scores_net_a3, cls_scores_net_a3->getDimensionType());
cls_scores_net_a3->copyToHostTensor(&cls_scores_tensor_a3);
auto rois_ptr_a3 = cls_scores_tensor_a3.host<float>();
std::cout << std::string(cls_id3)<< cls_scores_tensor_a3.height() << " " << cls_scores_tensor_a3.width() << " "
<< cls_scores_tensor_a3.channel() << " " << cls_scores_tensor_a3.elementSize() << std::endl;
for (int i = 0; i < cls_scores_tensor_a3.elementSize(); i++) {
vec_temp.push_back(rois_ptr_a3[i]);
}
scores_shape_0.push_back(cls_scores_tensor_a3.height() * cls_scores_tensor_a3.width());
vec_cls_scores.push_back(vec_temp);
vec_temp.clear();
std::vector<float>().swap(vec_temp);
std::cout << std::endl;
auto cls_scores_net_a4 = net->getSessionOutput(session, cls_id4);
MNN::Tensor cls_scores_tensor_a4(cls_scores_net_a4, cls_scores_net_a4->getDimensionType());
cls_scores_net_a4->copyToHostTensor(&cls_scores_tensor_a4);
auto cls_scores_ptr_a4 = cls_scores_tensor_a4.host<float>();
std::cout << std::string(cls_id4) << cls_scores_tensor_a4.height() << " " << cls_scores_tensor_a4.width() << " "
<< cls_scores_tensor_a4.channel() << " " << cls_scores_tensor_a4.elementSize() << std::endl;
for (int i = 0; i < cls_scores_tensor_a4.elementSize(); i++) {
vec_temp.push_back(cls_scores_ptr_a4[i]);
}
scores_shape_0.push_back(cls_scores_tensor_a4.height() * cls_scores_tensor_a4.width());
vec_cls_scores.push_back(vec_temp);
vec_temp.clear();
std::vector<float>().swap(vec_temp);
std::vector<std::vector<float>> vec_bbox_preds;
int bbox_preds_channels = 0;
std::cout << std::endl;
auto bbox_preds_net_b0 = net->getSessionOutput(session, bbox_id0);
MNN::Tensor bbox_preds_tensor_b0(bbox_preds_net_b0, bbox_preds_net_b0->getDimensionType());
bbox_preds_net_b0->copyToHostTensor(&bbox_preds_tensor_b0);
auto rois_ptr_b0 = bbox_preds_tensor_b0.host<float>();
std::cout << std::string(bbox_id0) << bbox_preds_tensor_b0.height() << " " << bbox_preds_tensor_b0.width() << " "
<< bbox_preds_tensor_b0.channel() << " " << bbox_preds_tensor_b0.elementSize() << std::endl;
bbox_preds_channels = bbox_preds_tensor_b0.channel();
for (int i = 0; i < bbox_preds_tensor_b0.elementSize(); i++) {
vec_temp.push_back(rois_ptr_b0[i]);
}
vec_bbox_preds.push_back(vec_temp);
vec_temp.clear();
std::vector<float>().swap(vec_temp);
std::cout << std::endl;
auto vec_bbox_net_b1 = net->getSessionOutput(session, bbox_id1);
MNN::Tensor vec_bbox_tensor_b1(vec_bbox_net_b1, vec_bbox_net_b1->getDimensionType());
vec_bbox_net_b1->copyToHostTensor(&vec_bbox_tensor_b1);
auto vec_bbox_ptr_b1 = vec_bbox_tensor_b1.host<float>();
std::cout << std::string(bbox_id1) << vec_bbox_tensor_b1.height() << " " << vec_bbox_tensor_b1.width() << " "
<< vec_bbox_tensor_b1.channel() << " " << vec_bbox_tensor_b1.elementSize() << std::endl;
for (int i = 0; i < vec_bbox_tensor_b1.elementSize(); i++) {
vec_temp.push_back(vec_bbox_ptr_b1[i]);
}
vec_bbox_preds.push_back(vec_temp);
vec_temp.clear();
std::vector<float>().swap(vec_temp);
std::cout << std::endl;
auto vec_bbox_net_b2 = net->getSessionOutput(session, bbox_id2);
MNN::Tensor vec_bbox_tensor_b2(vec_bbox_net_b2, vec_bbox_net_b2->getDimensionType());
vec_bbox_net_b2->copyToHostTensor(&vec_bbox_tensor_b2);
auto rois_ptr_b2 = vec_bbox_tensor_b2.host<float>();
std::cout << std::string(bbox_id2) << vec_bbox_tensor_b2.height() << " " << vec_bbox_tensor_b2.width() << " "
<< vec_bbox_tensor_b2.channel() << " " << vec_bbox_tensor_b2.elementSize() << std::endl;
for (int i = 0; i < vec_bbox_tensor_b2.elementSize(); i++) {
vec_temp.push_back(rois_ptr_b2[i]);
}
vec_bbox_preds.push_back(vec_temp);
vec_temp.clear();
std::vector<float>().swap(vec_temp);
std::cout << std::endl;
auto bbox_preds_net_b3 = net->getSessionOutput(session, bbox_id3);
MNN::Tensor bbox_preds_tensor_b3(bbox_preds_net_b3, bbox_preds_net_b3->getDimensionType());
bbox_preds_net_b3->copyToHostTensor(&bbox_preds_tensor_b3);
auto bbox_preds_ptr_b3 = bbox_preds_tensor_b3.host<float>();
std::cout << std::string(bbox_id3) << bbox_preds_tensor_b3.height() << " " << bbox_preds_tensor_b3.width() << " "
<< bbox_preds_tensor_b3.channel() << " " << bbox_preds_tensor_b3.elementSize() << std::endl;
for (int i = 0; i < bbox_preds_tensor_b3.elementSize(); i++) {
vec_temp.push_back(bbox_preds_ptr_b3[i]);
}
vec_bbox_preds.push_back(vec_temp);
vec_temp.clear();
std::vector<float>().swap(vec_temp);
std::cout << std::endl;
auto bbox_preds_net_b4 = net->getSessionOutput(session, bbox_id4);
MNN::Tensor bbox_preds_tensor_b4(bbox_preds_net_b4, bbox_preds_net_b4->getDimensionType());
bbox_preds_net_b4->copyToHostTensor(&bbox_preds_tensor_b4);
auto bbox_preds_ptr_b4 = bbox_preds_tensor_b4.host<float>();
std::cout << std::string(bbox_id4) << bbox_preds_tensor_b4.height() << " " << bbox_preds_tensor_b4.width() << " "
<< bbox_preds_tensor_b4.channel() << " " << bbox_preds_tensor_b4.elementSize() << std::endl;
for (int i = 0; i < bbox_preds_tensor_b4.elementSize(); i++) {
vec_temp.push_back(bbox_preds_ptr_b4[i]);
}
vec_bbox_preds.push_back(vec_temp);
vec_temp.clear();
std::vector<float>().swap(vec_temp);
std::vector<std::vector<float>> vec_rois;
int rois_channels = 0;
std::cout << std::endl;
auto rois_net_c0 = net->getSessionOutput(session, rois_id0);
MNN::Tensor rois_tensor_c0(rois_net_c0, rois_net_c0->getDimensionType());
rois_net_c0->copyToHostTensor(&rois_tensor_c0);
auto rois_ptr_c0 = rois_tensor_c0.host<float>();
std::cout << std::string(rois_id0) << rois_tensor_c0.height() << " " << rois_tensor_c0.width() << " "
<< rois_tensor_c0.channel() << " " << rois_tensor_c0.elementSize() << std::endl;
rois_channels = rois_tensor_c0.channel();
for (int i = 0; i < rois_tensor_c0.elementSize(); i++) {
vec_temp.push_back(rois_ptr_c0[i]);
}
vec_rois.push_back(vec_temp);
vec_temp.clear();
std::vector<float>().swap(vec_temp);
std::cout << std::endl;
auto rois_net_c1 = net->getSessionOutput(session, rois_id1);
MNN::Tensor rois_tensor_c1(rois_net_c1, rois_net_c1->getDimensionType());
rois_net_c1->copyToHostTensor(&rois_tensor_c1);
auto rois_ptr_c1 = rois_tensor_c1.host<float>();
std::cout << std::string(rois_id1) << rois_tensor_c1.height() << " " << rois_tensor_c1.width() << " "
<< rois_tensor_c1.channel() << " " << rois_tensor_c1.elementSize() << std::endl;
for (int i = 0; i < rois_tensor_c1.elementSize(); i++) {
vec_temp.push_back(rois_ptr_c1[i]);
}
vec_rois.push_back(vec_temp);
vec_temp.clear();
std::vector<float>().swap(vec_temp);
std::cout << std::endl;
auto rois_net_c2 = net->getSessionOutput(session, rois_id2);
MNN::Tensor rois_tensor_c2(rois_net_c2, rois_net_c2->getDimensionType());
rois_net_c2->copyToHostTensor(&rois_tensor_c2);
auto rois_ptr_c2 = rois_tensor_c2.host<float>();
std::cout << std::string(rois_id2) << rois_tensor_c2.height() << " " << rois_tensor_c2.width() << " "
<< rois_tensor_c2.channel() << " " << rois_tensor_c2.elementSize() << std::endl;
for (int i = 0; i < rois_tensor_c2.elementSize(); i++) {
vec_temp.push_back(rois_ptr_c2[i]);
}
vec_rois.push_back(vec_temp);
vec_temp.clear();
std::vector<float>().swap(vec_temp);
std::cout << std::endl;
auto rois_net_c3 = net->getSessionOutput(session, rois_id3);
MNN::Tensor rois_tensor_c3(rois_net_c3, rois_net_c3->getDimensionType());
rois_net_c3->copyToHostTensor(&rois_tensor_c3);
auto rois_ptr_c3 = rois_tensor_c3.host<float>();
std::cout << std::string(rois_id3) << rois_tensor_c3.height() << " " << rois_tensor_c3.width() << " "
<< rois_tensor_c3.channel() << " " << rois_tensor_c3.elementSize() << std::endl;
for (int i = 0; i < rois_tensor_c3.elementSize(); i++) {
vec_temp.push_back(rois_ptr_c3[i]);
}
vec_rois.push_back(vec_temp);
vec_temp.clear();
std::vector<float>().swap(vec_temp);
std::cout << std::endl;
auto rois_net_c4 = net->getSessionOutput(session, rois_id4);
MNN::Tensor rois_tensor_c4(rois_net_c4, rois_net_c4->getDimensionType());
rois_net_c4->copyToHostTensor(&rois_tensor_c4);
auto rois_ptr_c4 = rois_tensor_c4.host<float>();
std::cout << std::string(rois_id4)<< rois_tensor_c4.height() << " " << rois_tensor_c4.width() << " "
<< rois_tensor_c4.channel() << " " << rois_tensor_c4.elementSize() << std::endl;
for (int i = 0; i < rois_tensor_c4.elementSize(); i++) {
vec_temp.push_back(rois_ptr_c4[i]);
}
vec_rois.push_back(vec_temp);
vec_temp.clear();
std::vector<float>().swap(vec_temp);
// 写的尽量不依赖MNN ,还要进行NCNN的转化
std::vector<int> keep;
std::vector<std::vector<float>> keep_box;
std::vector<float> keep_score;
std::vector<int> keep_label;
std::vector<Ploy> keep_box_dets;
int nms_pre = 2000;
int min_bbox_size = 0;
float score_thr = 0.05;
float iou_thr = 0.1;
int max_pre_img = 2000;
bool rescale = true;
bool with_nms = true;
bool use_sigmoid_cls = true;
get_bboxes_single(
vec_cls_scores,
vec_bbox_preds,
vec_rois,
scores_shape_0,
keep_box,
keep_score,
keep_label,
img_width,
img_height,
nms_pre,
cls_out_channels,
bbox_preds_channels,
rois_channels,
rescale,
with_nms,
use_sigmoid_cls,
scale_factor,
score_thr,
iou_thr,
max_pre_img);
float font_scale = 0.25;
cv::Scalar bbox_color = cv::Scalar(226, 43, 138);
cv::Scalar text_color = cv::Scalar(255, 255, 255);
std::vector<std::vector<cv::Point>> contours;
std::cout << keep_box.size() << std::endl;
for (int i = 0; i < keep_box.size(); i++) {
std::vector<cv::Point> contours_item;
float p1_0 = 0, p1_1 = 0, p2_0 = 0, p2_1 = 0, p3_0 = 0, p3_1 = 0, p4_0 = 0, p4_1 = 0, xc = 0, yc = 0;
convet_point(keep_box[i], p1_0, p1_1, p2_0, p2_1, p3_0, p3_1, p4_0, p4_1);
contours_item.push_back(cv::Point(p1_0, p1_1));
contours_item.push_back(cv::Point(p2_0, p2_1));
contours_item.push_back(cv::Point(p3_0, p3_1));
contours_item.push_back(cv::Point(p4_0, p4_1));
contours.push_back(contours_item);
xc = keep_box[i][0];
yc = keep_box[i][1];
cv::drawContours(img, contours, -1, bbox_color, 2);
char text[256];
sprintf(text, "%s %.2f%%", classes[keep_label[i]], keep_score[i]);
int baseLine = 0;
cv::Size label_size = cv::getTextSize(text, cv::FONT_HERSHEY_SIMPLEX, font_scale, 1, &baseLine);
int text_width = label_size.width;
int text_height = label_size.height;
cv::rectangle(img, cv::Point(int(xc), int(yc) - text_height - 2), cv::Point(int(xc) + text_width, int(yc) + 3),
cv::Scalar(0, 128, 0), -1);
cv::putText(img, text, cv::Point(int(xc), int(yc)),
cv::FONT_HERSHEY_SIMPLEX, font_scale, text_color);
contours.clear();
std::vector<std::vector<cv::Point>>().swap(contours);
}
cv::imshow("image", img);
cv::imwrite("image.jpg", img);
cv::waitKey(0);
return 0;
}
测试结果
对比结果
测试自己的训练结果
import mmcv
import numpy as np
import torch
from mmcv.ops import RoIPool
from mmcv.parallel import collate, scatter
from mmcv.runner import load_checkpoint
from mmdet.core import get_classes
from mmdet.datasets import replace_ImageToTensor
from mmdet.datasets.pipelines import Compose
from mmdet.models import build_detector
from argparse import ArgumentParser
from mmdet.apis import inference_detector, init_detector
import torch
# import trochvision
import torch.utils.data
import argparse
import onnxruntime
import os
import cv2
import numpy as np
from onnxruntime.datasets import get_example
import mmrotate # noqa: F401
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
def getConfig(imgs, model):
if isinstance(imgs, (list, tuple)):
is_batch = True
else:
imgs = [imgs]
is_batch = False
cfg = model.cfg
device = next(model.parameters()).device # model device
if isinstance(imgs[0], np.ndarray):
cfg = cfg.copy()
# set loading pipeline type
cfg.data.test.pipeline[0].type = 'LoadImageFromWebcam'
cfg.data.test.pipeline = replace_ImageToTensor(cfg.data.test.pipeline)
test_pipeline = Compose(cfg.data.test.pipeline)
datas = []
for img in imgs:
# prepare data
if isinstance(img, np.ndarray):
# directly add img
data = dict(img=img)
else:
# add information into dict
data = dict(img_info=dict(filename=img), img_prefix=None)
# build the data pipeline
data = test_pipeline(data)
datas.append(data)
data = collate(datas, samples_per_gpu=len(imgs))
# just get the actual data from DataContainer
data['img_metas'] = [img_metas.data[0] for img_metas in data['img_metas']]
img_metas = data['img_metas'][0]
return img_metas
def torch2onnx(args, model):
img_metas = getConfig(args.img, model)
model.forward = model.forward_dummy
model.to(device)
input_names = ["input"] # 模型输入的name
# output_names = ["output","prob"] # 模型输出的name
from torch.autograd import Variable
input = cv2.imread(args.img)
(new_h, new_w) = (1024, 1024) # 配置文件
h, w = input.shape[:2]
img_mmcv_scale_factor = max(new_h, new_w) / max(h, w)
(new_h, new_w) = (img_mmcv_scale_factor * h, img_mmcv_scale_factor * w)
h_scale = new_h / h
w_scale = new_w / w
scale_factor = np.array([w_scale, h_scale, w_scale, h_scale, 1],
dtype=np.float32)
inputr = cv2.resize(input, (int(new_w), int(new_h))) # hwc bgr
input = cv2.cvtColor(inputr, cv2.COLOR_BGR2RGB) # hwc rgb
# [0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
input = np.transpose(input, (2, 0, 1)).astype(np.float32) # chw rgb
# input=input/255.0
print("befor the input[0,0,0]:{}".format(input[0, 0, 0]))
print("the size of input[0,...] is {}".format(input[0, ...].shape))
print("the size of input[1,...] is {}".format(input[1, ...].shape))
print("the size of input[2,...] is {}".format(input[2, ...].shape))
input[0, ...] = (input[0, ...] - 123.675) / 58.395 # la
input[1, ...] = (input[1, ...] - 116.28) / 57.12
input[2, ...] = (input[2, ...] - 103.53) / 57.375
# 'mean': array([123.675, 116.28, 103.53], dtype=float32), 'std': array([58.395, 57.12, 57.375], dtype=float32)
print("after input[0,0,0]:{}".format(input[0, 0, 0]))
now_image1 = Variable(torch.from_numpy(input))
dummy_input = now_image1.unsqueeze(0).to(device)
# vutils.save_image(dummy_input, r'G:\mmrotate\mmrotate\models\detectors\dummy_input.jpg', normalize=True)
print("====", dummy_input, type(dummy_input))
torch.onnx.export(model, dummy_input, args.onnx_model_path, input_names=input_names,
export_params=True,
keep_initializers_as_inputs=True,
do_constant_folding=True,
verbose=False,
opset_version=11)
example_model = get_example(args.onnx_model_path)
session = onnxruntime.InferenceSession(example_model)
input_name = session.get_inputs()[0].name
result = session.run([], {input_name: dummy_input.data.cpu().numpy()})
print("outs=", result)
a0 = torch.tensor(result[0]).to(device)
a1 = torch.tensor(result[1]).to(device)
a2 = torch.tensor(result[2]).to(device)
a3 = torch.tensor(result[3]).to(device)
a4 = torch.tensor(result[4]).to(device)
a = [a0, a1, a2, a3, a4]
b0 = torch.tensor(result[5]).to(device)
b1 = torch.tensor(result[6]).to(device)
b2 = torch.tensor(result[7]).to(device)
b3 = torch.tensor(result[8]).to(device)
b4 = torch.tensor(result[9]).to(device)
b = [b0, b1, b2, b3, b4]
outs = (a, b)
c0 = torch.tensor(result[10]).to(device)
b0_scale_factor = c0.new_tensor(scale_factor)
b0_scale_factor = c0 / b0_scale_factor
c0 = b0_scale_factor
c1 = torch.tensor(result[11]).to(device)
c2 = torch.tensor(result[12]).to(device)
c3 = torch.tensor(result[13]).to(device)
c4 = torch.tensor(result[14]).to(device)
c = [c0, c1, c2, c3, c4]
c = [c[idx] / item.new_tensor(scale_factor) for idx, item in enumerate(c)]
rois = [c]
result_ = model.simple_test_onnx(img_metas, outs, rois, False)
model.show_result(
args.img, result_[0], score_thr=args.score_thr, out_file=args.onnxoutput)
def main():
"""Test a single image."""
parser = ArgumentParser()
parser.add_argument('--img', default=r"/home/ubuntu/CLionProjects/untitled8/3.png",
help='Image file')
parser.add_argument('--config', default=r"/home/ubuntu/mmrotate/configs/kfiou/r3det_kfiou_ln_r50_fpn_1x_dota_oc.py",
help='Config file')
parser.add_argument('--checkpoint', default=r"/home/ubuntu/Downloads/test_card/card_24.pth",
help='Checkpoint file')
parser.add_argument('--onnx_model_path',
default=r"/home/ubuntu/Downloads/test_card/card_24.onnx",
help='onnx_model_path')
parser.add_argument('--device', default='cuda:0', help='Device used for inference')
parser.add_argument('--output', default=r'ptsxj731533730.jpg', help='Output image')
parser.add_argument('--onnxoutput', default=r'onnxsxj731533730.jpg', help='Output image')
parser.add_argument('--score-thr', type=float, default=0.3, help='bbox score threshold')
args = parser.parse_args()
# build the model from a config file and a checkpoint file
model = init_detector(args.config, args.checkpoint, device=args.device)
# test a single image
result = inference_detector(model, args.img)
print("result=", result)
# show the results
model.show_result(
args.img, result, score_thr=args.score_thr, out_file=args.output)
torch2onnx(args, model)
# D:\Python39\Lib\site-packages\mmcv\ops
if __name__ == '__main__':
main()
原图
pt图
onnx图
c++ 新训练的模型和之前的模型的输出名,一一对应就行,数据可以不用比对
百度云中的模型
ubuntu@ubuntu:~/Downloads/test_card$ python3 -m onnxsim card_24.onnx card_24_sim.onnx
Your model contains "Tile" ops or/and "ConstantOfShape" ops. Folding these ops
can make the simplified model much larger. If it is not expected, please specify
"--no-large-tensor" (which will lose some optimization chances)
Simplifying...
Finish! Here is the difference:
┏━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┓
┃ ┃ Original Model ┃ Simplified Model ┃
┡━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━┩
│ Add │ 55 │ 43 │
│ ArgMax │ 5 │ 5 │
│ Cast │ 28 │ 0 │
│ Clip │ 10 │ 10 │
│ Concat │ 62 │ 5 │
│ Constant │ 344 │ 0 │
│ ConstantOfShape │ 29 │ 0 │
│ Conv │ 167 │ 161 │
│ Div │ 15 │ 0 │
│ Equal │ 10 │ 0 │
│ Exp │ 10 │ 10 │
│ Expand │ 50 │ 5 │
│ Gather │ 71 │ 35 │
│ GatherElements │ 10 │ 10 │
│ If │ 5 │ 0 │
│ MaxPool │ 1 │ 1 │
│ Mul │ 34 │ 25 │
│ Range │ 4 │ 0 │
│ ReduceMax │ 5 │ 5 │
│ Relu │ 129 │ 129 │
│ Reshape │ 32 │ 15 │
│ Resize │ 2 │ 2 │
│ Shape │ 79 │ 0 │
│ Slice │ 47 │ 25 │
│ Squeeze │ 5 │ 10 │
│ Sub │ 5 │ 0 │
│ Tile │ 20 │ 0 │
│ Transpose │ 10 │ 10 │
│ Unsqueeze │ 125 │ 50 │
│ Where │ 5 │ 0 │
│ Model Size │ 160.1MiB │ 166.5MiB │
└─────────────────┴────────────────┴──────────────────┘
ubuntu@ubuntu:~/MNN/build$ ./MNNConvert -f ONNX --modelFile /home/ubuntu/Downloads/test_card/card_24_sim.onnx --MNNModel /home/ubuntu/Downloads/test_card/card_24_sim.mnn --bizCode MNN
Start to Convert Other Model Format To MNN Model...
[09:50:51] /home/ubuntu/MNN/tools/converter/source/onnx/onnxConverter.cpp:40: ONNX Model ir version: 6
Start to Optimize the MNN Net...
inputTensors : [ input, ]
outputTensors: [ 1351, 1524, 1697, 1870, 2043, 2095, 2096, 2113, 2114, 2131, 2132, 2149, 2150, 2167, 2168, ]
Converted Success!
测试代码main.cpp
#include <iostream>
#include <ostream>
#include <random>
#include <vector>
#include <opencv2/opencv.hpp>
#include<MNN/Interpreter.hpp>
#include<MNN/ImageProcess.hpp>
#include "polyiou.h"
#define IMAGE_TARGET 1024
struct Ploy {
float p1_0;
float p1_1;
float p2_0;
float p2_1;
float p3_0;
float p3_1;
float p4_0;
float p4_1;
Ploy() : p1_0(0), p1_1(0), p2_0(0), p2_1(0), p3_0(0), p3_1(0), p4_0(0), p4_1(0) {}
Ploy(float p1_0, float p1_1, float p2_0, float p2_1, float p3_0, float p3_1, float p4_0, float p4_1) : p1_0(p1_0),
p1_1(p1_1),
p2_0(p2_0),
p2_1(p2_1),
p3_0(p3_0),
p3_1(p3_1),
p4_0(p4_0),
p4_1(p4_1) {}
};
struct BBox {
int idx;
float conf;
Ploy ploy;
BBox() : idx(0), conf(0), ploy(0, 0, 0, 0, 0, 0, 0, 0) {}
BBox(int idx, float conf, Ploy ploy) : idx(idx), conf(conf), ploy(ploy) {}
};
double mysoftmax(double num) {
return exp(num);
}
double mysigmoid(double num) {
return 1 / (1 + exp(-num));
}
template<typename T>
void softmax(const typename ::std::vector<T> &v, typename ::std::vector<T> &s) {
double sum = 0.0;
transform(v.begin(), v.end(), s.begin(), mysoftmax);
sum = accumulate(s.begin(), s.end(), sum);
for (size_t i = 0; i < s.size(); ++i)
s.at(i) /= sum;
}
template<typename T>
void sigmoid(const typename ::std::vector<T> &v, typename ::std::vector<T> &s) {
transform(v.begin(), v.end(), s.begin(), mysigmoid);
}
void cls_score_softmax(std::vector<float> &vec_cls_scores, std::vector<float> &item_cls_scores) {
item_cls_scores = vec_cls_scores;
softmax(vec_cls_scores, item_cls_scores);
}
void cls_score_sigmoid(std::vector<float> &vec_cls_scores, std::vector<float> &item_cls_scores) {
item_cls_scores = vec_cls_scores;
sigmoid(vec_cls_scores, item_cls_scores);
}
void dim_permute(std::vector<float> vec_cls_scores, std::vector<float> &item_cls_score, int w_h_dim) {
for (int i = 0; i < w_h_dim; i++) {
for (int j = i; j < vec_cls_scores.size(); j += w_h_dim) {
item_cls_score.emplace_back(vec_cls_scores[j]);
}
}
}
void process_top_k(std::vector<float> scores, int top_K, std::vector<float> &scores_K, std::vector<int> &index_K) {
std::vector<int> idx(scores.size());
std::iota(idx.begin(), idx.end(), 0);
std::sort(idx.begin(), idx.end(),
[&scores](int index_1, int index_2) { return scores[index_1] > scores[index_2]; });
// 获取K值
int k_num = std::min<int>(scores.size(), top_K);
int idx_j = 0;
for (int j = 0; j < k_num; ++j) {
idx_j = idx[j];
index_K.emplace_back(idx_j);
scores_K.emplace_back(scores[idx_j]);
}
}
float norm_angle(float angle, std::string angle_range) {
if (angle_range == "oc") {
return angle;
} else if (angle_range == "le135") {
return fmod((angle + M_PI / 4), M_PI) - M_PI / 4;
} else if (angle_range == "le90") {
return fmod((angle + (M_PI) / 2), M_PI) - M_PI / 2;
}
std::cout << "Not yet implemented." << std::endl;
return 0;
}
void bbox_coder_decode(std::vector<float> top_k_anchors,
std::vector<float> top_k_bbox_pred,
std::vector<float> &bbox_coder,
int bbox_preds_channels,
int img_width,
int img_height,
float wh_ratio_clip = 16.0f / 1000.0f,
bool add_ctr_clamp = false,
int ctr_clamp = 32,
bool proj_xy = false,
std::string angle_range = "oc",
bool edge_swap = false) {
// G:\mmrotate\mmrotate\core\bbox\coder\delta_xywh_rbbox_coder.py
float dx_width;
float dy_height;
float dw;
float dh;
float gx;
float gy;
float ga;
for (int i = 0; i < top_k_bbox_pred.size(); i += bbox_preds_channels) {
float dx = top_k_bbox_pred[i];
float dy = top_k_bbox_pred[i + 1];
float dw = top_k_bbox_pred[i + 2];
float dh = top_k_bbox_pred[i + 3];
float da = top_k_bbox_pred[i + 4];
float px = top_k_anchors[i];
float py = top_k_anchors[i + 1];
float pw = top_k_anchors[i + 2];
float ph = top_k_anchors[i + 3];
float pa = top_k_anchors[i + 4];
float dx_width = pw * dx;
float dy_height = ph * dy;
float max_ratio = abs(log(wh_ratio_clip));
if (add_ctr_clamp) {
dx_width = (dx_width >= -ctr_clamp) ? dx_width : -ctr_clamp;
dx_width = (dx_width <= ctr_clamp) ? dx_width : ctr_clamp;
dy_height = (dy_height >= -ctr_clamp) ? dy_height : -ctr_clamp;
dy_height = (dy_height <= ctr_clamp) ? dy_height : ctr_clamp;
dw = (dw <= max_ratio) ? dw : max_ratio;
dh = (dh <= max_ratio) ? dh : max_ratio;
} else {
dw = (dw <= max_ratio) ? dw : max_ratio;
dw = (dw >= -max_ratio) ? dw : -max_ratio;
dh = (dh <= max_ratio) ? dh : max_ratio;
dh = (dh >= -max_ratio) ? dh : -max_ratio;
}
float gw = pw * exp(dw);
float gh = ph * exp(dh);
if (proj_xy) {
gx = dx * pw * cos(pa) - dy * ph * sin(pa) + px;
gy = dx * pw * sin(pa) + dy * ph * cos(pa) + py;
} else {
gx = px + dx_width;
gy = py + dy_height;
ga = norm_angle(pa + da, angle_range);
}
// if max_shape is not None:
{
gx = (gx >= 0) ? gx : 0;
gx = (gx <= img_width - 1) ? gx : img_width - 1;
gy = (gy >= 0) ? gy : 0;
gy = (gy <= img_height - 1) ? gy : img_height - 1;
}
if (edge_swap) {
float w_regular = gw > gh ? gw : gh;
float h_regular = gw > gh ? gh : gw;
float theta_regular = gw > gh ? ga : ga + M_PI / 2;
theta_regular = norm_angle(theta_regular, angle_range);
bbox_coder.emplace_back(gx);
bbox_coder.emplace_back(gy);
bbox_coder.emplace_back(gw);
bbox_coder.emplace_back(gh);
bbox_coder.emplace_back(ga);
} else {
bbox_coder.emplace_back(gx);
bbox_coder.emplace_back(gy);
bbox_coder.emplace_back(gw);
bbox_coder.emplace_back(gh);
bbox_coder.emplace_back(ga);
}
}
}
// 进行iou计算
float iou(Ploy &r1, Ploy &r2) {
std::vector<double> p;
p.emplace_back(r1.p1_0);
p.emplace_back(r1.p1_1);
p.emplace_back(r1.p2_0);
p.emplace_back(r1.p2_1);
p.emplace_back(r1.p3_0);
p.emplace_back(r1.p3_1);
p.emplace_back(r1.p4_0);
p.emplace_back(r1.p4_1);
std::vector<double> q;
q.emplace_back(r2.p1_0);
q.emplace_back(r2.p1_1);
q.emplace_back(r2.p2_0);
q.emplace_back(r2.p2_1);
q.emplace_back(r2.p3_0);
q.emplace_back(r2.p3_1);
q.emplace_back(r2.p4_0);
q.emplace_back(r2.p4_1);
double iou = iou_poly(p, q);
p.clear();
std::vector<double>().swap(p);
q.clear();
std::vector<double>().swap(q);
return iou;
}
// 进行nms计算
void single_class_non_max_suppression(std::vector<Ploy> ploys, std::vector<float> confs, std::vector<Ploy> &ans,
std::vector<int> &keep_idx, float conf_thresh, float iou_thresh) {
if (ploys.size() == 0) {
return;
}
std::vector<BBox> bboxes;
BBox bbox;
for (int i = 0; i < (int) ploys.size(); ++i) {
bboxes.emplace_back(BBox(i, confs[i], ploys[i]));
}
// 对bbox的conf进行降序排序
sort(bboxes.begin(), bboxes.end(), [&](const BBox &a, const BBox &b) {
return a.conf > b.conf;
});
while (!bboxes.empty()) {
bbox = bboxes[0];
if (bbox.conf < conf_thresh) {
break;
}
keep_idx.emplace_back(bbox.idx);
bboxes.erase(bboxes.begin());
// 让conf最高的bbox与其他剩余的bbox进行iou计算
int size = bboxes.size();
for (int i = 0; i < size; ++i) {
float iou_ans = iou(bbox.ploy, bboxes[i].ploy);
if (iou_ans > iou_thresh) {
bboxes.erase(bboxes.begin() + i);
size = bboxes.size();
i = i - 1;
}
}
}
for (const int number : keep_idx) {
ans.emplace_back(ploys[number]);
}
}
void convet_point(std::vector<float> mutil_point,
float &p1_0,
float &p1_1,
float &p2_0,
float &p2_1,
float &p3_0,
float &p3_1,
float &p4_0,
float &p4_1
) {
float xc = mutil_point[0];
float yc = mutil_point[1];
float w = mutil_point[2];
float h = mutil_point[3];
float ag = mutil_point[4];
float wx = w / 2 * cos(ag);
float wy = w / 2 * sin(ag);
float hx = -h / 2 * sin(ag);
float hy = h / 2 * cos(ag);
p1_0 = xc - wx - hx;
p1_1 = yc - wy - hy;
p2_0 = xc + wx - hx;
p2_1 = yc + wy - hy;
p3_0 = xc + wx + hx;
p3_1 = yc + wy + hy;
p4_0 = xc - wx + hx;
p4_1 = yc - wy + hy;
}
void ext_module_nms_rotated(std::vector<std::vector<float>> dim_mlvl_bbox,
std::vector<float> dim_mlvl_score,
std::vector<int> order_K,
std::vector<int> &keep_idx,
float nms_iou_thr,
bool multi_label = false) {
// nms.py
std::cout << dim_mlvl_bbox.size() << " " << " " << dim_mlvl_score.size() << std::endl;
std::vector<Ploy> pts0_item;
std::vector<Ploy> ans;
for (int i = 0; i < dim_mlvl_bbox.size(); i++) {
float p1_0 = 0, p1_1 = 0, p2_0 = 0, p2_1 = 0, p3_0 = 0, p3_1 = 0, p4_0 = 0, p4_1 = 0;
convet_point(dim_mlvl_bbox[i], p1_0, p1_1, p2_0, p2_1, p3_0, p3_1, p4_0, p4_1);
pts0_item.emplace_back(Ploy(p1_0, p1_1, p2_0, p2_1, p3_0, p3_1, p4_0, p4_1));
}
single_class_non_max_suppression(pts0_item, dim_mlvl_score, ans, keep_idx, 0.3, nms_iou_thr);
pts0_item.clear();
std::vector<Ploy>().swap(pts0_item);
ans.clear();
std::vector<Ploy>().swap(ans);
}
void nms_rotated(std::vector<std::vector<float>> dim_mlvl_bbox,
std::vector<float> dim_mlvl_score,
std::vector<int> &keep_inds,
float nms_iou_thr,
bool clockwise = true) {
if (dim_mlvl_bbox[0].size() == 0) {
return;
}
std::vector<int> order_K;
std::vector<float> scores_K;
process_top_k(dim_mlvl_score, dim_mlvl_score.size(), scores_K, order_K);
ext_module_nms_rotated(dim_mlvl_bbox, dim_mlvl_score, order_K, keep_inds, nms_iou_thr);
}
void multiclass_nms_rotated(std::vector<std::vector<float>> multi_bbox,
std::vector<std::vector<float>> mlvl_score,
std::vector<int> mlvl_data_shape,
std::vector<std::vector<float>> &keep_box,
std::vector<float> &keep_score,
std::vector<int> &keep_label,
float score_thr = 0.05,
float nms_iou_thr = 0.1,
int max_num = 2000,
bool score_factors = false,
bool return_inds = false) {
std::vector<std::vector<float>> dim_mlvl_bbox;
std::vector<float> temp_dim_mlvl_bbox;
std::vector<std::vector<float>> dets_;
std::vector<float> dim_mlvl_score;
std::vector<int> dim_mlvl_label;
std::vector<int> dim_mlvl_inds;
float max_coordinate = -1;
int num_classes = mlvl_score[0].size() - 1;
if (multi_bbox[0].size() > 5) { ;
} else { ;
}
for (int i = 0; i < mlvl_score.size(); i++) {
int length = mlvl_score[i].size() - 1;
for (int j = 0; j < length; j++) {
if (mlvl_score[i][j] > score_thr) {
dim_mlvl_score.emplace_back(mlvl_score[i][j]);
dim_mlvl_inds.emplace_back(i * length + j);
dim_mlvl_label.emplace_back(j);
auto item = multi_bbox[(i * length + j) / num_classes];
auto maxPosition = max_element(item.begin(), item.end());
max_coordinate = std::max(max_coordinate, item[maxPosition - item.begin()]);
dim_mlvl_bbox.emplace_back(item);
}
}
}
if (dim_mlvl_bbox.size() == 0) {
for (int i = 0; i < dim_mlvl_bbox.size(); i++) {
for (int j = 0; j < dim_mlvl_bbox[i].size(); j++) {
temp_dim_mlvl_bbox.emplace_back(dim_mlvl_bbox[i][j]);
}
temp_dim_mlvl_bbox.emplace_back(dim_mlvl_score[i]);
dets_.emplace_back(temp_dim_mlvl_bbox);
temp_dim_mlvl_bbox.clear();
std::vector<float>().swap(temp_dim_mlvl_bbox);
}
if (return_inds) {
return; //dets, labels, inds
} else {
return;//dets, labels, inds
}
}
std::vector<int> keep;
nms_rotated(dim_mlvl_bbox, dim_mlvl_score, keep, nms_iou_thr);
std::cout << "kip_dim= " << keep.size() << std::endl;
if (max_num > 0) {
if (keep.size() > max_num) {
keep.resize(max_num);
}
}
for (int i = 0; i < keep.size(); i++) {
keep_box.emplace_back(dim_mlvl_bbox[keep[i]]);
keep_score.emplace_back(dim_mlvl_score[keep[i]]);
keep_label.emplace_back(dim_mlvl_label[keep[i]]);
}
std::cout << keep_box.size() << " " << keep_score.size() << " " << keep_label.size() << std::endl;
dim_mlvl_bbox.clear();
std::vector<std::vector<float>>().swap(dim_mlvl_bbox);
temp_dim_mlvl_bbox.clear();
std::vector<float>().swap(temp_dim_mlvl_bbox);
dets_.clear();
std::vector<std::vector<float>>().swap(dets_);
dim_mlvl_score.clear();
std::vector<float>().swap(dim_mlvl_score);
dim_mlvl_label.clear();
std::vector<int>().swap(dim_mlvl_label);
dim_mlvl_inds.clear();
std::vector<int>().swap(dim_mlvl_inds);
}
void get_bboxes_single(
std::vector<std::vector<float>> vec_cls_scores,
std::vector<std::vector<float>> vec_bbox_preds,
std::vector<std::vector<float>> vec_rois,
std::vector<int> scores_shape_0,
std::vector<std::vector<float>> &keep_box,
std::vector<float> &keep_score,
std::vector<int> &keep_label,
int img_width,
int img_height,
int nms_pre,
int cls_out_channels,
int bbox_preds_channels,
int rois_channels,
bool rescale,
bool with_nms,
bool use_sigmoid_cls,
float scale_factor[],
float score_thr,
float iou_thr,
int max_pre_img) {
std::vector<std::vector<float>> mlvl_bboxes;
std::vector<std::vector<float>> mlvl_scores;
std::vector<float> item_cls_score;
std::vector<float> item_bbox_pred;
std::vector<float> item_s_cls_score;
std::vector<int> topk_inds;
std::vector<float> scores_K;
std::vector<float> max_scores;
std::vector<float> top_k_anchors;
std::vector<float> top_k_bbox_pred;
std::vector<float> top_k_scores;
std::vector<float> bbox_coder;
std::vector<std::vector<float>> mlvl_bbox;
std::vector<std::vector<float>> mlvl_score;
std::vector<int> mlvl_data_shape;
std::vector<float> item_temp;
for (int i = 0; i < vec_cls_scores.size(); i++) {
dim_permute(vec_cls_scores[i], item_cls_score, vec_cls_scores[i].size() / cls_out_channels); //1,2,0
dim_permute(vec_bbox_preds[i], item_bbox_pred, vec_bbox_preds[i].size() / bbox_preds_channels); //1,2,0
//item_cls_score 16384 15 仍然拉伸成1维数据
// item_bbox_pred 5 仍然拉伸成1维数据
if (use_sigmoid_cls) {
cls_score_sigmoid(item_cls_score, item_s_cls_score);
} else {
cls_score_softmax(item_cls_score, item_s_cls_score);
}
if (nms_pre > 0 && scores_shape_0[i] > nms_pre) {
if (use_sigmoid_cls) {
for (int j = 0; j < item_s_cls_score.size() / cls_out_channels; j++) {
auto maxPosition = max_element(item_s_cls_score.begin() + j * cls_out_channels,
item_s_cls_score.begin() + (j + 1) * cls_out_channels);
max_scores.emplace_back(item_s_cls_score[maxPosition - item_s_cls_score.begin()]);
}
process_top_k(max_scores, nms_pre, scores_K, topk_inds);
for (int m = 0; m < topk_inds.size(); m++) {
int index = topk_inds[m];
for (int n = 0; n < rois_channels; n++) {
top_k_anchors.emplace_back(vec_rois[i][index * rois_channels + n]);
}
for (int n = 0; n < bbox_preds_channels; n++) {
top_k_bbox_pred.emplace_back(item_bbox_pred[index * bbox_preds_channels + n]);
}
for (int n = 0; n < cls_out_channels; n++) {
top_k_scores.emplace_back(item_s_cls_score[index * cls_out_channels + n]);
}
}
topk_inds.clear();
std::vector<int>().swap(topk_inds);
scores_K.clear();
std::vector<float>().swap(scores_K);
max_scores.clear();
std::vector<float>().swap(max_scores);
}
mlvl_data_shape.emplace_back(nms_pre);
} else {
top_k_anchors = vec_rois[i];
top_k_bbox_pred = item_bbox_pred;
top_k_scores = item_s_cls_score;
mlvl_data_shape.emplace_back(scores_shape_0[i]);
}
bbox_coder_decode(top_k_anchors, top_k_bbox_pred, bbox_coder, bbox_preds_channels, img_width, img_height);
mlvl_bbox.emplace_back(bbox_coder);
mlvl_score.emplace_back(top_k_scores);
top_k_anchors.clear();
std::vector<float>().swap(top_k_anchors);
bbox_coder.clear();
std::vector<float>().swap(bbox_coder);
top_k_scores.clear();
std::vector<float>().swap(top_k_scores);
top_k_bbox_pred.clear();
std::vector<float>().swap(top_k_bbox_pred);
item_cls_score.clear();
std::vector<float>().swap(item_cls_score);
item_bbox_pred.clear();
std::vector<float>().swap(item_bbox_pred);
item_s_cls_score.clear();
std::vector<float>().swap(item_s_cls_score);
}
mlvl_bboxes = mlvl_bbox;
mlvl_scores = mlvl_score;
if (rescale) {
mlvl_bboxes.clear();
std::vector<std::vector<float>>().swap(mlvl_bboxes);
// angle should not be rescaled
for (int i = 0; i < mlvl_bbox.size(); i++) {
for (int j = 0; j < mlvl_bbox[i].size(); j += bbox_preds_channels) {
for (int k = 0; k < bbox_preds_channels - 1; k++) {
item_temp.emplace_back(mlvl_bbox[i][j + k] / scale_factor[k]);
}
item_temp.emplace_back(mlvl_bbox[i][j + bbox_preds_channels - 1]);
}
mlvl_bboxes.emplace_back(item_temp);
item_temp.clear();
std::vector<float>().swap(item_temp);
}
}
if (use_sigmoid_cls) {
mlvl_scores.clear();
std::vector<std::vector<float>>().swap(mlvl_scores);
for (int i = 0; i < mlvl_score.size(); i++) {
for (int j = 0; j < mlvl_score[i].size(); j += cls_out_channels) {
for (int k = 0; k < cls_out_channels; k++) {
item_temp.emplace_back(mlvl_score[i][j + k]);
};
item_temp.emplace_back(0);
}
mlvl_scores.emplace_back(item_temp);
item_temp.clear();
std::vector<float>().swap(item_temp);
}
cls_out_channels = cls_out_channels + 1;
}
mlvl_bbox.clear();
std::vector<std::vector<float>>().swap(mlvl_bbox);
//cat data
for (int i = 0; i < mlvl_bboxes.size(); i++) {
for (int j = 0; j < mlvl_bboxes[i].size(); j += bbox_preds_channels) {
for (int k = 0; k < bbox_preds_channels; k++) {
item_temp.emplace_back(mlvl_bboxes[i][j + k]);
}
mlvl_bbox.emplace_back(item_temp);
item_temp.clear();
std::vector<float>().swap(item_temp);
}
}
mlvl_score.clear();
std::vector<std::vector<float>>().swap(mlvl_score);
for (int i = 0; i < mlvl_scores.size(); i++) {
for (int j = 0; j < mlvl_scores[i].size(); j += cls_out_channels) { // 扩展了0维空间
for (int k = 0; k < cls_out_channels; k++) {
item_temp.emplace_back(mlvl_scores[i][j + k]);
}
mlvl_score.emplace_back(item_temp);
item_temp.clear();
std::vector<float>().swap(item_temp);
}
}
if (with_nms) {
multiclass_nms_rotated(mlvl_bbox,
mlvl_score,
mlvl_data_shape,
keep_box,
keep_score,
keep_label,
score_thr,
iou_thr,
max_pre_img);
} else {
// 引用已经回传数据
}
item_cls_score.clear(); //有点习惯了 释放,其实局部变量没有必要
std::vector<float>().swap(item_cls_score);
item_bbox_pred.clear();
std::vector<float>().swap(item_bbox_pred);
item_s_cls_score.clear();
std::vector<float>().swap(item_s_cls_score);
topk_inds.clear();
std::vector<int>().swap(topk_inds);
scores_K.clear();
std::vector<float>().swap(scores_K);
max_scores.clear();
std::vector<float>().swap(max_scores);
top_k_anchors.clear();
std::vector<float>().swap(top_k_anchors);
top_k_bbox_pred.clear();
std::vector<float>().swap(top_k_bbox_pred);
top_k_scores.clear();
std::vector<float>().swap(top_k_scores);
bbox_coder.clear();
std::vector<float>().swap(bbox_coder);
mlvl_bbox.clear();
std::vector<std::vector<float>>().swap(mlvl_bbox);
mlvl_score.clear();
std::vector<std::vector<float>>().swap(mlvl_score);
mlvl_data_shape.clear();
std::vector<int>().swap(mlvl_data_shape);
mlvl_bboxes.clear();
std::vector<std::vector<float>>().swap(mlvl_bboxes);
mlvl_scores.clear();
std::vector<std::vector<float>>().swap(mlvl_scores);
}
int main(int argc, char **argv) {
cv::Mat img = cv::imread("/home/ubuntu/CLionProjects/card_detect/IMG20220913091114.jpg");
const char *classes[] = {"card"};
int new_h=1024.0;
int new_w=1024.0;
int img_width = img.cols;
int img_height = img.rows;
float img_mmcv_scale_factor = std::max(new_w*1.0f, new_h*1.0f) / std::max(img_height*1.0f, img_width*1.0f);
new_h=img_mmcv_scale_factor*img_height;
new_w=img_mmcv_scale_factor*img_width;
float h_scale = new_h / (img_height*1.0f);
float w_scale = new_w / (img_width*1.0f);
float scale_factor[] = {w_scale, h_scale, w_scale, h_scale};
cv::Mat img_resized;
cv::resize(img, img_resized, cv::Size(new_w, new_h));
auto net = std::shared_ptr<MNN::Interpreter>(MNN::Interpreter::createFromFile("../model/card_24_sim.mnn"));
MNN::ScheduleConfig netConfig;
netConfig.type = MNN_FORWARD_CPU;
netConfig.numThread = 4;
auto session = net->createSession(netConfig);
auto input = net->getSessionInput(session, nullptr);
const float mean_vals[3] = {123.675f , 116.28f, 103.53f};
const float norm_255[3] = {1.0f / 58.395, 1.0f / 57.12, 1.0f / 57.375};
std::shared_ptr<MNN::CV::ImageProcess> pretreat(
MNN::CV::ImageProcess::create(MNN::CV::BGR, MNN::CV::RGB, mean_vals, 3,
norm_255, 3));
pretreat->convert(img_resized.data, (int) new_h, (int) new_w, img_resized.step[0], input);
net->runSession(session);
char* cls_id0="2095";
char* cls_id1="2113";
char* cls_id2="2131";
char* cls_id3="2149";
char* cls_id4="2167";
char* bbox_id0="2096";
char* bbox_id1="2114";
char *bbox_id2="2132";
char *bbox_id3="2150";
char *bbox_id4="2168";
char* rois_id0="1351";
char* rois_id1="1524";
char *rois_id2="1697";
char *rois_id3="1870";
char *rois_id4="2043";
/*
char* cls_id0="1967";//"1962";
char* cls_id1="1985";//"1980";
char* cls_id2="2003";//"1998";
char* cls_id3="2021";//"2016";
char* cls_id4="2039";//"2034";
char* bbox_id0="1968";//"1963";
char* bbox_id1="1986";//"1981";
char *bbox_id2="2004";//"1999";
char *bbox_id3="2022";//"2017";
char *bbox_id4="2040";//"2035";
char* rois_id0="1238";//"1233";
char* rois_id1="1411";//"1406";
char *rois_id2="1584";//"1579";
char *rois_id3="1757";//"1752";
char *rois_id4="1930";//"1925";
*/
std::vector<std::vector<float>> vec_cls_scores;
std::vector<int> scores_shape_0;
std::vector<float> vec_temp;
int cls_out_channels = 0;
std::cout << std::endl;
auto cls_scores_a0 = net->getSessionOutput(session, cls_id0);
MNN::Tensor cls_scores_tensor_a0(cls_scores_a0, cls_scores_a0->getDimensionType());
cls_scores_a0->copyToHostTensor(&cls_scores_tensor_a0);
auto cls_scores_ptr_a0 = cls_scores_tensor_a0.host<float>();
std::cout << std::string(cls_id0) << cls_scores_tensor_a0.height() << " " << cls_scores_tensor_a0.width() << " "
<< cls_scores_tensor_a0.channel() << " " << cls_scores_tensor_a0.elementSize() << std::endl;
cls_out_channels = cls_scores_tensor_a0.channel();
for (int i = 0; i < cls_scores_tensor_a0.elementSize(); i++) {
vec_temp.emplace_back(cls_scores_ptr_a0[i]);
}
scores_shape_0.emplace_back(cls_scores_tensor_a0.height() * cls_scores_tensor_a0.width());
vec_cls_scores.emplace_back(vec_temp);
vec_temp.clear();
std::vector<float>().swap(vec_temp);
std::cout << std::endl;
auto cls_scores_a1 = net->getSessionOutput(session, cls_id1);
MNN::Tensor cls_scores_tensor_a1(cls_scores_a1, cls_scores_a1->getDimensionType());
cls_scores_a1->copyToHostTensor(&cls_scores_tensor_a1);
auto cls_scores_ptr_a1 = cls_scores_tensor_a1.host<float>();
std::cout << std::string(cls_id1) << cls_scores_tensor_a1.height() << " " << cls_scores_tensor_a1.width() << " "
<< cls_scores_tensor_a1.channel() << " " << cls_scores_tensor_a1.elementSize() << std::endl;
for (int i = 0; i < cls_scores_tensor_a1.elementSize(); i++) {
vec_temp.emplace_back(cls_scores_ptr_a1[i]);
}
scores_shape_0.emplace_back(cls_scores_tensor_a1.height() * cls_scores_tensor_a1.width());
vec_cls_scores.emplace_back(vec_temp);
vec_temp.clear();
std::vector<float>().swap(vec_temp);
std::cout << std::endl;
auto cls_scores_net_a2 = net->getSessionOutput(session, cls_id2);
MNN::Tensor cls_scores_tensor_a2(cls_scores_net_a2, cls_scores_net_a2->getDimensionType());
cls_scores_net_a2->copyToHostTensor(&cls_scores_tensor_a2);
auto cls_scores_ptr_a2 = cls_scores_tensor_a2.host<float>();
std::cout << std::string(cls_id2) << cls_scores_tensor_a2.height() << " " << cls_scores_tensor_a2.width() << " "
<< cls_scores_tensor_a2.channel() << " " << cls_scores_tensor_a2.elementSize() << std::endl;
for (int i = 0; i < cls_scores_tensor_a2.elementSize(); i++) {
vec_temp.emplace_back(cls_scores_ptr_a2[i]);
}
scores_shape_0.emplace_back(cls_scores_tensor_a2.height() * cls_scores_tensor_a2.width());
vec_cls_scores.emplace_back(vec_temp);
vec_temp.clear();
std::vector<float>().swap(vec_temp);
std::cout << std::endl;
auto cls_scores_net_a3 = net->getSessionOutput(session, cls_id3);
MNN::Tensor cls_scores_tensor_a3(cls_scores_net_a3, cls_scores_net_a3->getDimensionType());
cls_scores_net_a3->copyToHostTensor(&cls_scores_tensor_a3);
auto rois_ptr_a3 = cls_scores_tensor_a3.host<float>();
std::cout << std::string(cls_id3)<< cls_scores_tensor_a3.height() << " " << cls_scores_tensor_a3.width() << " "
<< cls_scores_tensor_a3.channel() << " " << cls_scores_tensor_a3.elementSize() << std::endl;
for (int i = 0; i < cls_scores_tensor_a3.elementSize(); i++) {
vec_temp.emplace_back(rois_ptr_a3[i]);
}
scores_shape_0.emplace_back(cls_scores_tensor_a3.height() * cls_scores_tensor_a3.width());
vec_cls_scores.emplace_back(vec_temp);
vec_temp.clear();
std::vector<float>().swap(vec_temp);
std::cout << std::endl;
auto cls_scores_net_a4 = net->getSessionOutput(session, cls_id4);
MNN::Tensor cls_scores_tensor_a4(cls_scores_net_a4, cls_scores_net_a4->getDimensionType());
cls_scores_net_a4->copyToHostTensor(&cls_scores_tensor_a4);
auto cls_scores_ptr_a4 = cls_scores_tensor_a4.host<float>();
std::cout << std::string(cls_id4) << cls_scores_tensor_a4.height() << " " << cls_scores_tensor_a4.width() << " "
<< cls_scores_tensor_a4.channel() << " " << cls_scores_tensor_a4.elementSize() << std::endl;
for (int i = 0; i < cls_scores_tensor_a4.elementSize(); i++) {
vec_temp.emplace_back(cls_scores_ptr_a4[i]);
}
scores_shape_0.emplace_back(cls_scores_tensor_a4.height() * cls_scores_tensor_a4.width());
vec_cls_scores.emplace_back(vec_temp);
vec_temp.clear();
std::vector<float>().swap(vec_temp);
std::vector<std::vector<float>> vec_bbox_preds;
int bbox_preds_channels = 0;
std::cout << std::endl;
auto bbox_preds_net_b0 = net->getSessionOutput(session, bbox_id0);
MNN::Tensor bbox_preds_tensor_b0(bbox_preds_net_b0, bbox_preds_net_b0->getDimensionType());
bbox_preds_net_b0->copyToHostTensor(&bbox_preds_tensor_b0);
auto rois_ptr_b0 = bbox_preds_tensor_b0.host<float>();
std::cout << std::string(bbox_id0) << bbox_preds_tensor_b0.height() << " " << bbox_preds_tensor_b0.width() << " "
<< bbox_preds_tensor_b0.channel() << " " << bbox_preds_tensor_b0.elementSize() << std::endl;
bbox_preds_channels = bbox_preds_tensor_b0.channel();
for (int i = 0; i < bbox_preds_tensor_b0.elementSize(); i++) {
vec_temp.emplace_back(rois_ptr_b0[i]);
}
vec_bbox_preds.emplace_back(vec_temp);
vec_temp.clear();
std::vector<float>().swap(vec_temp);
std::cout << std::endl;
auto vec_bbox_net_b1 = net->getSessionOutput(session, bbox_id1);
MNN::Tensor vec_bbox_tensor_b1(vec_bbox_net_b1, vec_bbox_net_b1->getDimensionType());
vec_bbox_net_b1->copyToHostTensor(&vec_bbox_tensor_b1);
auto vec_bbox_ptr_b1 = vec_bbox_tensor_b1.host<float>();
std::cout << std::string(bbox_id1) << vec_bbox_tensor_b1.height() << " " << vec_bbox_tensor_b1.width() << " "
<< vec_bbox_tensor_b1.channel() << " " << vec_bbox_tensor_b1.elementSize() << std::endl;
for (int i = 0; i < vec_bbox_tensor_b1.elementSize(); i++) {
vec_temp.emplace_back(vec_bbox_ptr_b1[i]);
}
vec_bbox_preds.emplace_back(vec_temp);
vec_temp.clear();
std::vector<float>().swap(vec_temp);
std::cout << std::endl;
auto vec_bbox_net_b2 = net->getSessionOutput(session, bbox_id2);
MNN::Tensor vec_bbox_tensor_b2(vec_bbox_net_b2, vec_bbox_net_b2->getDimensionType());
vec_bbox_net_b2->copyToHostTensor(&vec_bbox_tensor_b2);
auto rois_ptr_b2 = vec_bbox_tensor_b2.host<float>();
std::cout << std::string(bbox_id2) << vec_bbox_tensor_b2.height() << " " << vec_bbox_tensor_b2.width() << " "
<< vec_bbox_tensor_b2.channel() << " " << vec_bbox_tensor_b2.elementSize() << std::endl;
for (int i = 0; i < vec_bbox_tensor_b2.elementSize(); i++) {
vec_temp.emplace_back(rois_ptr_b2[i]);
}
vec_bbox_preds.emplace_back(vec_temp);
vec_temp.clear();
std::vector<float>().swap(vec_temp);
std::cout << std::endl;
auto bbox_preds_net_b3 = net->getSessionOutput(session, bbox_id3);
MNN::Tensor bbox_preds_tensor_b3(bbox_preds_net_b3, bbox_preds_net_b3->getDimensionType());
bbox_preds_net_b3->copyToHostTensor(&bbox_preds_tensor_b3);
auto bbox_preds_ptr_b3 = bbox_preds_tensor_b3.host<float>();
std::cout << std::string(bbox_id3) << bbox_preds_tensor_b3.height() << " " << bbox_preds_tensor_b3.width() << " "
<< bbox_preds_tensor_b3.channel() << " " << bbox_preds_tensor_b3.elementSize() << std::endl;
for (int i = 0; i < bbox_preds_tensor_b3.elementSize(); i++) {
vec_temp.emplace_back(bbox_preds_ptr_b3[i]);
}
vec_bbox_preds.emplace_back(vec_temp);
vec_temp.clear();
std::vector<float>().swap(vec_temp);
std::cout << std::endl;
auto bbox_preds_net_b4 = net->getSessionOutput(session, bbox_id4);
MNN::Tensor bbox_preds_tensor_b4(bbox_preds_net_b4, bbox_preds_net_b4->getDimensionType());
bbox_preds_net_b4->copyToHostTensor(&bbox_preds_tensor_b4);
auto bbox_preds_ptr_b4 = bbox_preds_tensor_b4.host<float>();
std::cout << std::string(bbox_id4) << bbox_preds_tensor_b4.height() << " " << bbox_preds_tensor_b4.width() << " "
<< bbox_preds_tensor_b4.channel() << " " << bbox_preds_tensor_b4.elementSize() << std::endl;
for (int i = 0; i < bbox_preds_tensor_b4.elementSize(); i++) {
vec_temp.emplace_back(bbox_preds_ptr_b4[i]);
}
vec_bbox_preds.emplace_back(vec_temp);
vec_temp.clear();
std::vector<float>().swap(vec_temp);
std::vector<std::vector<float>> vec_rois;
int rois_channels = 0;
std::cout << std::endl;
auto rois_net_c0 = net->getSessionOutput(session, rois_id0);
MNN::Tensor rois_tensor_c0(rois_net_c0, rois_net_c0->getDimensionType());
rois_net_c0->copyToHostTensor(&rois_tensor_c0);
auto rois_ptr_c0 = rois_tensor_c0.host<float>();
std::cout << std::string(rois_id0) << rois_tensor_c0.height() << " " << rois_tensor_c0.width() << " "
<< rois_tensor_c0.channel() << " " << rois_tensor_c0.elementSize() << std::endl;
rois_channels = rois_tensor_c0.channel();
for (int i = 0; i < rois_tensor_c0.elementSize(); i++) {
vec_temp.emplace_back(rois_ptr_c0[i]);
}
vec_rois.emplace_back(vec_temp);
vec_temp.clear();
std::vector<float>().swap(vec_temp);
std::cout << std::endl;
auto rois_net_c1 = net->getSessionOutput(session, rois_id1);
MNN::Tensor rois_tensor_c1(rois_net_c1, rois_net_c1->getDimensionType());
rois_net_c1->copyToHostTensor(&rois_tensor_c1);
auto rois_ptr_c1 = rois_tensor_c1.host<float>();
std::cout << std::string(rois_id1) << rois_tensor_c1.height() << " " << rois_tensor_c1.width() << " "
<< rois_tensor_c1.channel() << " " << rois_tensor_c1.elementSize() << std::endl;
for (int i = 0; i < rois_tensor_c1.elementSize(); i++) {
vec_temp.emplace_back(rois_ptr_c1[i]);
}
vec_rois.emplace_back(vec_temp);
vec_temp.clear();
std::vector<float>().swap(vec_temp);
std::cout << std::endl;
auto rois_net_c2 = net->getSessionOutput(session, rois_id2);
MNN::Tensor rois_tensor_c2(rois_net_c2, rois_net_c2->getDimensionType());
rois_net_c2->copyToHostTensor(&rois_tensor_c2);
auto rois_ptr_c2 = rois_tensor_c2.host<float>();
std::cout << std::string(rois_id2) << rois_tensor_c2.height() << " " << rois_tensor_c2.width() << " "
<< rois_tensor_c2.channel() << " " << rois_tensor_c2.elementSize() << std::endl;
for (int i = 0; i < rois_tensor_c2.elementSize(); i++) {
vec_temp.emplace_back(rois_ptr_c2[i]);
}
vec_rois.emplace_back(vec_temp);
vec_temp.clear();
std::vector<float>().swap(vec_temp);
std::cout << std::endl;
auto rois_net_c3 = net->getSessionOutput(session, rois_id3);
MNN::Tensor rois_tensor_c3(rois_net_c3, rois_net_c3->getDimensionType());
rois_net_c3->copyToHostTensor(&rois_tensor_c3);
auto rois_ptr_c3 = rois_tensor_c3.host<float>();
std::cout << std::string(rois_id3) << rois_tensor_c3.height() << " " << rois_tensor_c3.width() << " "
<< rois_tensor_c3.channel() << " " << rois_tensor_c3.elementSize() << std::endl;
for (int i = 0; i < rois_tensor_c3.elementSize(); i++) {
vec_temp.emplace_back(rois_ptr_c3[i]);
}
vec_rois.emplace_back(vec_temp);
vec_temp.clear();
std::vector<float>().swap(vec_temp);
std::cout << std::endl;
auto rois_net_c4 = net->getSessionOutput(session, rois_id4);
MNN::Tensor rois_tensor_c4(rois_net_c4, rois_net_c4->getDimensionType());
rois_net_c4->copyToHostTensor(&rois_tensor_c4);
auto rois_ptr_c4 = rois_tensor_c4.host<float>();
std::cout << std::string(rois_id4)<< rois_tensor_c4.height() << " " << rois_tensor_c4.width() << " "
<< rois_tensor_c4.channel() << " " << rois_tensor_c4.elementSize() << std::endl;
for (int i = 0; i < rois_tensor_c4.elementSize(); i++) {
vec_temp.emplace_back(rois_ptr_c4[i]);
}
vec_rois.emplace_back(vec_temp);
vec_temp.clear();
std::vector<float>().swap(vec_temp);
// 写的尽量不依赖MNN ,还要进行NCNN的转化
std::vector<int> keep;
std::vector<std::vector<float>> keep_box;
std::vector<float> keep_score;
std::vector<int> keep_label;
std::vector<Ploy> keep_box_dets;
int nms_pre = 2000;
int min_bbox_size = 0;
float score_thr = 0.05;
float iou_thr = 0.1;
int max_pre_img = 2000;
bool rescale = true;
bool with_nms = true;
bool use_sigmoid_cls = true;
get_bboxes_single(
vec_cls_scores,
vec_bbox_preds,
vec_rois,
scores_shape_0,
keep_box,
keep_score,
keep_label,
img_width,
img_height,
nms_pre,
cls_out_channels,
bbox_preds_channels,
rois_channels,
rescale,
with_nms,
use_sigmoid_cls,
scale_factor,
score_thr,
iou_thr,
max_pre_img);
float font_scale = 0.25;
cv::Scalar bbox_color = cv::Scalar(0, 0, 255);
cv::Scalar text_color = cv::Scalar(0, 255, 0);
std::vector<std::vector<cv::Point>> contours;
std::cout << keep_box.size() << std::endl;
for (int i = 0; i < keep_box.size(); i++) {
std::vector<cv::Point> contours_item;
float p1_0 = 0, p1_1 = 0, p2_0 = 0, p2_1 = 0, p3_0 = 0, p3_1 = 0, p4_0 = 0, p4_1 = 0, xc = 0, yc = 0;
convet_point(keep_box[i], p1_0, p1_1, p2_0, p2_1, p3_0, p3_1, p4_0, p4_1);
contours_item.emplace_back(cv::Point(p1_0, p1_1));
contours_item.emplace_back(cv::Point(p2_0, p2_1));
contours_item.emplace_back(cv::Point(p3_0, p3_1));
contours_item.emplace_back(cv::Point(p4_0, p4_1));
contours.emplace_back(contours_item);
xc = keep_box[i][0];
yc = keep_box[i][1];
cv::drawContours(img, contours, -1, bbox_color, 2);
char text[256];
sprintf(text, "%s %.2f%%", classes[keep_label[i]], keep_score[i]);
int baseLine = 0;
cv::Size label_size = cv::getTextSize(text, cv::FONT_HERSHEY_SIMPLEX, font_scale, 1, &baseLine);
int text_width = label_size.width;
int text_height = label_size.height;
cv::rectangle(img, cv::Point(int(xc), int(yc) - text_height - 2), cv::Point(int(xc) + text_width, int(yc) + 3),
cv::Scalar(0, 128, 0), -1);
cv::putText(img, text, cv::Point(int(xc), int(yc)),
cv::FONT_HERSHEY_SIMPLEX, font_scale, text_color);
contours.clear();
std::vector<std::vector<cv::Point>>().swap(contours);
}
cv::imshow("image", img);
cv::imwrite("image.jpg", img);
cv::waitKey(0);
return 0;
}
c++ 的测试结果
代码也放在云盘中linux+clion ,优化自己搞,商用版本不对外开放,留给神力社区赚赚赚
ncnn待补充