PaddleLite使用

PaddleLite模型使用
PaddleLite使用流程基本上和TensorflowLite大體類似缤弦,只不過輸入Tensor的shape信息需要用戶自行分配,否則輸入和輸出Tensor的shape信息全都是默認(rèn)值0

1狸捅、配置 Config 信息:創(chuàng)建 MobileConfig 尘喝,用于配置模型路徑斋陪、運(yùn)行設(shè)備環(huán)境等相關(guān)信息
2、通過 set_model_from_file 接口配置模型路徑

  paddle::lite_api::MobileConfig config;
  config.set_model_from_file(model_path);
  config.set_threads(CPU_THREAD_NUM);
  config.set_power_mode(CPU_POWER_MODE);

3鞍匾、通過 CreatePaddlePredictor 接口創(chuàng)建 Predictor 對像橡淑,完成模型解析和環(huán)境初始化咆爽。

p->predictor = paddle::lite_api::CreatePaddlePredictor<paddle::lite_api::MobileConfig>(config);

4置森、推理之前需要向輸入 Tensor 中填充數(shù)據(jù)凫海。即通過 predictor->GetInput(num) 接口獲取第 num 個(gè)輸入 tensor男娄,也可以通過name來獲取,獲取輸入Tensor后先做 Resize 處理建瘫,給 tensor 分配相應(yīng)的空間啰脚;然后通過獲取 input_tensor->mutable_data<Dtype>() 輸入數(shù)據(jù)地址進(jìn)行賦值處理

const std::vector<int64_t> INPUT_SHAPE = {1, 426, 640, 3};// NHWC格式
std::unique_ptr<paddle::lite_api::Tensor> input_tensor(
      std::move(predictor->GetInput(0)));
input_tensor->Resize(INPUT_SHAPE);

auto *input_data = input_tensor->mutable_data<float>();//這里模型輸入類型fp32
uint8_t *image_data = reinterpret_cast<uint8_t *>(resize_image.data);
cv::Mat out_img = cv::Mat::ones(input_height, input_width, CV_8UC3);
for (int i = 0; i < input_height; ++i) {
    for (int j = 0; j < input_width; ++j) {
        float r = image_data[(i * input_width + j) * 3 + 0];
        float g = image_data[(i * input_width + j) * 3 + 1];
        float b = image_data[(i * input_width + j) * 3 + 2];
        float rr = std::max(-1.0f, std::min(r / 127.5f - 1.0f, 1.0f));//具體模型處理不同
        float gg = std::max(-1.0f, std::min(g / 127.5f - 1.0f, 1.0f));
        float bb = std::max(-1.0f, std::min(b / 127.5f - 1.0f, 1.0f));
        *input_data++ = rr;
        *input_data++ = gg;
        *input_data++ = bb;
        out_img.at<cv::Vec3b>(i, j)[0] = (uint8_t) (r * 255);
        out_img.at<cv::Vec3b>(i, j)[1] = (uint8_t) (g * 255);
        out_img.at<cv::Vec3b>(i, j)[2] = (uint8_t) (b * 255);
    }
}
cv::imwrite("../input.png", out_img);

5橄浓、使用 Predictor 對像的成員函數(shù) Run 進(jìn)行模型推理

predictor->Run();

6荸实、推理執(zhí)行結(jié)束后缴淋,通過 predictor->GetOutput(num) 接口獲取第 num 個(gè)輸出 tensor

std::unique_ptr<const paddle::lite_api::Tensor> output_tensor(
      std::move(predictor->GetOutput(0)));  
const float *output_data = output_tensor->mutable_data<float>();
// NHWC
int h = output_tensor->shape().at(1);
int w = output_tensor->shape().at(2);
int c = output_tensor->shape().at(3);
static uint8_t *s_texbuf = nullptr;//紋理內(nèi)存
if (s_texbuf == nullptr) {
    s_texbuf = (uint8_t *) calloc(1, w * h * 4);
}
uint8_t *d = s_texbuf; 
for (int y = 0; y < h; y++) {
    for (int x = 0; x < w; x++) {
        float r = *output_data++;
        float g = *output_data++;
        float b = *output_data++;
        r = (uint8_t) ((r + 1.0f) / 2.0f * 255);//具體模型處理這里不同
        g = (uint8_t) ((g + 1.0f) / 2.0f * 255);
        b = (uint8_t) ((b + 1.0f) / 2.0f * 255);
        r = std::min(255.0f, r);
        g = std::min(255.0f, g);
        b = std::min(255.0f, b);
        *d++ = r;
        *d++ = g;
        *d++ = b;
        *d++ = 0xFF; 
    }
} 

使用過程遇到問題
如何確定模型預(yù)處理和后處理所做的操作
PaddleHub項(xiàng)目提供的待優(yōu)化的模型壓縮包python腳本包含了圖像預(yù)處理和后處理過程宴猾,只需要將python代碼中必須的代碼轉(zhuǎn)化為c++版本即可仇哆,以animegan_v2_shinkai_33模型為例夫植,解壓后的目錄格式

animegan_v2_shinkai_33                                              
│   ├── animegan_v2_shinkai_33                                       
│   │   ├── __model__
│   │   ├── generator_G_MODEL_A_Conv_1_weights
│   │   ├── generator_G_MODEL_A_Conv_2_weights
│   │   ├── generator_G_MODEL_A_Conv_weights
│   │   ├── generator_G_MODEL_A_LayerNorm_1_beta
│   │   ├── generator_G_MODEL_A_LayerNorm_1_gamma
│   │   └── ......
    └── model.py
    └── module.py
    └── processor.py

module.py腳本中推斷邏輯

加載數(shù)據(jù)處理器

processor = Processor(
    images, 
    paths,  
    output_dir, 
    min_size, 
    max_size
)

# 模型預(yù)測
outputs = self.model.predict(processor.input_datas)

# 結(jié)果后處理
results = processor.postprocess(outputs, visualization)

# 返回結(jié)果
return results

processor.py中預(yù)處理和后處理邏輯

    # 數(shù)據(jù)預(yù)處理函數(shù)
    def preprocess(self):
        input_datas = []

        # 數(shù)據(jù)預(yù)處理
        for i, img in enumerate(self.datas):
            # 格式轉(zhuǎn)換
            img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
            
            # 縮放圖片
            h, w = img.shape[:2]
            if max(h,w)>self.max_size:
                img = cv2.resize(img, (self.max_size, int(h/w*self.max_size))) if h<w else cv2.resize(img, (int(w/h*self.max_size), self.max_size))
            elif min(h,w)<self.min_size:
                img = cv2.resize(img, (self.min_size, int(h/w*self.min_size))) if h>w else cv2.resize(img, (int(w/h*self.min_size), self.min_size))

            # 裁剪圖片
            h, w = img.shape[:2]
            img = img[:h-(h%32), :w-(w%32), :]

            # 歸一化
            img = img/127.5 - 1.0

            # 新建維度
            img = np.expand_dims(img, axis=0).astype('float32')

            # 加入輸入數(shù)據(jù)列表
            input_datas.append(img)

        # 數(shù)據(jù)按batch_size切分
        input_datas = np.concatenate(input_datas, 0)
        split_num = len(self.datas)//self.batch_size+1 if len(self.datas)%self.batch_size!=0 else len(self.datas)//self.batch_size
        input_datas = np.array_split(input_datas, split_num)   

        # 返回預(yù)處理完成的數(shù)據(jù)
        return input_datas
    
    # 后處理函數(shù)
    def postprocess(self, outputs, visualization):
        results = []

        for im_id, output in enumerate(outputs):
            # 反歸一化
            image = (output.squeeze() + 1.) / 2 * 255

            # 限幅
            image = np.clip(image, 0, 255).astype(np.uint8)

            # 格式轉(zhuǎn)換
            image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

            # 可視化
            if visualization:
                # 檢查輸出目錄
                check_dir(self.output_dir)

                # 寫入輸出圖片
                cv2.imwrite(os.path.join(self.output_dir, '%d_%d.jpg' % (im_id, time.time())), image)

            results.append(image)

        # 返回結(jié)果
        return results

CUDA和OpenCL支持問題

PaddleLite CUDA和OpenCL支持的op不是很完善,PaddleLite不像TensorflowLite完善沈跨,目前沒找到什么方式可以在不支持的op情況下自動(dòng)切換到CPU方式,在加載模型這一步就會(huì)出錯(cuò)狞玛,提示有不支持的op,并且在模型轉(zhuǎn)化為nb模型這一步如果出現(xiàn)不支持的op就會(huì)報(bào)錯(cuò)心肪,必須添加對應(yīng)架構(gòu)下的op實(shí)現(xiàn),并重新編譯PaddleLite和opt導(dǎo)出工具

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末慧瘤,一起剝皮案震驚了整個(gè)濱河市锅减,隨后出現(xiàn)的幾起案子蹬音,更是在濱河造成了極大的恐慌,老刑警劉巖著淆,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件永部,死亡現(xiàn)場離奇詭異,居然都是意外死亡懦砂,警方通過查閱死者的電腦和手機(jī)组橄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進(jìn)店門玉工,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人屠升,你說我怎么就攤上這事狭郑。” “怎么了脏答?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長糙麦。 經(jīng)常有香客問我丛肮,道長,這世上最難降的妖魔是什么焚廊? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任咆瘟,我火速辦了婚禮诽里,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘谤狡。我一直安慰自己,他們只是感情好焰宣,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布匕积。 她就那樣靜靜地躺著榜跌,像睡著了一般。 火紅的嫁衣襯著肌膚如雪悄蕾。 梳的紋絲不亂的頭發(fā)上瓤逼,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天库物,我揣著相機(jī)與錄音,去河邊找鬼诱告。 笑死民晒,一個(gè)胖子當(dāng)著我的面吹牛锄禽,可吹牛的內(nèi)容都是我干的靴姿。 我是一名探鬼主播,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼宵晚,長吁一口氣:“原來是場噩夢啊……” “哼淤刃!你這毒婦竟也來了吱型?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤铝侵,失蹤者是張志新(化名)和其女友劉穎据沈,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體锌介,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡孔祸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年崔慧,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片惶室。...
    茶點(diǎn)故事閱讀 40,102評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡皇钞,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出馆里,到底是詐尸還是另有隱情,我是刑警寧澤鸠踪,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布营密,位于F島的核電站,受9級(jí)特大地震影響评汰,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜兰绣,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一缀辩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧臀玄,春花似錦畅蹂、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至示损,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間始鱼,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工医清, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留状勤,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓持搜,卻偏偏與公主長得像葫盼,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子贫导,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 一孩灯、簡介 飛槳(PaddlePaddle)以百度深度學(xué)習(xí)技術(shù)研究和業(yè)務(wù)應(yīng)用為基礎(chǔ)逾滥,集深度學(xué)習(xí)核心訓(xùn)練和推理框架、基...
    Mr_Michael閱讀 1,670評論 0 0
  • 本文檔基于openvino_2022.2讥巡。 一.簡介 OpenVINO? 工具包是一個(gè)綜合工具包舔哪,用于快速開發(fā)解決...
    Mr_Michael閱讀 11,253評論 0 2
  • 一、簡介 1.華為昇騰AI全棧簡介 Atlas系列產(chǎn)品[https://support.huawei.com/en...
    Mr_Michael閱讀 3,772評論 0 0
  • 1. 項(xiàng)目介紹 1.1 PP-YOLOE模型 ?目標(biāo)檢測作為計(jì)算機(jī)視覺領(lǐng)域的頂梁柱抬驴,不僅可以獨(dú)立完成車輛怎爵、商品、缺...
    椒顏皮皮蝦閱讀 1,348評論 0 0
  • 對于在移動(dòng)端和IoT設(shè)備上部署深度學(xué)習(xí)模型鳖链,通用墩莫、高性能的移動(dòng)端推理框架起到十分關(guān)鍵的作用。在使用mnn過程中狂秦,自...
    zmz_transf閱讀 3,654評論 0 2