高通手機跑AI系列之——人像與背景分割

(原創(chuàng)作者@CSDN_伊利丹~怒風(fēng))

環(huán)境準(zhǔn)備

手機

測試手機型號:Redmi K60 Pro

處理器:第二代驍龍8移動--8gen2

運行內(nèi)存:8.0GB ,LPDDR5X-8400,67.0 GB/s

攝像頭:前置16MP+后置50MP+8MP+2MP

AI算力:NPU 48Tops INT8 && GPU 1536ALU x 2 x 680MHz = 2.089 TFLOPS

提示:任意手機均可以,性能越好的手機運行速度越快

軟件
APP:AidLux2.0

系統(tǒng)環(huán)境:Ubuntu 20.04.3 LTS

提示:AidLux登錄后代碼運行更流暢,在代碼運行時保持AidLux APP在前臺運行,避免代碼運行過程中被系統(tǒng)回收進程,另外屏幕保持常亮,一般息屏后一段時間,手機系統(tǒng)會進入休眠狀態(tài),如需長駐后臺需要給APP權(quán)限。

算法Demo

代碼功能介紹

這段代碼實現(xiàn)了一個基于深度學(xué)習(xí)的實時人像分割應(yīng)用,它通過攝像頭捕獲視頻流,利用輕量級推理引擎 Aidlite 運行人像分割模型,實時識別畫面中的人物區(qū)域,并將人物與背景以視覺上的藍色輪廓效果進行區(qū)分。下面詳細(xì)介紹其功能和工作流程:

核心功能
  1. 視頻流捕獲

    1. 使用 OpenCV 的VideoCapture接口打開前置攝像頭(設(shè)備 ID=1),持續(xù)讀取視頻幀。
    2. 支持 MIPI 接口(適用于嵌入式設(shè)備),具有自動重試機制,確保攝像頭成功開啟。
  2. 人像分割模型推理

    1. 加載預(yù)訓(xùn)練的人像分割模型(.nb格式,由 Aidlite 優(yōu)化)。
    2. 模型輸入為 513×513 像素的 RGB 圖像,輸出為每個像素的分類結(jié)果(0 = 背景,1 = 人物)。
    3. 使用 Aidlite 推理引擎執(zhí)行模型計算,支持 CPU 加速,可在移動設(shè)備上實時運行。
  3. 實時圖像處理

    1. 對每一幀視頻進行預(yù)處理:縮放、通道轉(zhuǎn)換、數(shù)據(jù)類型轉(zhuǎn)換。
    2. 將模型輸出的分割掩碼轉(zhuǎn)換為二值圖像(人物區(qū)域為白色,背景為黑色)。
    3. 通過圖像融合技術(shù)(cv2.addWeighted),將藍色半透明輪廓疊加到原始畫面的人物區(qū)域上。
  4. 性能監(jiān)控與顯示

    1. 計算并顯示幀率(FPS)和單幀推理耗時(毫秒)。
    2. 通過 OpenCV 窗口實時展示處理后的視頻效果。
技術(shù)組件詳解

1. 推理引擎 - Aidlite

Aidlite 是一個輕量級的深度學(xué)習(xí)推理引擎,專為嵌入式設(shè)備和移動設(shè)備優(yōu)化。它具有以下特點:

  • 多框架支持:可以運行來自 TensorFlow、PyTorch、PaddlePaddle 等不同框架訓(xùn)練的模型
  • 硬件加速:支持 CPU、GPU、NPU 等多種硬件后端,充分利用設(shè)備算力
  • 模型優(yōu)化:通過量化、剪枝等技術(shù)減小模型體積,提高推理速度
  • 輕量級設(shè)計:內(nèi)存占用小,適合資源受限的設(shè)備

在這段代碼中,Aidlite 被配置為使用 PaddlePaddle 框架訓(xùn)練的模型,并通過 CPU 進行推理。

2. 計算機視覺庫 - OpenCV (cv2)

OpenCV 是一個強大的計算機視覺庫,在這段代碼中主要用于:

  • 視頻捕獲與處理:通過cv2.VideoCapture獲取攝像頭視頻流
  • 圖像處理:調(diào)整圖像大小 (cv2.resize)、翻轉(zhuǎn) (cv2.flip)
  • 圖像融合:使用cv2.addWeighted實現(xiàn)半透明效果
  • 顯示結(jié)果:通過cv2.imshow顯示處理后的圖像

3. AI 模型功能

代碼中使用的 AI 模型是一個人像分割模型,它能夠:

  • 輸入:RGB 圖像 (513×513 像素)
  • 輸出:像素級別的分類結(jié)果 (每個像素被分類為 "人物" 或 "背景")
  • 工作原理:基于深度學(xué)習(xí)的語義分割技術(shù),識別圖像中的人物區(qū)域
  • 應(yīng)用場景:視頻會議背景虛化、AR 試衣、短視頻特效等

應(yīng)用場景

這個代碼示例可以應(yīng)用于以下場景:

  1. 視頻會議:實時背景虛化或替換,增強會議隱私和專業(yè)性
  2. 直播與短視頻:添加實時人像特效,如輪廓高亮、動態(tài)貼紙等
  3. 健身與運動應(yīng)用:實時跟蹤人體動作,提供運動指導(dǎo)
  4. 安防監(jiān)控:檢測和跟蹤特定區(qū)域內(nèi)的人員活動

通過調(diào)整transfer函數(shù),可以實現(xiàn)更多樣化的視覺效果,如背景模糊、背景替換、動態(tài)濾鏡等。

DEMO代碼

import cv2
import time 
from time import sleep
import remi
import os
import sys
import numpy as np
import aidlite
 
def transfer(image, mask):
    """
    將分割掩碼與原始圖像融合,創(chuàng)建半透明效果
    
    參數(shù):
        image: 原始圖像,BGR格式
        mask: 分割掩碼,單通道二值圖像(0表示背景,255表示人物)
        
    返回:
        融合后的圖像
    """
    # 調(diào)整掩碼大小以匹配原始圖像
    mask = cv2.resize(mask, (image.shape[1], image.shape[0]))
    # 創(chuàng)建三通道掩碼圖像(只在藍色通道填充值)
    mask_n = np.zeros_like(image)
    mask_n[:, :, 0] = mask  # 將掩碼值賦給藍色通道,產(chǎn)生藍色輪廓效果
    
    # 圖像融合參數(shù)(alpha透明度)
    alpha = 0.7
    beta = (1.0 - alpha)
    # 加權(quán)融合原始圖像和掩碼圖像
    dst = cv2.addWeighted(image, alpha, mask_n, beta, 0.0)
    return dst
 
# 模型輸入輸出參數(shù)配置
w = 513  # 模型輸入寬度
h = 513  # 模型輸入高度
inShape = [[1, 3, 513, 513]]  # 輸入張量形狀: [批次大小, 通道數(shù), 高度, 寬度]
outShape = [[1, w, h]]  # 輸出張量形狀: [批次大小, 高度, 寬度]
model_path = "models/model.nb"  # 模型文件路徑(.nb格式為Aidlite優(yōu)化后的模型格式)
 
# ------------------------ Aidlite推理引擎初始化 ------------------------
# 創(chuàng)建Aidlite模型實例
model = aidlite.Model.create_instance(model_path)
if model is None:
    print("Create model failed !")
 
# 設(shè)置模型輸入輸出數(shù)據(jù)類型和形狀
model.set_model_properties(inShape, aidlite.DataType.TYPE_FLOAT32, outShape, aidlite.DataType.TYPE_INT64)
 
# 創(chuàng)建配置實例,設(shè)置模型框架類型和加速類型
config = aidlite.Config.create_instance()
config.framework_type = aidlite.FrameworkType.TYPE_PADDLE  # 模型基于PaddlePaddle框架訓(xùn)練
config.accelerate_type = aidlite.AccelerateType.TYPE_CPU  # 使用CPU進行推理(也支持GPU、NPU等)
 
# 構(gòu)建并初始化解釋器
fast_interpreter = aidlite.InterpreterBuilder.build_interpretper_from_model_and_config(model, config)
if fast_interpreter is None:
    print("build_interpretper_from_model_and_config failed !")
 
result = fast_interpreter.init()
if result != 0:
    print("interpreter init failed !")
 
result = fast_interpreter.load_model()
if result != 0:
    print("interpreter load model failed !")
 
print("model load success!")
 
# ------------------------ 視頻流處理與推理 ------------------------
# 嘗試打開前置攝像頭(設(shè)備ID為1)
camId = 1
opened = False
while not opened:
    # 使用mipi接口打開攝像頭(適用于某些嵌入式設(shè)備)
    cap = cv2.VideoCapture(camId, device='mipi')
    if cap.isOpened():
        opened = True
    else:
        print("open camera failed")
        cap.release()
        time.sleep(0.5)
 
# 主循環(huán): 捕獲視頻幀并進行實時處理
while True:
    ret, frame = cap.read()
    if not ret:
        continue
    if frame is None:
        continue
    
    # 如果使用前置攝像頭,水平翻轉(zhuǎn)圖像以獲得自然的鏡像效果
    frame = cv2.flip(frame, 1)
    
    # 圖像預(yù)處理: 調(diào)整大小并轉(zhuǎn)換為模型輸入格式
    img = cv2.resize(frame, (w, h))
    input = img.astype(np.float32)  # 轉(zhuǎn)換為浮點類型
    input = np.transpose(input, (2, 0, 1))  # 調(diào)整通道順序: [H,W,C] -> [C,H,W]
    print('input', input.shape)
    
    # 設(shè)置輸入數(shù)據(jù)到推理引擎
    print('paddle: start set')
    result = fast_interpreter.set_input_tensor(0, input)
    if result != 0:
        print("interpreter set_input_tensor() failed")
    
    # 記錄推理開始時間
    start_time = time.time()
    print('bnn: start invoke')
    
    # 執(zhí)行模型推理
    result = fast_interpreter.invoke()
    if result != 0:
        print("interpreter invoke() failed")
 
    print('invoke end')
    # 計算推理耗時并轉(zhuǎn)換為毫秒
    t = (time.time() - start_time)
    print('elapsed_ms invoke:', t * 1000)
    # 計算幀率并顯示在畫面上
    lbs = 'Fps: '+ str(int(1 / t)) + " ~~ Time:" + str(t * 1000) + "ms"
    
    # 獲取模型輸出結(jié)果
    print('paddle: start get')
    pred_0 = fast_interpreter.get_output_tensor(0, output_type=aidlite.DataType.TYPE_INT64)
    if pred_0 is None:
        print("sample : interpreter->get_output_tensor(0) failed !")
 
    # 后處理: 重塑輸出張量并創(chuàng)建二值人物掩碼
    pred0 = (pred_0).reshape(w, h)
    # 將模型預(yù)測結(jié)果中類別為1的像素設(shè)為255(人物),其余設(shè)為0(背景)
    person = np.where(pred0 == 1, 255, 0).astype(np.uint8)
    # 將掩碼與原始圖像融合
    dst = transfer(frame, person)
 
    # 顯示結(jié)果
    cv2.imshow("", dst)
 
    # 按 'q' 鍵退出循環(huán)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
 
# 釋放資源
cap.release()
cv2.destroyAllWindows()

模型位置

/opt/aidlux/app/aid-examples//portrait_seg

模型效果

c3dea20fd08b4b10891f4e5bf6537dcf.gif
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容