Rk3588开发板,deeplabv3+_mobilenetv2部署代码,脚本代码,c++代码

Rk3588开发板,deeplabv3+_mobilenetv2部署代码,脚本代码,c++代码

前提说明:

代码是经过RKNPU2-MASTER的example中的rknn_yolov5_demo修改完成的。可以不管其他文件,将main.cc、build-android_RK3588.sh、CMakeList.txt直接进行修改就行。其他操作需要自己在开发文档中进行。

build-android_RK3588.sh文件

下面展示build-android_RK3588.sh脚本文件。

#!/bin/bash

set -e

if [ -z ${ANDROID_NDK_PATH} ]
then
  ANDROID_NDK_PATH=~/下载/android-ndk-r17c
fi

BUILD_TYPE=Release

TARGET_SOC="rk3588"

ROOT_PWD=$( cd "$( dirname $0 )" && cd -P "$( dirname "$SOURCE" )" && pwd )

BUILD_DIR=${ROOT_PWD}/build/build_android_v8a

if [[ ! -d "${BUILD_DIR}" ]]; then
  mkdir -p ${BUILD_DIR}
fi

cd ${BUILD_DIR}
cmake ../.. \
        -DANDROID_TOOLCHAIN=clang \
        -DTARGET_SOC=${TARGET_SOC} \
       	-DCMAKE_SYSTEM_NAME=Android \
        -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK_PATH/build/cmake/android.toolchain.cmake \
        -DANDROID_ABI="arm64-v8a" \
        -DANDROID_STL=c++_static \
        -DANDROID_PLATFORM=android-24 \
        -DCMAKE_BUILD_TYPE=${BUILD_TYPE}
make -j4
make install
cd ..

CMakeList.txt文件

下面展示CMakeList.txt文件代码。

cmake_minimum_required(VERSION 3.4.1)

project(rknn_deeplab_demo)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# skip 3rd-party lib dependencies
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--allow-shlib-undefined")

# install target and libraries
set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/install/rknn_deeplab_demo_${CMAKE_SYSTEM_NAME})

set(CMAKE_SKIP_INSTALL_RPATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")

if (CMAKE_C_COMPILER MATCHES "aarch64")
  set(LIB_ARCH aarch64)
else()
  set(LIB_ARCH armhf)
endif()

include_directories(${CMAKE_SOURCE_DIR})

# rknn api
if(TARGET_SOC STREQUAL "rk356x")
  set(RKNN_API_PATH ${CMAKE_SOURCE_DIR}/../../runtime/RK356X/${CMAKE_SYSTEM_NAME}/librknn_api)
elseif(TARGET_SOC STREQUAL "rk3588")
  set(RKNN_API_PATH ${CMAKE_SOURCE_DIR}/../../runtime/RK3588/${CMAKE_SYSTEM_NAME}/librknn_api)
else()
  message(FATAL_ERROR "TARGET_SOC is not set, ref value: rk356x or rk3588 or rv110x")
endif()

if (CMAKE_SYSTEM_NAME STREQUAL "Android")
  set(RKNN_RT_LIB ${RKNN_API_PATH}/${CMAKE_ANDROID_ARCH_ABI}/librknnrt.so)
else()
  set(RKNN_RT_LIB ${RKNN_API_PATH}/${LIB_ARCH}/librknnrt.so)
endif()
include_directories(${RKNN_API_PATH}/include)
include_directories(${CMAKE_SOURCE_DIR}/../3rdparty)

# opencv
if (CMAKE_SYSTEM_NAME STREQUAL "Android")
    set(OpenCV_DIR ${CMAKE_SOURCE_DIR}/../3rdparty/opencv/OpenCV-android-sdk/sdk/native/jni/abi-${CMAKE_ANDROID_ARCH_ABI})
else()
  if(LIB_ARCH STREQUAL "armhf")
    set(OpenCV_DIR ${CMAKE_SOURCE_DIR}/../3rdparty/opencv/opencv-linux-armhf/share/OpenCV)
  else()
    set(OpenCV_DIR ${CMAKE_SOURCE_DIR}/../3rdparty/opencv/opencv-linux-aarch64/share/OpenCV)
  endif()
endif()
find_package(OpenCV REQUIRED)

#rga
if(TARGET_SOC STREQUAL "rk356x")
  set(RGA_PATH ${CMAKE_SOURCE_DIR}/../3rdparty/rga/RK356X)
elseif(TARGET_SOC STREQUAL "rk3588")
  set(RGA_PATH ${CMAKE_SOURCE_DIR}/../3rdparty/rga/RK3588)
else()
  message(FATAL_ERROR "TARGET_SOC is not set, ref value: rk356x or rk3588")
endif()
if (CMAKE_SYSTEM_NAME STREQUAL "Android")
  set(RGA_LIB ${RGA_PATH}/lib/Android/${CMAKE_ANDROID_ARCH_ABI}/librga.so)
else()
  set(RGA_LIB ${RGA_PATH}/lib/Linux//${LIB_ARCH}/librga.so)
endif()
include_directories( ${RGA_PATH}/include)

# mpp
set(MPP_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../3rdparty/mpp)
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
  set(MPP_LIBS ${MPP_PATH}/${CMAKE_SYSTEM_NAME}/${LIB_ARCH}/librockchip_mpp.so)
elseif (CMAKE_SYSTEM_NAME STREQUAL "Android")
  set(MPP_LIBS ${MPP_PATH}/${CMAKE_SYSTEM_NAME}/${CMAKE_ANDROID_ARCH_ABI}/libmpp.so)
endif()
include_directories(${MPP_PATH}/include)

# zlmediakit
set(ZLMEDIAKIT_PATH ${CMAKE_SOURCE_DIR}/../3rdparty/zlmediakit)
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
include_directories(${ZLMEDIAKIT_PATH}/include)
set(ZLMEDIAKIT_LIBS ${ZLMEDIAKIT_PATH}/${LIB_ARCH}/libmk_api.so)
endif()

if (ZLMEDIAKIT_LIBS)
    add_definitions(-DBUILD_VIDEO_RTSP)
endif()

set(CMAKE_INSTALL_RPATH "lib")

# rknn_deeplab_demo
include_directories( ${CMAKE_SOURCE_DIR}/include)

add_executable(rknn_deeplab_demo
        src/main.cc
)

target_link_libraries(rknn_deeplab_demo
  ${RKNN_RT_LIB}
  ${RGA_LIB}
  ${OpenCV_LIBS}
)

if (MPP_LIBS)
add_executable(rknn_deeplab_video_demo
        src/main_video.cc
        src/postprocess.cc
        utils/mpp_decoder.cpp
        utils/mpp_encoder.cpp
        utils/drawing.cpp
)
target_link_libraries(rknn_deeplab_video_demo
  ${RKNN_RT_LIB}
  ${RGA_LIB}
  ${OpenCV_LIBS}
  ${MPP_LIBS}
  ${ZLMEDIAKIT_LIBS}
)
endif()

# install target and libraries
set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/install/rknn_deeplab_demo_${CMAKE_SYSTEM_NAME})
install(TARGETS rknn_deeplab_demo DESTINATION ./)

install(PROGRAMS ${RKNN_RT_LIB} DESTINATION lib)
install(PROGRAMS ${RGA_LIB} DESTINATION lib)
install(DIRECTORY model DESTINATION ./)

if (MPP_LIBS)
install(TARGETS rknn_deeplab_video_demo DESTINATION ./)
install(PROGRAMS ${MPP_LIBS} DESTINATION lib)
endif()

if (ZLMEDIAKIT_LIBS)
install(PROGRAMS ${ZLMEDIAKIT_LIBS} DESTINATION lib)
endif()

main.cc文件

下面展示build-android_RK3588.sh脚本文件。

// Copyright (c) 2021 by Rockchip Electronics Co., Ltd. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/*-------------------------------------------
                Includes
-------------------------------------------*/
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <iostream>
#include <cmath>
#include <vector>
#include <fstream>
#include <cstring>
#include <dirent.h>
#define _BASETSD_H

#include "RgaUtils.h"
#include "im2d.h"
#include "opencv2/core/core.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/imgproc.hpp"
#include "rga.h"
#include "rknn_api.h"

#define PERF_WITH_POST 1
/*-------------------------------------------
                  Functions
-------------------------------------------*/

int colors[22][3] = {{0, 0, 0}, {128, 0, 0}, {0, 128, 0}, {128, 128, 0}, {0, 0, 128}, {128, 0, 128}, {0, 128, 128},
                   {128, 128, 128}, {64, 0, 0}, {192, 0, 0}, {64, 128, 0}, {192, 128, 0}, {64, 0, 128}, {192, 0, 128},
                   {64, 128, 128}, {192, 128, 128}, {0, 64, 0}, {128, 64, 0}, {0, 192, 0}, {128, 192, 0}, {0, 64, 128}, {128, 64, 12}};

static void dump_tensor_attr(rknn_tensor_attr* attr)
{
  std::string shape_str = attr->n_dims < 1 ? "" : std::to_string(attr->dims[0]);
  for (int i = 1; i < attr->n_dims; ++i) {
    shape_str += ", " + std::to_string(attr->dims[i]);
  }

  printf("  index=%d, name=%s, n_dims=%d, dims=[%s], n_elems=%d, size=%d, w_stride = %d, size_with_stride=%d, fmt=%s, "
         "type=%s, qnt_type=%s, "
         "zp=%d, scale=%f\n",
         attr->index, attr->name, attr->n_dims, shape_str.c_str(), attr->n_elems, attr->size, attr->w_stride,
         attr->size_with_stride, get_format_string(attr->fmt), get_type_string(attr->type),
         get_qnt_type_string(attr->qnt_type), attr->zp, attr->scale);
}

double __get_us(struct timeval t) { return (t.tv_sec * 1000000 + t.tv_usec); }

static unsigned char* load_data(FILE* fp, size_t ofst, size_t sz)
{
  unsigned char* data;
  int            ret;

  data = NULL;

  if (NULL == fp) {
    return NULL;
  }

  ret = fseek(fp, ofst, SEEK_SET);
  if (ret != 0) {
    printf("blob seek failure.\n");
    return NULL;
  }

  data = (unsigned char*)malloc(sz);
  if (data == NULL) {
    printf("buffer malloc failure.\n");
    return NULL;
  }
  ret = fread(data, 1, sz, fp);
  return data;
}

static unsigned char* load_model(const char* filename, int* model_size)
{
  FILE*          fp;
  unsigned char* data;

  fp = fopen(filename, "rb");
  if (NULL == fp) {
    printf("Open file %s failed.\n", filename);
    return NULL;
  }

  fseek(fp, 0, SEEK_END);
  int size = ftell(fp);

  data = load_data(fp, 0, size);

  fclose(fp);

  *model_size = size;
  return data;
}

static int saveFloat(const char* file_name, float* output, int element_size)
{
  FILE* fp;
  fp = fopen(file_name, "w");
  for (int i = 0; i < element_size; i++) {
    fprintf(fp, "%.6f\n", output[i]);
  }
  fclose(fp);
  return 0;
}
int nw = 0;
int nh = 0;

cv::Mat resizeImage(cv::Mat image, cv::Size size) {
    int iw = image.cols;
    int ih = image.rows;
    int w = size.width;
    int h = size.height;

    double scale = std::min(static_cast<double>(w) / iw, static_cast<double>(h) / ih);
    nw = static_cast<int>(iw * scale);
    nh = static_cast<int>(ih * scale);

    cv::resize(image, image, cv::Size(nw, nh), cv::INTER_CUBIC);

    cv::Mat newImage(size, CV_8UC3, cv::Scalar(128, 128, 128));
    image.copyTo(newImage(cv::Rect((w - nw) / 2, (h - nh) / 2, nw, nh)));

    return newImage;
}

// std::vector<int> argmax_indices; // 存储 argmax 结果
void softmax(float* data, int channels, int height, int width) {
    for (int h = 0; h < height; ++h) {
        for (int w = 0; w < width; ++w) {
            int max_index = 0;
            // 计算最大值以增加稳定性
            float max_val = data[h * w];
            for (int c = 1; c < channels; ++c) {
              // if(max_val<data[c*width*height+h*width+w]){
              //   max_val = data[c*width*height+h*width+w];
              //   max_index = c;
              // }
                max_val = std::max(max_val, data[c*width*height+h*width+w]);
            }
            // argmax_indices.push_back(max_index);

            // 计算指数并计算 softmax 时的总和
            float sum = 0.0f;
            for (int c = 0; c < channels; ++c) {
                data[c*width*height+h*width+w] -= max_val;
                data[c*width*height+h*width+w] = std::exp(data[c*width*height+h*width+w]);
                sum += data[c*width*height+h*width+w];
            }
            
            // 使用总和进行归一化
            for (int c = 0; c < channels; ++c) {
                data[c*width*height+h*width+w] /= sum;
                // printf("%d,          %f\n",c*width*height+h*width+w,data[c*width*height+h*width+w]);
            }
        }
    }
}

void clearFileContent(const std::string& filePath) {
    std::ofstream file(filePath, std::ofstream::out | std::ofstream::trunc);
    if (!file.is_open()) {
        std::cerr << "Unable to clear file content." << std::endl;
        return;
    }
    file.close();
}

void listFilesInDirectory(const std::string& directoryPath, const std::string& outputFile) {
    clearFileContent(outputFile); 
    
    std::ofstream output(outputFile);

    if (!output.is_open()) {
        std::cerr << "不能打开输出文件." << std::endl;
        return;
    }

    DIR* dir = opendir(directoryPath.c_str());
    if (!dir) {
        std::cerr << "不能打开文件夹." << std::endl;
        output.close();
        return;
    }

    dirent* entry;
    while ((entry = readdir(dir)) != nullptr) {
        if (entry->d_type == DT_REG) {
            output << entry->d_name << std::endl;
        }
    }

    closedir(dir);
    output.close();
}

/*-------------------------------------------
                  Main Functions
-------------------------------------------*/
int main()
{
  int            status     = 0;
  char*          model_name = NULL;
  rknn_context   ctx;
  size_t         actual_size        = 0;
  int            img_width          = 0;
  int            img_height         = 0;
  int            img_channel        = 0;
  struct timeval start_time, stop_time;
  int            ret;

  // init rga context
  // rga_buffer_t src;
  // rga_buffer_t dst;
  // im_rect      src_rect;
  // im_rect      dst_rect;
  // memset(&src_rect, 0, sizeof(src_rect));
  // memset(&dst_rect, 0, sizeof(dst_rect));
  // memset(&src, 0, sizeof(src));
  // memset(&dst, 0, sizeof(dst));


  //脚本工具,将文件夹中的文件名,全部都保存在dataset.txt文件。
  std::string directoryPath = "./dataset";
  std::string outputFile = "./dataset.txt";
  listFilesInDirectory(directoryPath,outputFile);
  std::cout<<"文件名已保存"<<outputFile <<std::endl;

  model_name = "./model/RK3588/deeplab_mobilenetv2.rknn";

  /* Create the neural network */
  printf("Loading mode...\n");
  int            model_data_size = 0;
  unsigned char* model_data      = load_model(model_name, &model_data_size);
  ret                            = rknn_init(&ctx, model_data, model_data_size, RKNN_FLAG_COLLECT_PERF_MASK, NULL);
  if (ret < 0) {
    printf("rknn_init error ret=%d\n", ret);
    return -1;
  }

  rknn_sdk_version version;
  ret = rknn_query(ctx, RKNN_QUERY_SDK_VERSION, &version, sizeof(rknn_sdk_version));
  if (ret < 0) {
    printf("rknn_init error ret=%d\n", ret);
    return -1;
  }
  printf("sdk version: %s driver version: %s\n", version.api_version, version.drv_version);

  rknn_input_output_num io_num;
  ret = rknn_query(ctx, RKNN_QUERY_IN_OUT_NUM, &io_num, sizeof(io_num));
  if (ret < 0) {
    printf("rknn_init error ret=%d\n", ret);
    return -1;
  }
  printf("model input num: %d, output num: %d\n", io_num.n_input, io_num.n_output);

  rknn_tensor_attr input_attrs[io_num.n_input];
  memset(input_attrs, 0, sizeof(input_attrs));
  for (int i = 0; i < io_num.n_input; i++) {
    input_attrs[i].index = i;
    ret                  = rknn_query(ctx, RKNN_QUERY_INPUT_ATTR, &(input_attrs[i]), sizeof(rknn_tensor_attr));
    if (ret < 0) {
      printf("rknn_init error ret=%d\n", ret);
      return -1;
    }
    dump_tensor_attr(&(input_attrs[i]));
  }

  rknn_tensor_attr output_attrs[io_num.n_output];
  memset(output_attrs, 0, sizeof(output_attrs));
  for (int i = 0; i < io_num.n_output; i++) {
    output_attrs[i].index = i;
    ret                   = rknn_query(ctx, RKNN_QUERY_OUTPUT_ATTR, &(output_attrs[i]), sizeof(rknn_tensor_attr));
    dump_tensor_attr(&(output_attrs[i]));
  }

  int channel = 3;
  int width   = 0;
  int height  = 0;
  if (input_attrs[0].fmt == RKNN_TENSOR_NCHW) {
    printf("model is NCHW input fmt\n");
    channel = input_attrs[0].dims[1];
    height  = input_attrs[0].dims[2];
    width   = input_attrs[0].dims[3];
  } else {
    printf("model is NHWC input fmt\n");
    height  = input_attrs[0].dims[1];
    width   = input_attrs[0].dims[2];
    channel = input_attrs[0].dims[3];
  }

  printf("model input height=%d, width=%d, channel=%d\n", height, width, channel);

  rknn_input inputs[1];
  memset(inputs, 0, sizeof(inputs));
  inputs[0].index        = 0;
  inputs[0].type         = RKNN_TENSOR_UINT8;
  inputs[0].size         = width * height * channel;
  inputs[0].fmt          = RKNN_TENSOR_NHWC;
  inputs[0].pass_through = 0;

  // You may not need resize when src resulotion equals to dst resulotion

  // 开始循环
  std::ifstream file("dataset.txt");
  std::string line;
  while (std::getline(file,line)){
    std::string input_path = "./dataset/" +line;
    std::string save_path = "./output/" +line;

    char* image_name = strdup(input_path.c_str());
    printf("Read %s ...\n", image_name);
    cv::Mat orig_img = cv::imread(image_name, 1);
    if (!orig_img.data) {
      printf("cv::imread %s fail!\n", image_name);
      return -1;
    }
    cv::Mat img;
    cv::cvtColor(orig_img, img, cv::COLOR_BGR2RGB);
    img_width  = img.cols;
    img_height = img.rows;
    printf("img width = %d, img height = %d\n", img_width, img_height);



    gettimeofday(&start_time, NULL);
    // 新的ressize方式
    img= resizeImage(img,cv::Size(width,height));
    // cv::imwrite("xiao.jpg",img);
    inputs[0].buf = img.data;

    gettimeofday(&stop_time, NULL);
    printf("resize时间once run use %f ms\n", (__get_us(stop_time) - __get_us(start_time)) / 1000);

    gettimeofday(&start_time, NULL);

    rknn_inputs_set(ctx, io_num.n_input, inputs);

    rknn_output outputs[io_num.n_output];
    memset(outputs, 0, sizeof(outputs));
    for (int i = 0; i < io_num.n_output; i++) {
      outputs[i].want_float = 1;
    }

    gettimeofday(&stop_time, NULL);
    printf("input和output时间once run use %f ms\n", (__get_us(stop_time) - __get_us(start_time)) / 1000);
    gettimeofday(&start_time, NULL); 


    ret = rknn_run(ctx, NULL);

    rknn_perf_detail perf_detail;
    ret = rknn_query(ctx,RKNN_QUERY_PERF_DETAIL,&perf_detail,sizeof(perf_detail));
    ret = rknn_outputs_get(ctx, io_num.n_output, outputs, NULL);


    // 根据获取的属性,判断数据类型
    // if (output_attrs[0].type == RKNN_TENSOR_FLOAT32) {
    //     printf("第一个输出数据类型为:RKNN_TENSOR_FLOAT32\n");
    // } else if (output_attrs[0].type == RKNN_TENSOR_UINT8) {
    //     printf("第一个输出数据类型为:RKNN_TENSOR_UINT8\n");
    // } else if (output_attrs[0].type == RKNN_TENSOR_INT8) {
    //     printf("第一个输出数据类型为:RKNN_TENSOR_INT8\n");
    // } else {
    //     printf("第一个输出数据类型未知\n");
    // }


    // printf("张量的数量::%d\n",io_num.n_output);
    // for (int i = 0; i < io_num.n_output; ++i) {
    //   printf("Output %d dimensions:", i);
    //   for (int j = 0; j < output_attrs[i].n_dims; ++j) {
    //       printf(" %d", output_attrs[i].dims[j]);
    //   }
    //   printf("\n");
    //   printf("\n");
    //   printf("\n");
    //   printf("\n");
    //   printf("\n");
    //   printf("\n");
    // }

    gettimeofday(&stop_time, NULL);
    printf("推理数据once run use %f ms\n", (__get_us(stop_time) - __get_us(start_time)) / 1000);
    
    // 打印每一层的运行时间。
    printf("每一层运行时间::\n\n %s \n\n",perf_detail.perf_data);


    gettimeofday(&start_time, NULL);

    // 提取有关输出张量的相关信息
    int output_index = 0; // 要复制的输出张量的索引
    int output_channel = output_attrs[output_index].dims[1];
    int output_height = output_attrs[output_index].dims[2];
    int output_width = output_attrs[output_index].dims[3];
    printf("输出通道:%d,输出高度:%d,输出宽度:%d\n", output_channel, output_height, output_width);
    // for (int i=0; i <344064;i++){
    //     printf("aaaaaaa  %d  The fifth element of pr is: %f\n",i, pr[i]);

    // }

    int output_size = outputs[output_index].size;
    printf("output_size的大小:::::%d\n",output_size);

    
    // 获取模型输出数据的指针
    // unsigned char* output_data = reinterpret_cast<unsigned char*>(outputs[output_index].buf);
    float* output_data = reinterpret_cast<float*>(outputs[0].buf);
    // 创建一个新的整数数组来存储解释后的数据
    std::vector<float> interpreted_data(output_size);

    for (int i = 0; i < output_size/4; ++i) {
        
        interpreted_data[i] = output_data[i];
        // printf("%d,          %f\n",i,interpreted_data[i]);
    }

    int mini_h = nh/4;
    int mini_w = nw/4;

    float* pr = interpreted_data.data();
    // printf("interpreted_data的大小:::::%d\n",interpreted_data.size());

    int slice_start_h = (output_height - mini_h) / 2;
    int slice_end_h = (output_height - mini_h) / 2 + mini_h;
    int slice_start_w = (output_width - mini_w) / 2;
    int slice_end_w = (output_width - mini_w) / 2 + mini_w;

    // 计算切片后的数据大小
    int sliced_height = slice_end_h - slice_start_h;
    int sliced_width = slice_end_w - slice_start_w;
    int sliced_channel = output_channel;
    int sliced_size = sliced_height * sliced_width*sliced_channel;


    // 创建一个新的数组来存储切片后的数据
    std::vector<float> sliced_data(sliced_size);
    // 复制数据到新数组
    for (int k = 0;k<sliced_channel;k++){
      for (int i = slice_start_h; i < slice_end_h; i++) {
        for (int j = slice_start_w; j < slice_end_w; j++) {
            int src_index =k*output_height*output_width+ i * output_width + j;
            int dst_index = k*sliced_height*sliced_width + (i - slice_start_h) * sliced_width + (j - slice_start_w);
            sliced_data[dst_index] = pr[src_index];
        }
      }
    }
    pr = sliced_data.data();
    
    // softmax操作
    softmax(pr, sliced_channel, sliced_height,sliced_width);


    cv::Mat segmented_img = cv::Mat(mini_h, mini_w, CV_8UC3);
    std::vector<int> argmax_indices; // 存储 argmax 结果
    for (int h = 0; h < sliced_height; ++h) {
        for (int w = 0; w < sliced_width; ++w) {
            int max_index = 0;
            float max_value = pr[h * sliced_width + w];

            for (int c = 1; c < output_channel; ++c) {
                float current_value = pr[c*sliced_height*sliced_width+ h * sliced_width + w];
                if (current_value > max_value) {
                    max_value = current_value;
                    max_index = c;
                }
            }

            argmax_indices.push_back(max_index);
            // printf("%d ",max_index);

            segmented_img.at<cv::Vec3b>(h, w) = cv::Vec3b(colors[max_index][2], colors[max_index][1], colors[max_index][0]);
        }
        // printf("\n");
    }
    printf("argmax_indices大小::%d\n",argmax_indices.size());
    
    

    
    // cv::Mat segmented_img = cv::Mat(mini_h, mini_w, CV_8UC3);
    // // Map argmax_indices to colors and fill the segmented image(可优化可以直接生成mat数据)
    // for (int h = 0; h < mini_h; ++h) {
    //     for (int w = 0; w < mini_w; ++w) {
    //         int index = argmax_indices[h * mini_w + w];
    //         segmented_img.at<cv::Vec3b>(h, w) = cv::Vec3b(colors[index][2], colors[index][1], colors[index][0]);
    //     }
    // }
    
    

    
    gettimeofday(&stop_time, NULL);
    printf("后处理时间::once run use %f ms\n", (__get_us(stop_time) - __get_us(start_time)) / 1000);

    bool saved = cv::imwrite(save_path, segmented_img);
    if(saved){
      std::cout<<"图片已存为:"<<save_path<<"\n\n\n\n"<<std::endl;
  }


}
  // release
  ret = rknn_destroy(ctx);

  if (model_data) {
    free(model_data);
  }
  return 0;
}

.rknn模型文件放在model中的RK3588中。

提示:

需要文档,或者其他文件的,可以评论区找我。希望对大家有用。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值