【凌智視覺模塊】rv1106 部署 ppocrv4 檢測模型 rknn 推理

PP-OCRv4 文本框檢測

1. 模型介紹

如有需要可以前往我們的倉庫進行查看 凌智視覺模塊

PP-OCRv4在PP-OCRv3的基礎上進一步升級。整體的框架圖保持了與PP-OCRv3相同的pipeline,針對檢測模型和識別模型進行了數據、網絡結構、訓練策略等多個模塊的優化。
請添加圖片描述

從算法改進思路上看,分別針對檢測和識別模型,進行以下方面的改進:
檢測模塊:

  • LCNetV3:精度更高的骨干網絡
  • PFHead:并行head分支融合結構
  • DSR: 訓練中動態增加shrink ratio
  • CML:添加Student和Teacher網絡輸出的KL div loss

原理可前往PPOCR技術報告查看:https://paddlepaddle.github.io/PaddleOCR/v2.9/ppocr/blog/PP-OCRv4_introduction.html#1pfheadhead

2. 模型轉換

參考RKNN Model ZOO將 PPOCRv4 的文本檢測模型轉化成 RKNN 模型。


import sys
from rknn.api import RKNNDATASET_PATH = '../../../../datasets/PPOCR/imgs/dataset_20.txt'
DEFAULT_RKNN_PATH = '../model/ppocrv4_det.rknn'
DEFAULT_QUANT = Truedef parse_arg():if len(sys.argv) < 3:print("Usage: python3 {} onnx_model_path [platform] [dtype(optional)] [output_rknn_path(optional)]".format(sys.argv[0]));print("       platform choose from [rk3562, rk3566, rk3568, rk3576, rk3588, rv1126b, rv1109, rv1126, rk1808]")print("       dtype choose from    [i8, fp] for [rk3562, rk3566, rk3568, rk3576, rk3588, rv1126b]")print("       dtype choose from    [u8, fp] for [rv1109, rv1126, rk1808]")exit(1)model_path = sys.argv[1]platform = sys.argv[2]do_quant = DEFAULT_QUANTif len(sys.argv) > 3:model_type = sys.argv[3]if model_type not in ['i8', 'u8', 'fp']:print("ERROR: Invalid model type: {}".format(model_type))exit(1)elif model_type in ['i8', 'u8']:do_quant = Trueelse:do_quant = Falseif len(sys.argv) > 4:output_path = sys.argv[4]else:output_path = DEFAULT_RKNN_PATHreturn model_path, platform, do_quant, output_pathif __name__ == '__main__':model_path, platform, do_quant, output_path = parse_arg()# Create RKNN objectrknn = RKNN(verbose=False)# Pre-process configprint('--> Config model')rknn.config(mean_values=[[123.675, 116.28, 103.53]], std_values=[[58.395, 57.12, 57.375]], target_platform=platform)print('done')# Load modelprint('--> Loading model')ret = rknn.load_onnx(model=model_path)if ret != 0:print('Load model failed!')exit(ret)print('done')# Build modelprint('--> Building model')ret = rknn.build(do_quantization=do_quant, dataset=DATASET_PATH)if ret != 0:print('Build model failed!')exit(ret)print('done')# Export rknn modelprint('--> Export rknn model')ret = rknn.export_rknn(output_path)if ret != 0:print('Export rknn model failed!')exit(ret)print('done')# Releaserknn.release()

根據目標平臺,完成參數配置,運行程序完成轉換。在完成模型轉換后可以查看 rv1106 的算子支持手冊,確保所有的算子是可以使用的,避免白忙活。

3. 模型部署

#include <iostream>
#include <cmath>
#include <opencv2/opencv.hpp>
#include "rknpu2_backend/rknpu2_backend.h"
#include <cstdlib>
#include <ctime>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "postprocess.h"
#include <lockzhiner_vision_module/edit/edit.h>
#include <lockzhiner_vision_module/vision/utils/visualize.h>// 用于計時的頭文件
#include <chrono>using namespace std::chrono;int main(int argc, char *argv[])
{if (argc != 2){std::cerr << "Usage: " << argv[0] << " <model_path>" << std::endl;return 1;}const std::string model_path = argv[1];// 初始化RKNN后端lockzhiner_vision_module::vision::RKNPU2Backend backend;if (!backend.Initialize(model_path)){std::cerr << "Failed to initialize RKNN backend" << std::endl;return -1;}lockzhiner_vision_module::edit::Edit edit;if (!edit.StartAndAcceptConnection()){std::cerr << "Error: Failed to start and accept connection." << std::endl;return EXIT_FAILURE;}std::cout << "Device connected successfully." << std::endl;// 打開攝像頭cv::VideoCapture cap;cap.set(cv::CAP_PROP_FRAME_WIDTH, 640);cap.set(cv::CAP_PROP_FRAME_HEIGHT, 480);cap.open(0);if (!cap.isOpened()){std::cerr << "Error: Could not open camera." << std::endl;return 1;}cv::Mat image;int frame_count = 0; // 幀計數器while (true){cap >> image;if (image.empty())continue;frame_count++;// 每隔3幀處理一次(即每4幀處理1次)if (frame_count % 4 == 1){// 獲取輸入Tensor的信息auto input_tensor = backend.GetInputTensor(0);std::vector<size_t> input_dims = input_tensor.GetDims();float input_scale = input_tensor.GetScale();int input_zp = input_tensor.GetZp();// 預處理cv::Mat preprocessed = preprocess(image, input_dims, input_scale, input_zp);if (preprocessed.empty()){std::cerr << "Preprocessing failed" << std::endl;goto skip_inference;}// 驗證輸入數據尺寸size_t expected_input_size = input_tensor.GetElemsBytes();size_t actual_input_size = preprocessed.total() * preprocessed.elemSize();if (expected_input_size != actual_input_size){std::cerr << "Input size mismatch! Expected: " << expected_input_size<< ", Actual: " << actual_input_size << std::endl;goto skip_inference;}// 拷貝輸入數據void *input_data = input_tensor.GetData();memcpy(input_data, preprocessed.data, actual_input_size);// 開始計時auto start = high_resolution_clock::now();// 推理if (!backend.Run()){std::cerr << "Inference failed!" << std::endl;free(input_data);goto skip_inference;}// 結束計時auto end = high_resolution_clock::now();auto duration_ms = duration_cast<milliseconds>(end - start).count();std::cout << "Inference time: " << duration_ms << " ms" << std::endl;// 獲取輸出結果const auto &output_tensor = backend.GetOutputTensor(0);std::vector<size_t> output_dims = output_tensor.GetDims();float output_zp = output_tensor.GetZp();float output_scale = output_tensor.GetScale();const int8_t *output_data_int8 = static_cast<const int8_t *>(output_tensor.GetData());// 轉換為浮點型std::vector<float> output_data_float(output_tensor.GetNumElems());for (size_t i = 0; i < output_tensor.GetNumElems(); ++i){output_data_float[i] = (output_data_int8[i] - output_zp) * output_scale;}// 獲取原始圖像寬高int original_width = image.cols;int original_height = image.rows;float scale_w = (float)original_width / 480;float scale_h = (float)original_height / 480;// 后處理ppocr_det_result results = {0};dbnet_postprocess(output_data_float.data(),output_dims[2], output_dims[3],0.5, 0.3, true, "slow", 2.0, "quad",scale_w, scale_h, &results);// 繪制檢測框draw_boxes(&image, results);}skip_inference:// 顯示當前幀(無論是否進行了推理)edit.Print(image);// 按下 ESC 鍵退出if (cv::waitKey(1) == 27){break;}}cap.release();return 0;
}

4. 編譯程序

使用 Docker Destop 打開 LockzhinerVisionModule 容器并執行以下命令來編譯項目

# 進入Demo所在目錄
cd /LockzhinerVisionModuleWorkSpace/LockzhinerVisionModule/Cpp_example/D11_PPOCRv4-Det
# 創建編譯目錄
rm -rf build && mkdir build && cd build
# 配置交叉編譯工具鏈
export TOOLCHAIN_ROOT_PATH="/LockzhinerVisionModuleWorkSpace/arm-rockchip830-linux-uclibcgnueabihf"
# 使用cmake配置項目
cmake ..
# 執行編譯項目
make -j8 

在執行完上述命令后,會在build目錄下生成可執行文件。

5. 執行結果

5.1 運行前準備

  • 請確保你已經下載了 凌智視覺模塊字符檢測模型權重文件

5.2 運行過程

chmod 777 Test-ppocrv4
./Test-ppocrv4 ppocrv4_det.rknn 

5.3 運行效果

5.3.1 ppocrv4字符識別
  • 測試結果

請添加圖片描述

  • 測試時間

請添加圖片描述

瓶頸分析,雖然 ppocrv4 的文本檢測模型的推理時間為 90ms 左右,但是在實際使用時建議使用跳幀檢測,不每一幀都進行推理,可以有效降低卡頓。

5.3.2 注意事項

由于本章節只部署了一個 PPOCRv4 的文字識別模型,并沒有訓練檢測模型,如需訓練自己的數據集,可使用 paddleOCR 訓練檢測模型。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/86702.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/86702.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/86702.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

uniapp Vue2 獲取電量的獨家方法:繞過官方插件限制

在使用 uniapp 進行跨平臺應用開發時&#xff0c;獲取設備電量信息是一個常見的需求。然而&#xff0c;uniapp 官方提供的uni.getBatteryInfo方法存在一定的局限性&#xff0c;它不僅需要下載插件&#xff0c;而且目前僅支持 Vue3&#xff0c;這讓使用 Vue2 進行開發的開發者陷…

Go語言中的if else控制語句

if else是Go語言中最基礎也最常用的條件控制語句&#xff0c;用于根據條件執行不同的代碼塊。下面我將詳細介紹Go語言中if else的各種用法和特性。 1. 基本語法 1.1. 最簡單的if語句 if 條件表達式 {// 條件為true時執行的代碼 } 示例&#xff1a; if x > 10 {fmt.Prin…

[Spring]-AOP

AOP場景 AOP: Aspect Oriented Programming (面向切面編程) OOP: Object Oriented Programming (面向對象編程) 場景設計 設計: 編寫一個計算器接口和實現類&#xff0c;提供加減乘除四則運算 需求: 在加減乘除運算的時候需要記錄操作日志(運算前參數、運算后結果)實現方案:…

Web3 借貸與清算機制全解析:鏈上金融的運行邏輯

Web3 借貸與清算機制全解析&#xff1a;鏈上金融的運行邏輯 超額抵押借款 例如&#xff0c;借款人用ETH為抵押借入DAI&#xff1b;借款人的ETH的價值一定是要超過DAI的價值&#xff1b;借款人可以任意自由的使用自己借出的DAI 穩定幣 第一步&#xff1a;借款人需要去提供一定…

RK3588開發筆記-GNSS-RTK模塊調試

目錄 前言 一、什么是GNSS/RTK 二、硬件連接 三、內核配置 四、模塊調試 五、ntripclient使用 總結 前言 在RK3588平臺上集成高精度定位功能是許多工業級應用的需求。本文記錄了我調試GNSS-RTK模塊的全過程,包含硬件連接、驅動移植、數據解析和精度優化等關鍵環節,希望對…

Vue.js $emit的介紹和簡單使用

前言 在 Vue.js 開發中&#xff0c;組件化是核心思想之一。但組件間的通信是一個重要課題&#xff0c;特別是子組件向父組件傳遞數據的場景。Vue 提供了多種通信方式&#xff0c;而$emit正是實現子→父通信的關鍵方法。本文將深入解析$emit的原理、使用場景及最佳實踐。 一、$e…

【Linux 學習計劃】-- 簡易版shell編寫

目錄 思路 創建自己的命令行 獲取用戶命令 分割命令 檢查是否是內建命令 cd命令實現 進程程序替換執行程序 總代碼 結語 思路 int main() {while (1){// 1. 自己的命令行PrintCommandLine();// 2. 獲取用戶命令char command[SIZE];int n GetUserCommand(command, si…

一個完整的日志收集方案:Elasticsearch + Logstash + Kibana+Filebeat (二)

&#x1f4c4; 本地 Windows 部署 Logstash 連接本地 Elasticsearch 指南 ? 目標 在本地 Windows 上安裝并運行 Logstash配置 Logstash 將數據發送至本地 Elasticsearch測試數據采集與 ES 存儲流程 &#x1f9f0; 前提條件 軟件版本要求安裝說明Java17Oracle JDK 下載 或 O…

Java使用Selenium反爬蟲優化方案

當我們爬取大站的時候&#xff0c;就得需要對抗反爬蟲機制的場景&#xff0c;因為項目要求使用Java和Selenium。Selenium通常用于模擬用戶操作&#xff0c;但效率較低&#xff0c;所以需要我們結合其他技術來實現高效。 在 Java 中使用 Selenium 進行高效反爬蟲對抗時&#xff…

狀態管理方案對比與決策

1. 狀態管理的基本概念 現代前端應用隨著功能復雜度提升&#xff0c;狀態管理已成為架構設計的核心挑戰。狀態管理本質上解決的是數據的存儲、變更追蹤和響應式更新問題&#xff0c;以確保UI與底層數據保持同步。 核心挑戰: 狀態共享與組件通信可預測的狀態變更性能優化與重…

Fetch與Axios:區別、聯系、優缺點及使用差異

Fetch與Axios&#xff1a;區別、聯系、優缺點及使用差異 文章目錄 Fetch與Axios&#xff1a;區別、聯系、優缺點及使用差異一、聯系二、區別1. 瀏覽器支持與兼容性2. 響應處理3. 請求攔截和響應攔截4. 錯誤處理 三、優缺點1. Fetch API優點缺點 2. Axios優點缺點 四、使用上的差…

【Docker】快速入門與項目部署實戰

我們在部署一個項目時&#xff0c;會出現一系列問題比如&#xff1a; 命令太多了&#xff0c;記不住軟件安裝包名字復雜&#xff0c;不知道去哪里找安裝和部署步驟復雜&#xff0c;容易出錯 其實上述問題不僅僅是新手&#xff0c;即便是運維在安裝、部署的時候一樣會覺得麻煩…

Java面試題尚硅谷版第1季

1、寫出如下代碼運行結果 1.1、 使用局部變量表和操作數棧解題 1.2、使用前置和后置遞增解題 2、寫一個單例模式 2.1、考察知識點 2.2、單例模式實現 3、類加載和初始化順序 package classload;public class Father {private int i test();private static int j method();st…

關于Qt阻斷樣式繼承的解決辦法

引言 在使用 Qt 開發桌面應用時&#xff0c;借助樣式表&#xff08;StyleSheet&#xff09;來統一定義界面風格是非常常見的做法。通常&#xff0c;你會在主程序中通過 qApp->setStyleSheet(...) 或者直接給某個父控件設置樣式表&#xff0c;讓所有的子控件都采用相同的配色…

鼠標右鍵添加新建某種文件的方法

場景 我經常用到.emmx&#xff0c;.eddx文件&#xff0c;電腦上裝的是wpsX億圖&#xff08;因為有wps會員&#xff09;&#xff0c;沒有開億圖會員。 然后問題就是&#xff0c;思維導圖和流程圖我都能正常開&#xff0c;正常編輯&#xff0c;但鼠標右鍵沒有新建這兩個文件的按…

Inxpect安全雷達傳感器與控制器:動態檢測 + 抗干擾技術重構工業安全防護體系

Inxpect 推出工業安全領域新型智能傳感器與控制器&#xff0c;其核心產品為雷達掃描儀&#xff0c;具備動態調整檢測區域、抗干擾能力強等特點&#xff0c;可精準檢測危險區域人員進入或存在情況&#xff0c;適用于移動機器人等場景。 Inxpect安全雷達傳感器核心功能 動態檢測…

【AI學習】李廣密與階躍星辰首席科學家張祥雨對談:多模態發展的歷史和未來

仔細閱讀了文章《專訪張祥雨&#xff1a;多模態推理和自主學習是未來的 2 個 「GPT-4」 時刻》 https://mp.weixin.qq.com/s/892QuRPH9uP6zN6dS-HZMw 非常贊嘆的一篇文章&#xff0c;說清楚了NLP、CV發展中的許多重大問題&#xff0c;讀來醍醐灌頂&#xff01;這樣的文章&…

C++中std::deque詳解和實戰工程代碼示例

C中std::deque詳解和實戰工程代碼示例 std::deque&#xff08;雙端隊列&#xff09;是 C 標準庫中的一個序列容器&#xff0c;與 std::vector 類似&#xff0c;但它支持從頭部和尾部高效地插入和刪除元素。它底層采用分段連續空間實現&#xff0c;兼具靈活性與性能。 一、基本…

【AI大模型入門指南】概念與專有名詞詳解 (二)

【AI大模型入門指南】概念與專有名詞詳解 &#xff08;二&#xff09; 一 、前言 當你和聊天機器人聊得天花亂墜時&#xff0c;當你用文字讓AI生成精美圖片時&#xff0c;當手機相冊自動幫你分類照片時 —— 這些看似智能的操作背后&#xff0c;都藏著 AI 大模型的身影。 本…

AIStor 的模型上下文協議 (MCP) 服務器:管理功能

在本系列的上一篇博文中&#xff0c;我們討論了 MinIO AIStor 的模型上下文協議 (MCP) 服務器的基本用戶級功能。我們學習了如何使用人類語言命令查看存儲桶的內容、分析對象并標記它們以便將來處理&#xff0c;以及如何通過 LLM&#xff08;例如 Anthropic Claude&#xff09;…