diff --git a/003ONNX转RKNN.py b/003ONNX转RKNN.py index 05c057f..249a894 100644 --- a/003ONNX转RKNN.py +++ b/003ONNX转RKNN.py @@ -16,7 +16,7 @@ rknn.config( ) # 加载 ONNX -ret = rknn.load_onnx(model="/home/admin-root/haotian/rk3588/pytorch模型转rknn/models/yolov8m.onnx") +ret = rknn.load_onnx(model="/home/admin-root/haotian/康达瑞贝斯机器狗/yolov8_20250820.onnx") assert ret == 0, "加载 ONNX 失败!" # 转换模型 @@ -27,12 +27,12 @@ ret = rknn.build( assert ret == 0, "转换 RKNN 失败!" # 导出 RKNN -ret = rknn.export_rknn("/home/admin-root/haotian/rk3588/pytorch模型转rknn/models/yolov8m.rknn") +ret = rknn.export_rknn("/home/admin-root/haotian/康达瑞贝斯机器狗/yolov8_20250820.rknn") assert ret == 0, "导出 RKNN 失败!" # Set inputs -img = cv2.imread('/home/admin-root/haotian/rk3588/pytorch模型转rknn/images/bus.jpg') +img = cv2.imread('/home/admin-root/haotian/康达瑞贝斯机器狗/YoloV8Obj/dataset_20250819/train/images/1e4c75b76e531606e2adc491a8f09ae8_frame_000000.jpg') img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) img.resize((3, 640, 640)) img = np.expand_dims(img, 0) diff --git a/009PaddleOCR_ONNX转rknn.py b/009PaddleOCR_ONNX转rknn.py index 7dd2fec..b25f87c 100644 --- a/009PaddleOCR_ONNX转rknn.py +++ b/009PaddleOCR_ONNX转rknn.py @@ -9,16 +9,16 @@ rknn = RKNN() # 配置参数(关键!) rknn.config( target_platform="rk3588", # 根据实际芯片型号修改 - # mean_values=[[123.675, 116.28, 103.53]], # 默认输入是255, 使用这些值归一化到0-1 - # std_values=[[58.395, 57.12, 57.375]], - mean_values=[[0, 0, 0]], # 默认输入是255, 使用这些值归一化到0-1 - std_values=[[255, 255, 255]], + mean_values=[[123.675, 116.28, 103.53]], # 文本检测模型, 默认输入是255, 使用这些值归一化到0-1 + std_values=[[58.395, 57.12, 57.375]], + # mean_values=[[127.5, 127.5, 127.5]], # 文本识别模型 + # std_values=[[127.5, 127.5, 127.5]], quant_img_RGB2BGR=True, - optimization_level=3, # 最高优化级别 + # optimization_level=3, # 最高优化级别 ) # 加载 ONNX, 只支持固定输入的onnx模型 -ret = rknn.load_onnx(model="/home/admin-root/haotian/康达瑞贝斯机器狗/rec_shape_20250815.onnx") +ret = rknn.load_onnx(model="/home/admin-root/haotian/康达瑞贝斯机器狗/det_shape_20250814.onnx") assert ret == 0, "加载 ONNX 失败!" # 转换模型 @@ -29,31 +29,31 @@ ret = rknn.build( assert ret == 0, "转换 RKNN 失败!" # 导出 RKNN -ret = rknn.export_rknn("/home/admin-root/haotian/康达瑞贝斯机器狗/rec_shape_20250815_0m.rknn") +ret = rknn.export_rknn("/home/admin-root/haotian/康达瑞贝斯机器狗/det_shape_20250814_0.rknn") assert ret == 0, "导出 RKNN 失败!" -# Set inputs -img = cv2.imread('/home/admin-root/haotian/rk3588/pytorch模型转rknn/images/bus.jpg') -img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) -# img.resize((3, 640, 640)) -img.resize((3, 48, 320)) -img = np.expand_dims(img, 0) +# # Set inputs +# img = cv2.imread('/home/admin-root/haotian/rk3588/pytorch模型转rknn/images/bus.jpg') +# img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) +# # img.resize((3, 640, 640)) +# img.resize((3, 48, 320)) +# img = np.expand_dims(img, 0) -# Init runtime environment -print('--> Init runtime environment') -ret = rknn.init_runtime() -if ret != 0: - print('Init runtime environment failed!') - exit(ret) -print('done') +# # Init runtime environment +# print('--> Init runtime environment') +# ret = rknn.init_runtime() +# if ret != 0: +# print('Init runtime environment failed!') +# exit(ret) +# print('done') -# Inference -print('--> Running model') -outputs = rknn.inference(inputs=[img], data_format=['nchw']) -np.save('./tflite_mobilenet_v1_0.npy', outputs[0]) -print(len(outputs)) -print('done') +# # Inference +# print('--> Running model') +# outputs = rknn.inference(inputs=[img], data_format=['nchw']) +# np.save('./tflite_mobilenet_v1_0.npy', outputs[0]) +# print(len(outputs)) +# print('done') rknn.release() diff --git a/013PaddleOCR_ONNX文本检测模型转rknn.py b/013PaddleOCR_ONNX文本检测模型转rknn.py new file mode 100644 index 0000000..6658455 --- /dev/null +++ b/013PaddleOCR_ONNX文本检测模型转rknn.py @@ -0,0 +1,38 @@ +from rknn.api import RKNN + +def convert_det_model(): + # 创建RKNN对象 + rknn = RKNN(verbose=True) + + # 配置模型 + print('--> Config model') + rknn.config(mean_values=[[123.675, 116.28, 103.53]], + std_values=[[58.395, 57.12, 57.375]], + quant_img_RGB2BGR=True, + target_platform='rk3588') # 根据您的芯片型号调整 + + # 加载ONNX模型 + print('--> Loading model') + ret = rknn.load_onnx(model='/home/admin-root/haotian/康达瑞贝斯机器狗/det_shape_20250814.onnx') + if ret != 0: + print('Load model failed!') + exit(ret) + + # 构建模型 + print('--> Building model') + ret = rknn.build(do_quantization=False + # , dataset='./det_dataset.txt' + ) + if ret != 0: + print('Build model failed!') + exit(ret) + + # 导出RKNN模型 + ret = rknn.export_rknn('./det_shape_bgr.rknn') + if ret != 0: + print('Export model failed!') + exit(ret) + + rknn.release() + +convert_det_model() \ No newline at end of file diff --git a/014PaddleOCR_ONNX文本识别模型转rknn.py b/014PaddleOCR_ONNX文本识别模型转rknn.py new file mode 100644 index 0000000..2e43282 --- /dev/null +++ b/014PaddleOCR_ONNX文本识别模型转rknn.py @@ -0,0 +1,34 @@ +from rknn.api import RKNN + + +def convert_rec_model(): + rknn = RKNN(verbose=True) + + print('--> Config model') + rknn.config(mean_values=[[127.5, 127.5, 127.5]], + std_values=[[127.5, 127.5, 127.5]], + quant_img_RGB2BGR=True, + target_platform='rk3588') + + print('--> Loading model') + ret = rknn.load_onnx(model='/home/admin-root/haotian/康达瑞贝斯机器狗/rec_shape_20250815.onnx') + if ret != 0: + print('Load model failed!') + exit(ret) + + print('--> Building model') + ret = rknn.build(do_quantization=False + # , dataset='./rec_dataset.txt' + ) + if ret != 0: + print('Build model failed!') + exit(ret) + + ret = rknn.export_rknn('./rec_model_bgr.rknn') + if ret != 0: + print('Export model failed!') + exit(ret) + + rknn.release() + +convert_rec_model() \ No newline at end of file diff --git a/015测试Yolov8_rknn.py b/015测试Yolov8_rknn.py new file mode 100644 index 0000000..d134ef5 --- /dev/null +++ b/015测试Yolov8_rknn.py @@ -0,0 +1,240 @@ +import cv2 +import numpy as np +from rknn.api import RKNN +import time + +class YOLOv8RKNN: + def __init__(self, model_path, input_size=(640, 640)): + self.model_path = model_path + self.input_size = input_size + self.rknn = RKNN() + + # 类别名称,根据你的2个类别修改 + self.class_names = ['class1', 'class2'] # 请替换为你实际的类别名称 + + # 初始化模型 + self.load_model() + + def load_model(self): + """加载RKNN模型""" + print("Loading RKNN model...") + ret = self.rknn.load_rknn(self.model_path) + if ret != 0: + print("Load RKNN model failed!") + return False + + # 初始化运行时环境(在RK3588设备上运行) + print("Init RKNN runtime...") + ret = self.rknn.init_runtime(target='rk3588', device_id=None, perf_debug=False, eval_mem=False) + if ret != 0: + print("Init RKNN runtime failed!") + return False + + print("RKNN model loaded successfully!") + return True + + def preprocess(self, image): + """图像预处理""" + # 获取原始图像尺寸 + self.orig_height, self.orig_width = image.shape[:2] + + # Resize到模型输入尺寸,保持宽高比 + scale = min(self.input_size[0]/self.orig_width, self.input_size[1]/self.orig_height) + new_width = int(self.orig_width * scale) + new_height = int(self.orig_height * scale) + + # 缩放图像 + resized = cv2.resize(image, (new_width, new_height)) + + # 创建输入图像(填充到目标尺寸) + input_image = np.full((self.input_size[1], self.input_size[0], 3), 114, dtype=np.uint8) + + # 计算填充位置(居中) + y_offset = (self.input_size[1] - new_height) // 2 + x_offset = (self.input_size[0] - new_width) // 2 + + # 将缩放后的图像放到中心位置 + input_image[y_offset:y_offset+new_height, x_offset:x_offset+new_width] = resized + + # 保存缩放参数用于后处理 + self.scale = scale + self.x_offset = x_offset + self.y_offset = y_offset + + return input_image + + def postprocess(self, outputs, conf_threshold=0.5, nms_threshold=0.4): + """后处理:解析YOLO输出并进行NMS""" + # YOLOv8输出格式: [batch, 84, 8400] (2个类别: 4+2+80=84,但实际只有6维) + # 对于2类别: [x, y, w, h, conf_class1, conf_class2] + predictions = outputs[0][0] # 移除batch维度 + + # 转置为 [8400, 6] 格式 + predictions = predictions.transpose() + + boxes = [] + scores = [] + class_ids = [] + + for detection in predictions: + # 提取坐标和类别置信度 + x, y, w, h = detection[:4] + class_confs = detection[4:6] # 2个类别的置信度 + + # 找到最大置信度的类别 + class_id = np.argmax(class_confs) + max_conf = class_confs[class_id] + + if max_conf >= conf_threshold: + # 转换坐标格式 (中心点 -> 左上角) + x1 = x - w/2 + y1 = y - h/2 + x2 = x + w/2 + y2 = y + h/2 + + # 将坐标映射回原图尺寸 + x1 = (x1 - self.x_offset) / self.scale + y1 = (y1 - self.y_offset) / self.scale + x2 = (x2 - self.x_offset) / self.scale + y2 = (y2 - self.y_offset) / self.scale + + # 限制在图像边界内 + x1 = max(0, min(x1, self.orig_width)) + y1 = max(0, min(y1, self.orig_height)) + x2 = max(0, min(x2, self.orig_width)) + y2 = max(0, min(y2, self.orig_height)) + + boxes.append([x1, y1, x2, y2]) + scores.append(max_conf) + class_ids.append(class_id) + + # 执行NMS + if len(boxes) > 0: + boxes = np.array(boxes) + scores = np.array(scores) + class_ids = np.array(class_ids) + + # OpenCV NMS + indices = cv2.dnn.NMSBoxes(boxes, scores, conf_threshold, nms_threshold) + + if len(indices) > 0: + indices = indices.flatten() + return boxes[indices], scores[indices], class_ids[indices] + + return np.array([]), np.array([]), np.array([]) + + def detect(self, image, conf_threshold=0.5, nms_threshold=0.4): + """执行检测""" + # 预处理 + input_image = self.preprocess(image) + + # 推理 + start_time = time.time() + outputs = self.rknn.inference(inputs=[input_image]) + inference_time = time.time() - start_time + + # 后处理 + boxes, scores, class_ids = self.postprocess(outputs, conf_threshold, nms_threshold) + + return boxes, scores, class_ids, inference_time + + def draw_detections(self, image, boxes, scores, class_ids): + """在图像上绘制检测结果""" + for i in range(len(boxes)): + x1, y1, x2, y2 = boxes[i].astype(int) + score = scores[i] + class_id = int(class_ids[i]) + + # 绘制边界框 + cv2.rectangle(image, (x1, y1), (x2, y2), (0, 255, 0), 2) + + # 绘制标签 + label = f"{self.class_names[class_id]}: {score:.2f}" + label_size = cv2.getTextSize(label, cv2.FONT_HERSHEY_SIMPLEX, 0.5, 2)[0] + cv2.rectangle(image, (x1, y1-label_size[1]-10), + (x1+label_size[0], y1), (0, 255, 0), -1) + cv2.putText(image, label, (x1, y1-5), + cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0), 2) + + return image + + def release(self): + """释放资源""" + if self.rknn: + self.rknn.release() + +def main(): + # 初始化检测器 + model_path = "/home/orangepi/Desktop/康达机器狗/model_rknn/yolov8_20250820.rknn" + detector = YOLOv8RKNN(model_path) + + # 测试单张图片 + def test_image(image_path): + image = cv2.imread(image_path) + if image is None: + print(f"Cannot load image: {image_path}") + return + + # 执行检测 + boxes, scores, class_ids, inference_time = detector.detect(image) + + print(f"Inference time: {inference_time*1000:.2f}ms") + print(f"Detected {len(boxes)} objects") + + # 绘制结果 + result_image = detector.draw_detections(image, boxes, scores, class_ids) + + # 显示结果 + # cv2.imshow("Detection Result", result_image) + # cv2.waitKey(0) + # cv2.destroyAllWindows() + + cv2.imwrite("xxxxxxx.jpg", result_image) + + # 测试摄像头实时检测 + def test_camera(): + cap = cv2.VideoCapture(0) # 使用默认摄像头 + if not cap.isOpened(): + print("Cannot open camera") + return + + while True: + ret, frame = cap.read() + if not ret: + break + + # 执行检测 + boxes, scores, class_ids, inference_time = detector.detect(frame) + + # 绘制结果 + result_frame = detector.draw_detections(frame, boxes, scores, class_ids) + + # 显示FPS + fps = 1.0 / inference_time if inference_time > 0 else 0 + cv2.putText(result_frame, f"FPS: {fps:.1f}", (10, 30), + cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) + + cv2.imshow("Real-time Detection", result_frame) + + if cv2.waitKey(1) & 0xFF == ord('q'): + break + + cap.release() + cv2.destroyAllWindows() + + # 选择测试模式 + mode = input("选择模式 (1: 图片检测, 2: 摄像头实时检测): ") + + if mode == "1": + image_path = input("输入图片路径: ") + test_image(image_path) + elif mode == "2": + test_camera() + else: + print("无效选择") + + # 释放资源 + detector.release() + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/tflite_mobilenet_v1_0.npy b/tflite_mobilenet_v1_0.npy index 212e0e7..df256da 100644 Binary files a/tflite_mobilenet_v1_0.npy and b/tflite_mobilenet_v1_0.npy differ