【凌智視覺模塊】rv1106 部署 pp-humseg 模型

人像分割簡介

? 凌智視覺模塊 是一款基于rv1106芯片開發的視覺模塊,專注于視覺模型部署與開發。
人像分割是一種基于計算機視覺的技術,通過深度學習算法精準識別圖像或視頻中的人物主體,將其與背景進行像素級分離。該技術可實時運行于移動端及嵌入式設備,廣泛應用于虛擬背景、智能摳圖、視頻會議美顏等場景,支持復雜光照、多樣姿態和遮擋情況下的高精度分割,兼顧處理速度與效果。

人像分割常用方法

目前對于實現人像分割任務的方法有很多,下面介紹幾種常用的人像分割實現方法:

  • 傳統算法(如GrabCut):基于顏色直方圖與圖割優化,適合簡單背景,計算量小但精度有限。
  • U-Net系列:編碼器-解碼器結構,醫學圖像起家,適合精細邊緣,需較高算力。
  • DeepLab系列:采用空洞卷積擴大感受野,擅長復雜場景,模型較大。
  • BiSeNet:雙分支結構平衡速度與精度,實時分割首選,移動端友好。
  • PP-HumanSeg:百度自研輕量模型,專為人像優化,支持半監督訓練。

PP-HumanSeg模型簡介

將人物和背景在像素級別進行區分,是一個圖像分割的經典任務,具有廣泛的應用。 一般而言,該任務可以分為兩類:針對半身人像的分割,簡稱肖像分割;針對全身和半身人像的分割,簡稱通用人像分割。

對于肖像分割和通用人像分割,PaddleSeg發布了PP-HumanSeg系列模型,具有分割精度高、推理速度快、通用型強的優點。而且PP-HumanSeg系列模型可以開箱即用,零成本部署到產品中,也支持針對特定場景數據進行微調,實現更佳分割效果。

2022年7月,PaddleSeg重磅升級的PP-HumanSegV2人像分割方案,以96.63%的mIoU精度, 63FPS的手機端推理速度,再次刷新開源人像分割算法SOTA指標。相比PP-HumanSegV1方案,推理速度提升87.15%,分割精度提升3.03%,可視化效果更佳。V2方案可與商業收費方案媲美,而且支持零成本、開箱即用!

PP-HumanSeg由飛槳官方出品,是PaddleSeg團隊推出的模型和方案。

這些方法各有優勢,其中在工業部署方面 PP-HumanSeg(精度與速度平衡)和 BiSeNet(高性價比)更適合,配合 OpenCV 后處理優化邊緣。


API 介紹

RKNPU2Backend 類

####頭文件

#include "rknpu2_backend/rknpu2_backend.h"

作用:創建一個 RKNPU2Backend 類,用于實現對 RKNN 模型的處理。

構造類函數
ockzhiner_vision_module::vision::RKNPU2Backend backend;

作用:創建一個 RKNPU2Backend 類型的對象實例,用于實現人像分割。

  • 參數說明:無
  • 返回值:無
Initialize 函數
bool Initialize(const std::string &model_path, const std::string &param_path = "") override;

作用:初始化 RKNN 模型,加載模型文件和可選參數文件,完成推理引擎的準備工作。

  • 參數說明:
    • model_path:必需參數,RKNN 模型文件路徑(.rknn 格式)
    • param_path:可選參數,額外參數文件路徑(某些場景下用于補充模型配置,默認空字符串)
  • 返回值:返回 true/false,表示模型初始化是否成功。
Run 函數
bool Run();

作用:執行模型推理計算,驅動輸入數據通過模型計算得到輸出結果。

  • 參數說明:無
  • 返回值:
    • true:推理執行成功
    • false:推理失敗(可能原因:輸入數據未準備、內存不足等)
GetInputAttrs 函數
const std::vector<rknn_tensor_attr>& GetInputAttrs() const;

作用:獲取模型所有輸入張量的屬性信息(維度/形狀、數據類型、量化參數等)。

  • 參數說明:無
  • 返回值:常量引用形式的 rknn_tensor_attr 向量,包含輸入張量屬性。
GetOutputAttrs 函數
const std::vector<rknn_tensor_mem*>& GetInputMemories() const;

作用:獲取模型所有輸出張量的屬性信息。

  • 參數說明:無
  • 返回值:常量引用形式的 rknn_tensor_attr 向量,包含輸出張量屬性。

PP-Humanseg 人像分割代碼解析

流程圖

開始
│
├── 參數檢查 (argc == 3)
│   └── 錯誤 → 輸出Usage并退出
│
├── 初始化 RKNN 后端
│   ├── 加載模型
│   └── 初始化失敗 → 錯誤退出
│
├── 加載與預處理輸入圖像
│   ├── 讀取圖像文件
│   ├── 獲取輸入屬性
│   ├── 調用 preprocess() 函數
│       ├── 調整尺寸和顏色空間
│       ├── 量化圖像數據
│       └── 驗證尺寸匹配
│   └── 預處理失敗 → 錯誤退出
│
├── 執行推理
│   ├── 拷貝預處理后的圖像數據到輸入內存
│   ├── 執行推理
│       └── 推理失敗 → 錯誤退出
│
├── 后處理
│   ├── 獲取輸出屬性及內存
│   ├── 調用 postprocess() 函數
│       ├── 解析輸出數據生成概率圖
│       ├── 自適應閾值分割
│       ├── 多尺度形態學處理
│       ├── 智能邊緣優化
│       └── 多模態結果融合
│
├── 結果展示與保存
│   ├── 計算推理時間
│   ├── 生成并保存結果圖像
│   ├── 顯示原始圖像、掩膜及結果圖像
│
└── 程序結束

核心代碼解析

初始化模型
backend.Initialize(model_path)
獲取輸入輸出屬性
const auto& input_attrs = backend.GetInputAttrs();
const auto& output_attrs = backend.GetOutputAttrs();
對輸入圖像進行推理
backend.Run()

自定義函數說明

pp-humanseg 輸入預處理
cv::Mat preprocess(const cv::Mat& image, const std::vector<size_t>& input_dims) 

作用:對輸入圖像進行預處理操作,包括 尺寸調整顏色空間轉換量化處理,使其符合 RKNN 模型的輸入要求。

  • 參數說明:
    • image:輸入圖像(BGR 格式的 cv::Mat 對象)
    • input_dims:模型輸入張量的維度定義(需滿足 [1, H, W, 3] 的 NHWC 格式)
  • 返回值:
    • 返回預處理后的量化張量(cv::Mat,數據類型為 CV_8S
    • 若輸入維度不合法,返回空矩陣(cv::Mat())并報錯

pp-humanseg 輸入后處理
cv::Mat postprocess(const rknn_tensor_mem* output_mem, const std::vector<size_t>& output_dims,const cv::Size& target_size) 

作用:將模型輸出的原始張量轉換為高精度分割掩膜,包含 概率解碼動態閾值分割形態學優化邊緣增強 等步驟,最終生成與原始圖像尺寸匹配的二值化掩膜。

  • 參數說明:
    • output_mem:模型輸出的內存指針,包含量化后的原始數據
    • output_dims:模型輸出的維度信息,需滿足 [1, 2, H, W] 的 NCHW 格式
    • target_size:目標輸出尺寸
  • 返回值:返回優化后的二值化掩膜

###完整代碼實現

由于篇幅限制,此處僅展示關鍵代碼邏輯。實際開發中請結合具體項目工程使用。

int main(int argc, char* argv[]) {if (argc != 3) {std::cerr << "Usage: " << argv[0] << " <model_path> <image_path>" << std::endl;return 1;}const std::string model_path = argv[1];const std::string image_path = argv[2];// 初始化RKNN后端lockzhiner_vision_module::vision::RKNPU2Backend backend;if (!backend.Initialize(model_path)) {std::cerr << "Failed to initialize RKNN backend" << std::endl;return -1;}// 加載圖像cv::Mat image = cv::imread(image_path);if (image.empty()) {std::cerr << "Failed to read image: " << image_path << std::endl;return -1;}// 獲取輸入屬性const auto& input_attrs = backend.GetInputAttrs();if (input_attrs.empty()) {std::cerr << "No input attributes found" << std::endl;return -1;}const auto& input_attr = input_attrs[0];std::vector<size_t> input_dims(input_attr.dims, input_attr.dims + input_attr.n_dims);// 預處理cv::Mat preprocessed = preprocess(image, input_dims);if (preprocessed.empty()) {std::cerr << "Preprocessing failed" << std::endl;return -1;}// 驗證輸入數據尺寸const size_t expected_input_size = input_attr.size_with_stride;const 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;return -1;}// 拷貝輸入數據const auto& input_memories = backend.GetInputMemories();if (input_memories.empty() || !input_memories[0]) {std::cerr << "Invalid input memory" << std::endl;return -1;}memcpy(input_memories[0]->virt_addr, preprocessed.data, actual_input_size);// 執行推理high_resolution_clock::time_point start_time =high_resolution_clock::now();if (!backend.Run()) {std::cerr << "Inference failed" << std::endl;return -1;}// 獲取輸出const auto& output_attrs = backend.GetOutputAttrs();if (output_attrs.empty()) {std::cerr << "No output attributes found" << std::endl;return -1;}const auto& output_memories = backend.GetOutputMemories();if (output_memories.empty() || !output_memories[0]) {std::cerr << "Invalid output memory" << std::endl;return -1;}// 后處理const auto& output_attr = output_attrs[0];std::vector<size_t> output_dims(output_attr.dims, output_attr.dims + output_attr.n_dims);cv::Mat mask = postprocess(output_memories[0], output_dims, image.size());high_resolution_clock::time_point end_time = high_resolution_clock::now();auto time_span = duration_cast<milliseconds>(end_time - start_time);std::cout << "單張圖片推理時間(ms): " << time_span.count() << std::endl;// 生成結果cv::Mat result;cv::bitwise_and(image, image, result, mask);// 保存結果const std::string output_path = "result.jpg";cv::imwrite(output_path, result);std::cout << "Result saved to: " << output_path << std::endl;// 顯示調試視圖cv::imshow("Original", image);cv::imshow("Mask", mask);cv::imshow("Result", result);cv::waitKey(0);return 0;
}

完整代碼可前往我們的倉庫 凌智視覺模塊 查看


📌 總結

你提到的觀點非常有見地,尤其是在嵌入式邊緣計算設備上部署深度學習模型時,性能瓶頸往往并不在 NPU 的算力本身,而是在 CPU 與內存之間的協同效率。下面我們來系統性地分析一下 RV1106 G3 芯片(256MB RAM,1.2GHz 單核 CPU,NPU 算力 1TOPS INT8) 在運行 PP-HumanSeg 人像分割模型時可能遇到的瓶頸。


🧠 RV1106G3 性能瓶頸分析 —— 以 PP-HumanSeg 模型為例

? 芯片參數概覽

參數
CPU單核 ARM Cortex-A7 1.2GHz
內存256MB LPDDR4x
NPU1TOPS INT8 算力
應用場景邊緣 AI 推理、圖像處理

🔍 從硬件架構角度看瓶頸來源

1. CPU 性能限制

  • 單核設計 + 主頻 1.2GHz,對于復雜的數據預處理(如 OpenCV 中的 resize、cvtColor、歸一化等操作)、數據搬運、模型輸入輸出管理、后處理(形態學運算、邊緣優化)等任務來說,很容易成為瓶頸。
  • 特別是當模型推理速度很快(NPU 加速),但 CPU 處理圖像慢于推理速度時,整體幀率將受限于 CPU 的處理能力。

2. 內存帶寬 & 容量限制

  • 僅 256MB 內存,對于圖像進行處理時,容易出現:
    • 圖像緩存不足
    • 多幀緩沖困難
    • 大尺寸模型加載失敗
  • 數據頻繁在內存和 NPU 之間搬運,增加訪存開銷,降低整體吞吐。

3. NPU 并非瓶頸

  • PP-HumanSeg 是輕量化模型,且支持 INT8 推理,其計算量對 1TOPS 的 NPU 來說完全足夠。


? 標簽:#圖像分割 #PP-HumanSeg #RKNN #OpenCV #C++ #AI部署 #人像分割 #PaddleSeg #邊緣計算

🔚 版權聲明:本文為原創文章,轉載請注明出處。未經許可,禁止轉載。

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

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

相關文章

wangeditor富文本編輯器+vue3粘貼內容樣式處理

又是一個風格和日立的上午&#xff0c;某只菜鳥高高興興的騎著小電驢去上班&#xff0c;本著上班只要不遲到的理念飛速前行&#xff08;遲到扣錢啊~&#xff09;&#xff0c;高高興興的行走在路上。來到工位剛拴上我的繩子組長就開始滴滴俺&#xff0c;頓時我心中大感不妙&…

實測,大模型誰更懂數據可視化?

大家好&#xff0c;我是 Ai 學習的老章 看論文時&#xff0c;經常看到漂亮的圖表&#xff0c;很多不知道是用什么工具繪制的&#xff0c;或者很想復刻類似圖表。 實測&#xff0c;大模型 LaTeX 公式識別&#xff0c;出乎預料 前文&#xff0c;我用 Kimi、Qwen-3-235B-A22B、…

深度學習-梯度消失和梯度爆炸

梯度消失 在某些神經網絡中&#xff0c;隨著網絡深度的增加&#xff0c;梯度在隱藏層反向傳播時傾向于變小&#xff0c;這就意味著&#xff0c;前面隱藏層中的神經元要比后面的學習起來更慢&#xff0c;這種現象就叫做“梯度消失”&#xff1b; 梯度爆炸 如果我們進行一些特殊…

Go 語言基礎 2 Func,流程控制

更多個人筆記見&#xff1a; github個人筆記倉庫 gitee 個人筆記倉庫 個人學習&#xff0c;學習過程中還會不斷補充&#xff5e; &#xff08;后續會更新在github上&#xff09; 文章目錄 Func 函數函數棧概念 函數表示類型 Anonymous func 匿名函數closure 閉包基礎示例http利…

【Linux 學習計劃】-- 倒計時、進度條小程序

目錄 \r 、\n、fflush 倒計時 進度條 進度條進階版 結語 \r 、\n、fflush 首先我們先來認識這三個東西&#xff0c;這將會是我們接下來兩個小程序的重點之一 首先是我們的老演員\n&#xff0c;也就是回車加換行 這里面其實包含了兩個操作&#xff0c;一個叫做回車&…

從零實現wss通信示例(WebSocket SSL)

客戶端和服務端代碼框架跟上一篇一致,僅增加了ssl的證書部分用于加密通信,明文通信(ws協議)見上一篇【https://blog.csdn.net/suoxd123/article/details/148093934】 1. 證書創建 1. 安裝openssl 【官網地址】:https://slproweb.com/products/Win32OpenSSL.html 1.2 …

mysql 索引失效有哪些

InnoDB存儲引擎根據索引類型不同&#xff0c;分為聚簇索引和二級索引 聚簇索引&#xff1a;葉子節點存放的是實際數據 二級索引&#xff1a;存放的是主鍵值&#xff0c;不是實際數據 1.對索引使用左或者左右模糊匹配 select * from t_user where name like %林‘&#xff1b…

LabVIEW通用測控平臺設計

基于 LabVIEW 圖形化編程環境&#xff0c;設計了一套適用于工業自動化、科研測試領域的通用測控平臺。通過整合研華、NI等品牌硬件&#xff0c;實現多類型數據采集、實時控制及可視化管理。平臺采用模塊化架構&#xff0c;支持硬件靈活擴展&#xff0c;解決了傳統測控系統開發周…

華為OD機試真題——智能駕駛(2025A卷:200分)Java/python/JavaScript/C/C++/GO最佳實現

2025 A卷 200分 題型 本專欄內全部題目均提供Java、python、JavaScript、C、C++、GO六種語言的最佳實現方式; 并且每種語言均涵蓋詳細的問題分析、解題思路、代碼實現、代碼詳解、3個測試用例以及綜合分析; 本文收錄于專欄:《2025華為OD真題目錄+全流程解析+備考攻略+經驗分…

速賣通,國際站測評補單,如何平衡效率和安全

測評能夠幫助賣家讓平臺更喜歡自己的產品&#xff0c;給予更好排名的同時也讓后續進入店鋪的買家更容易認可自己的產品。這是進行真實交易后形成的評價&#xff0c;而不是通過機器軟件生成&#xff0c;形成虛擬數據后&#xff0c;那種刷評形式產生的評論。它符合任何電商平臺的…

學習路之PHP--easyswoole3.3入門及文件熱加載

學習路之PHP--easyswoole入門 一、框架說明二、常用命令三、文件熱加載 一、框架說明 目錄結構 目錄結構 project 項目部署目錄 ├─App 應用目錄(可以有多個) │ ├─HttpController 控制器目錄 │ │ └─Index.php …

設計模式26——解釋器模式

寫文章的初心主要是用來幫助自己快速的回憶這個模式該怎么用&#xff0c;主要是下面的UML圖可以起到大作用&#xff0c;在你學習過一遍以后可能會遺忘&#xff0c;忘記了不要緊&#xff0c;只要看一眼UML圖就能想起來了。同時也請大家多多指教。 解釋器模式&#xff08;Interp…

第三屆寧波技能大賽網絡安全賽項樣題

2025 第三屆寧波技能大賽網絡安全賽項樣題 模塊A: 網絡安全事件響應、數字取證調查和應用安全任務一:應急響應任務二:操作系統取證任務三:網絡數據包分析任務四:代碼審計 模塊B:CTF 奪旗-攻擊模塊C:CTF 奪旗-防御需要環境培訓可以私信博主&#xff01;&#xff01;&#xff01;…

GO語言進階:掌握進程OS操作與高效編碼數據轉換

&#x1f49d;&#x1f49d;&#x1f49d;歡迎蒞臨我的博客&#xff0c;很高興能夠在這里和您見面&#xff01;希望您在這里可以感受到一份輕松愉快的氛圍&#xff0c;不僅可以獲得有趣的內容和知識&#xff0c;也可以暢所欲言、分享您的想法和見解。 推薦&#xff1a;「storms…

IO進程(進程 Process)

什么是進程&#xff1f; 1.概念 程序&#xff1a;編譯好的可執行文件&#xff0c;存放在磁盤上的指令和數據的有序集合。 由此可見程序是靜態的&#xff0c;沒有執行的概念。 進程&#xff1a;是程序的一次執行的過程&#xff0c;是一個可調度的任務&#xff0c;也是執行一…

CSS傳統布局與定位詳解與TDK三大標簽SEO優化

一、傳統布局基礎 1. 文檔流布局 瀏覽器默認的文檔流布局方式遵循以下規則&#xff1a; 塊級元素&#xff08;如<div>、<p>、<h1>&#xff09;&#xff1a; 獨占一行寬度默認100%可以設置寬高、內外邊距 div {width: 500px;height: 200px;margin: 10px …

【GraphQL】深入解析 Apollo Client:從架構到實踐的一站式 GraphQL 解決方案

深入解析 Apollo Client&#xff1a;從架構到實踐的一站式 GraphQL 解決方案 1. 引言 GraphQL 作為現代 API 開發的核心技術&#xff0c;其靈活性和高效性正在重塑數據交互模式。Apollo Client 作為 GraphQL 生態中最受歡迎的客戶端庫&#xff0c;憑借強大的緩存機制、框架集…

docker學習基本使用教程

docker是一款用于開發部署和運行容器化平臺&#xff0c;能將應用及其依賴打包成輕量級、可移植的容器&#xff0c;實現一次構建&#xff0c;隨處運行。docker是cs架構程序&#xff08;客戶端和服務端&#xff09;&#xff0c;docker客戶端向docker守護進程發送請求&#xff0c;…

萬字詳解RTR RTSP SDP RTCP

目錄 1 RTSP1.1 RTSP基本簡介1.2 RSTP架構1.3 重點內容分析 2 RTR2.1 RTR簡介2.2 RTP 封裝 H.2642.3 RTP 解封裝 H.2642.4 RTP封裝 AAC2.5 RTP解封裝AAC 3 SDP3.1 基礎概念3.2 SDP協議示例解析3.3 重點知識 4 RTCP4.1 RTCP基礎概念4.2 重點 5 總結 1 RTSP 1.1 RTSP基本簡介 一…

唯一原生適配鴻蒙電腦的遠程控制應用,向日葵正式上線

近日&#xff0c;華為正式發布鴻蒙電腦新品&#xff0c;標志著HarmonyOS在PC端生態的進一步拓展。作為遠程控制領域的先行者&#xff0c;貝銳科技旗下的向日葵遠程控制軟件也在第一時間完成了對鴻蒙電腦系統的原生適配&#xff0c;并已正式上線華為鴻蒙電腦應用市場&#xff0c…