Toybrick

rknn c++ api与python api运算结果不一致,但如果输入参数为0一致

yinjun

新手上路

积分
25
发表于 2024-5-15 12:48:14    查看: 2933|回复: 1 | [复制链接]    打印 | 显示全部楼层
rt,我在安卓平板上部署rknn算法,通过python运行的推理结果和通过android部署的c++代码运行结果不一致,但如果输入参数为0则一致,求解
截图:
全部参数为0:


python 代码
  1. import os
  2. import urllib
  3. import traceback
  4. import time
  5. import sys
  6. import numpy as np
  7. import cv2
  8. from rknn.api import RKNN
  9. from blazefacenumpy import BlazeFace
  10. ONNX_MODEL = 'best.onnx' # onnx 模型的路径
  11. ONNX_MODEL = 'rppg_new.onnx' # onnx 模型的路径
  12. ONNX_MODEL = 'blazeface128.onnx' # onnx 模型的路径
  13. # ONNX_MODEL = 'v3.onnx' # onnx 模型的路径
  14. # ONNX_MODEL = 'alexnet.onnx' # onnx 模型的路径
  15. TFLITE_MODEL = 'face_detection_front.tflite'
  16. # TFLITE_MODEL = 'alexnet_float32.tflite'


  17. RKNN_MODEL = './yolov8-ghost-pose.rknn'  # 转换后的 RKNN 模型保存路径
  18. RKNN_MODEL = './bz128_3568.rknn'  # 转换后的 RKNN 模型保存路径
  19. # RKNN_MODEL = './facenet——3568.rknn'  # 转换后的 RKNN 模型保存路径
  20. # RKNN_MODEL = './pfldv3.rknn'  # 转换后的 RKNN 模型保存路径
  21. DATASET = './test.txt'   # 数据集文件路径

  22. QUANTIZE_ON = False   # 是否进行量化

  23. if __name__ == '__main__':

  24.         # 创建 RKNN 对象
  25.         rknn = RKNN(verbose=False)

  26.     # 检查 ONNX 模型文件是否存在
  27.         if not os.path.exists(ONNX_MODEL):
  28.                 print('model not exist')
  29.                 exit(-1)

  30.         # 配置模型预处理参数
  31.         print('--> Config model')
  32.         rknn.config(#reorder_channel='0 1 2', # 表示 RGB 通道
  33.                                
  34.                             mean_values=[[128, 128, 128]], # 每个通道的像素均值,预处理时对应通道减去该值
  35.                             std_values=[[128, 128, 128]], # 每个通道的像素标准差,每个通道除以该值
  36.                             optimization_level=3, # 优化级别
  37.                                 quantized_method='layer',
  38.                                 float_dtype="float16",
  39.                             target_platform = 'RK3568', #指定目标平台为rv1126
  40.                                 # quantize_input_node=QUANTIZE_ON
  41.                                 )  # 对时输入节点进行量化
  42.         print('done')

  43.         # 加载 ONNX 模型
  44.         # print('--> Loading model')
  45.         model = rknn.load_rknn(RKNN_MODEL)
  46.         ret = rknn.init_runtime(target="rk3568")

  47.         frame = cv2.imread('./test.jpg')
  48.         frame =cv2.resize(frame,(128,128))


  49.         npp = np.full_like(frame,2)

  50.         # color_img = np.zeros([1,3,128,128]).astype(np.float16)
  51.         pred = rknn.inference(inputs=[npp], data_format='nhwc',inputs_pass_through=[False])
  52.         # ret = rknn.load_onnx(model=ONNX_MODEL)
  53.         # rknn.inference(inputs=[])
  54.         exit(1)
复制代码
c++ 代码
  1. #include <android/log.h>
  2. #include <android/bitmap.h>

  3. #include "../rknn_api.h"
  4. #include "im2d_type.h"
  5. #include <sys/time.h>
  6. #include <string>
  7. #include <vector>
  8. #include <jni.h>


  9. #include "../rga/rga.h"
  10. #include "../rga/im2d.h"
  11. #include "../rga/im2d_version.h"

  12. #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, "wuzhengsdkC++", ##__VA_ARGS__);
  13. #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, "wuzhengsdkC++", ##__VA_ARGS__);


  14. uint32_t n_input = 1;
  15. uint32_t n_output = 2;

  16. int m_in_width = 0;   // the width of the RKNN model input
  17. int m_in_height = 0;  // the height of the RKNN model input
  18. int m_in_channel = 0; // the channel of the RKNN model input

  19. rknn_tensor_attr input_attrs[1];
  20. rknn_tensor_attr output_attrs[2];

  21. rknn_tensor_mem *output_mems[2];

  22. std::vector<float> out_scales;
  23. std::vector<int32_t> out_zps;

  24. bool created = false;
  25. rknn_context ctx = 0;

  26. //rga_buffer_t g_rga_dst;
  27. int g_inf_count = 0;

  28. char *jstringToChar(JNIEnv *env, jstring jstr) {
  29.     char *rtn = NULL;
  30.     jclass clsstring = env->FindClass("java/lang/String");
  31.     jstring strencode = env->NewStringUTF("GB2312");
  32.     jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B");
  33.     jbyteArray barr = (jbyteArray) env->CallObjectMethod(jstr, mid, strencode);
  34.     jsize alen = env->GetArrayLength(barr);
  35.     jbyte *ba = env->GetByteArrayElements(barr, JNI_FALSE);
  36.     if (alen > 0) {
  37.         rtn = (char *) malloc(alen + 1);
  38.         memcpy(rtn, ba, alen);
  39.         rtn[alen] = 0;
  40.     }
  41.     env->ReleaseByteArrayElements(barr, ba, 0);
  42.     return rtn;
  43. }


  44. JNIEXPORT void JNI_OnUnload(JavaVM *vm, void *reserved) {
  45.     LOGE("JNI_OnUnload");
  46. }

  47. extern "C"
  48. JNIEXPORT jint JNICALL Java_com_wuzhengai_examination_tfliterun_blazeface_rknn_BlazeFaceRknn_init(
  49.         JNIEnv *env,
  50.         jobject thiz,
  51.         jstring jmodel_path) {


  52.     char *model_path = jstringToChar(env, jmodel_path);


  53.     rknn_sdk_version version;
  54.     int ret1 = rknn_query(ctx, RKNN_QUERY_SDK_VERSION, &version,
  55.                           sizeof(rknn_sdk_version));
  56. //    printf("api version   : %s\n", version.api_version);
  57. //    printf("driver version: %s\n", version.drv_version);
  58.     LOGE("api version   : %s\n", (char *) version.api_version);
  59.     LOGE("driver version: %s\n", (char *) version.drv_version);
  60.     LOGE("%s,%s", version.api_version, version.drv_version)

  61.     // 1. Load model
  62.     FILE *fp = fopen(model_path, "rb");
  63.     if (fp == NULL) {
  64.         LOGE("fopen %s fail!\n", model_path);
  65.         return -1;
  66.     }
  67.     delete model_path;
  68.     model_path = NULL;
  69.     fseek(fp, 0, SEEK_END);
  70.     uint32_t model_len = ftell(fp);
  71.     void *model = malloc(model_len);
  72.     fseek(fp, 0, SEEK_SET);
  73.     if (model_len != fread(model, 1, model_len, fp)) {
  74.         LOGE("fread %s fail!\n", model_path);
  75.         free(model);
  76.         fclose(fp);
  77.         return -1;
  78.     }
  79.     fclose(fp);

  80.     // 2. Init RKNN model
  81.     int ret = rknn_init(&ctx, model, model_len, 0, nullptr);
  82.     free(model);
  83.     if (ret < 0) {
  84.         LOGE("rknn_init fail! ret=%d\n", ret);
  85.         return -1;
  86.     }

  87.     // 3. Query input/output attr.
  88.     rknn_input_output_num io_num;
  89.     rknn_query_cmd cmd = RKNN_QUERY_IN_OUT_NUM;
  90.     // 3.1 Query input/output num.
  91.     ret = rknn_query(ctx, cmd, &io_num, sizeof(io_num));
  92.     if (ret != RKNN_SUCC) {
  93.         LOGE("rknn_query io_num fail!ret=%d\n", ret);
  94.         return -1;
  95.     }
  96.     n_input = io_num.n_input;
  97.     n_output = io_num.n_output;


  98.     // 3.2 Query input attributes
  99.     memset(input_attrs, 0, n_input * sizeof(rknn_tensor_attr));
  100.     for (int i = 0; i < n_input; ++i) {
  101.         input_attrs[i].index = i;
  102.         cmd = RKNN_QUERY_INPUT_ATTR;
  103.         ret = rknn_query(ctx, cmd, &(input_attrs[i]), sizeof(rknn_tensor_attr));

  104.         if (ret < 0) {
  105.             LOGE("rknn_query input_attrs[%d] fail!ret=%d\n", i, ret);
  106.             return -1;
  107.         }
  108.     }

  109.     // 3.2.0 Update global model input shape.
  110.     if (RKNN_TENSOR_NHWC == input_attrs[0].fmt) {
  111.         m_in_height = input_attrs[0].dims[1];
  112.         m_in_width = input_attrs[0].dims[2];
  113.         m_in_channel = input_attrs[0].dims[3];
  114.     } else if (RKNN_TENSOR_NCHW == input_attrs[0].fmt) {
  115.         m_in_height = input_attrs[0].dims[2];
  116.         m_in_width = input_attrs[0].dims[3];
  117.         m_in_channel = input_attrs[0].dims[1];
  118.     } else {
  119.         LOGE("Unsupported model input layout: %d!\n", input_attrs[0].fmt);
  120.         return -1;
  121.     }



  122.     // 3.3 Query output attributes
  123.     memset(output_attrs, 0, n_output * sizeof(rknn_tensor_attr));
  124.     for (int i = 0; i < n_output; ++i) {
  125.         output_attrs[i].index = i;
  126.         cmd = RKNN_QUERY_OUTPUT_ATTR;
  127.         ret = rknn_query(ctx, cmd, &(output_attrs[i]), sizeof(rknn_tensor_attr));
  128.         if (ret < 0) {
  129.             LOGE("rknn_query output_attrs[%d] fail!ret=%d\n", i, ret);
  130.             return -1;
  131.         }
  132.         // set out_scales/out_zps for post_process
  133.         out_scales.push_back(output_attrs[i].scale);
  134.         out_zps.push_back(output_attrs[i].zp);
  135.     }

  136.     void *in_data = malloc(m_in_width * m_in_height * m_in_channel);
  137.     memset(in_data, 0, m_in_width * m_in_height * m_in_channel);

  138.     // 4.1.2 Update input attrs
  139.     input_attrs[0].index = 0;
  140.     input_attrs[0].type = RKNN_TENSOR_UINT8;
  141.     input_attrs[0].size = m_in_height * m_in_width * m_in_channel * sizeof(char);
  142.     input_attrs[0].fmt = RKNN_TENSOR_NCHW;
  143.     // TODO -- The efficiency of pass through will be higher, we need adjust the layout of input to
  144.     //         meet the use condition of pass through.
  145.     input_attrs[0].pass_through = 0;
  146.     // 4.1.3 Set input buffer
  147. //    rknn_set_io_mem(ctx, input_mems[0], &(input_attrs[0]));

  148.     created = true;

  149.     return 0;
  150. }



  151. extern "C"
  152. JNIEXPORT void JNICALL
  153. Java_com_wuzhengai_examination_tfliterun_blazeface_rknn_BlazeFaceRknn_release(
  154.         JNIEnv *env,
  155.         jobject thiz) {
  156.     LOGI("rknn_destroy!");
  157.     // release io_mem resource
  158. //    for (int i = 0; i < n_input; ++i) {
  159. //        rknn_destroy_mem(ctx, input_mems[i]);
  160. //    }
  161.     for (int i = 0; i < n_output; ++i) {
  162.         rknn_destroy_mem(ctx, output_mems[i]);
  163.     }
  164.     rknn_destroy(ctx);

  165. }



  166. extern "C"
  167. JNIEXPORT jboolean JNICALL
  168. Java_com_wuzhengai_examination_tfliterun_blazeface_rknn_BlazeFaceRknn_detect(
  169.         JNIEnv *env,
  170.         jobject thiz,
  171.         jintArray input,
  172.         jfloatArray output1,
  173.         jfloatArray output2) {

  174.     if (!created) {
  175.         LOGE("run_yolo: init yolo hasn't successful!");
  176.         return false;
  177.     }

  178.     jboolean inputCopy = JNI_FALSE;
  179.     jint *const inData = env->GetIntArrayElements(input, &inputCopy);

  180.     // 获取数组长度
  181.     jsize length = env->GetArrayLength(input);

  182. // 创建一个int8_t数组
  183.     uint8_t *inputData = new uint8_t[length];
  184.     // inputData
  185.     for (int i = 0; i < length; i++) {
  186.         inputData[i] = static_cast<uint8_t>(inData[i]);
  187.     }


  188.     LOGE("test,%d,%d,%d", inData[126],static_cast<uint8_t>(inData[126]),inputData[126])
  189.     jboolean outputCopy = JNI_FALSE;


  190.     jfloat *const y0 = env->GetFloatArrayElements(output1, &outputCopy);
  191.     jfloat *const y1 = env->GetFloatArrayElements(output2, &outputCopy);


  192.     rknn_input inputs[1];
  193.     memset(inputs, 0, sizeof(inputs));
  194.     inputs[0].index = 0;
  195.     inputs[0].type = RKNN_TENSOR_UINT8;
  196. //    float 类型需要乘以2?不清楚
  197.     inputs[0].size = m_in_height * m_in_width * m_in_channel ;
  198. //    inputs[0].size =75264;
  199.     inputs[0].fmt = RKNN_TENSOR_NHWC;
  200.     inputs[0].pass_through = 0;
  201.     inputs[0].buf = inData;


  202.     int ret = rknn_inputs_set(ctx, 1, inputs);


  203.     rknn_output outputs[2];
  204.     memset(outputs, 0, sizeof(outputs));
  205.     for (int i = 0; i < 2; ++i) {
  206.         outputs[i].want_float = 1;
  207.     }


  208.     if (ret < 0) {
  209.         LOGE("rknn_set fail! ret=%d\n", ret);
  210.         return false;
  211.     }
  212. //    LOGE("rknn set %d",ret)
  213.     ret = rknn_run(ctx, nullptr);
  214.     if (ret < 0) {
  215.         LOGE("rknn_run fail! ret=%d\n", ret);
  216.         return false;
  217.     }


  218.     rknn_outputs_get(ctx, 2, outputs, NULL);

  219.     memcpy(y0, outputs[0].buf, output_attrs[0].n_elems * sizeof(char));
  220.     memcpy(y1, outputs[1].buf, output_attrs[1].n_elems * sizeof(char));

  221. //
  222.     env->ReleaseIntArrayElements(input, inData, JNI_ABORT);
  223.     env->ReleaseFloatArrayElements(output1, y0, 0);
  224.     env->ReleaseFloatArrayElements(output2, y1, 0);

  225.     rknn_outputs_release(ctx, 2, outputs);
  226.     return JNI_TRUE;
  227. }

复制代码


回复

使用道具 举报

yinjun

新手上路

积分
25
 楼主| 发表于 2024-5-15 12:54:58 | 显示全部楼层
这是0输入,细看好像也不是完全一样。。





奇怪?怎么图片好像上不来?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

产品中心 购买渠道 开源社区 Wiki教程 资料下载 关于Toybrick


快速回复 返回顶部 返回列表