易百纳rv1126 a201开发板跑rknn yolov5

news/2025/3/25 21:56:48/

一开始我以为跑yolov5啊, 那必须上debian/ubuntu啊, 不然怎么装python, pytorch?buildroot没有apt, 于是花了大量时间想办法在a201的板子上跑debian, 等我debian跑上, python安排上, rknn-lite按照firefly的方法装好
https://dev.t-firefly.com/thread-104204-1-1.html
再去找rknn的示例程序的时候, 发现原来有c的版本.
https://github.com/airockchip/rknn_model_zoo/tree/main/models/vision/object_detection/yolov5-pytorch/RKNN_C_demo/RKNN_toolkit_1/rknn_yolov5_demo
默认易百纳的出厂固件就有rknn的lib

[root@RV1126_RV1109:/etc]# echo $LD_LIBRARY_PATH
:/oem/usrlibs:/oem/usr/lib:/oem/lib
[root@RV1126_RV1109:/etc]# cd /oem/usr/lib
[root@RV1126_RV1109:/oem/usr/lib]# ls
face_attribute.data           libeasymedia.so.1      librockchip_mpp.so.0
face_detection_v3.data        libeasymedia.so.1.0.1  librockchip_mpp.so.1
face_detection_v3_large.data  libgdbus.so            librockchip_vpu.so
face_landmark5.data           libispclient.so        librockchip_vpu.so.0
face_landmarks106.data        libmal.so              librockchip_vpu.so.1
face_landmarks68.data         librkaiq.so            librockface.so
face_recognition.data         librkdb.so             librockx.so
libCallFunIpc.so              librkisp_api.so        object_detection.data
libIPCProtocol.so             librknn_api.so         pose_body_v2.data
libeasymedia.so               librockchip_mpp.so     pose_finger.data

实现方法, 第一步, 用rkmedia产生一个jpeg图片,这个就简单了, 直接改rkmedia的example里面的示例代码,但是原本是用的CMakelists编译的, 效率太低, 直接改Makefile

hide := @
ECHO := echoGCC := /home/marc/rv_sdk/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gccSYSROOT =  /home/marc/rv_sdk/buildroot/output/rockchip_rv1126_rv1109/host/arm-buildroot-linux-gnueabihf/sysrootCFLAGS := -I../include/rkmedia \-I../include/rkaiq/common \-I../include/rkaiq/xcore \-I../include/rkaiq/uAPI \-I../include/rkaiq/algos \-I../include/rkaiq/iq_parser\#-I/home/marc/rv_sdk/buildroot/output/rockchip_rv1126_rv1109/build/camera_engine_rkaiq-1.0/include/uAPI/\#-I/home/marc/rv_sdk/buildroot/output/rockchip_rv1126_rv1109/build/camera_engine_rkaiq-1.0/include/xcore/\#-I/home/marc/rv_sdk/buildroot/output/rockchip_rv1126_rv1109/build/camera_engine_rkaiq-1.0/include/iq_parser/\LIB_FILES := -L$(SYSROOT)/usr/libLD_FLAGS := -lpthread -leasymedia -ldrm -lrockchip_mpp \-lavformat -lavcodec -lswresample -lavutil \-lasound -lv4l2 -lv4lconvert -lrga \-lRKAP_ANR -lRKAP_Common -lRKAP_3A \-lmd_share -lrkaiq -lod_shareCFLAGS += -DRKAIQSAMPLE_COMMON := common/sample_common_isp.call:$(GCC) jpeg_cap.c $(SAMPLE_COMMON) $(LIB_FILES) $(LD_FLAGS) $(CFLAGS) -o build/jpeg_capture --sysroot=$(SYSROOT)# $(GCC) my_vi.c $(SAMPLE_COMMON) $(LIB_FILES) $(LD_FLAGS) $(CFLAGS) -o build/my_vi --sysroot=$(SYSROOT)$(hide)$(ECHO) "Build Done ..."

就是改下GCC的目录跟加入sysroot目录, 不然会提示找不到库
通过make编译一下这个获取图片并保存的app:

#include <assert.h>
#include <fcntl.h>
#include <getopt.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>#include "common/sample_common.h"
#include "rkmedia_api.h"
#include "rkmedia_venc.h"#define RKAIQ 1static RK_CHAR *g_pOutPath = "/tmp/";
static bool getPicture = false;char jpeg_file_path_old[128];void video_packet_cb(MEDIA_BUFFER mb) {static RK_U32 jpeg_id = 0;static bool firstRun = true;//    printf("Get JPEG packet[%d]:ptr:%p, fd:%d, size:%zu, mode:%d, channel:%d, timestamp:%lld\n",//           jpeg_id, RK_MPI_MB_GetPtr(mb), RK_MPI_MB_GetFD(mb),//           RK_MPI_MB_GetSize(mb), RK_MPI_MB_GetModeID(mb),//           RK_MPI_MB_GetChannelID(mb), RK_MPI_MB_GetTimestamp(mb));char *jpeg_path = "/mnt/www/rknn_before.jpeg";// sprintf(jpeg_path, "/tmp/rknn.jpeg");if (!firstRun) {int rtn = remove(jpeg_path);if (rtn == 0) {// printf("File deleted successfully\n");} else {printf("Error: unable to delete the file\n");return;}}FILE *file = fopen(jpeg_path, "w");if (file) {fwrite(RK_MPI_MB_GetPtr(mb), 1, RK_MPI_MB_GetSize(mb), file);fclose(file);}RK_MPI_MB_ReleaseBuffer(mb);jpeg_id++;getPicture = true;firstRun = false;
}void video_packet_cb_old(MEDIA_BUFFER mb) {static RK_U32 jpeg_id = 0;static bool firstRun = true;printf("Get JPEG packet[%d]:ptr:%p, fd:%d, size:%zu, mode:%d, channel:%d, timestamp:%lld\n",jpeg_id, RK_MPI_MB_GetPtr(mb), RK_MPI_MB_GetFD(mb),RK_MPI_MB_GetSize(mb), RK_MPI_MB_GetModeID(mb),RK_MPI_MB_GetChannelID(mb), RK_MPI_MB_GetTimestamp(mb));char jpeg_path[128];sprintf(jpeg_path, "%s%lld.jpeg", g_pOutPath, RK_MPI_MB_GetTimestamp(mb));if (!firstRun) {int rtn = remove(jpeg_file_path_old);if (rtn == 0) {printf("File deleted successfully\n");} else {printf("Error: unable to delete the file\n");return;}}FILE *file = fopen(jpeg_path, "w");if (file) {fwrite(RK_MPI_MB_GetPtr(mb), 1, RK_MPI_MB_GetSize(mb), file);fclose(file);}RK_MPI_MB_ReleaseBuffer(mb);jpeg_id++;memcpy(jpeg_file_path_old, jpeg_path, 128);getPicture = true;firstRun = false;
}#define TEST_ARGB32_YELLOW 0xFFFFFF00
#define TEST_ARGB32_RED 0xFFFF0033
#define TEST_ARGB32_BLUE 0xFF003399
#define TEST_ARGB32_TRANS 0x00000000static void set_argb8888_buffer(RK_U32 *buf, RK_U32 size, RK_U32 color) {for (RK_U32 i = 0; buf && (i < size); i++)*(buf + i) = color;
}static RK_CHAR optstr[] = "?::a::w:h:W:H:o:I:M:r:";
static const struct option long_options[] = {{"aiq",      optional_argument, NULL, 'a'},{"width",    required_argument, NULL, 'w'},{"height",   required_argument, NULL, 'h'},{"Width",    required_argument, NULL, 'W'},{"Height",   required_argument, NULL, 'H'},{"output",   required_argument, NULL, 'o'},{"camid",    required_argument, NULL, 'I'},{"multictx", required_argument, NULL, 'M'},{"rotation", required_argument, NULL, 'r'},{"help",     optional_argument, NULL, '?'},{NULL,       0,                 NULL, 0},
};static void print_usage(const RK_CHAR *name) {printf("usage example:\n");printf("\t%s [-a [iqfiles_dir]]""[-I 0] ""[-M 0] ""[-H 1920] ""[-W 1080] ""[-h 720] ""[-w 480] ""[-o output_dir] ""\n",name);printf("\t-a | --aiq: enable aiq with dirpath provided, eg:-a ""/oem/etc/iqfiles/, ""set dirpath empty to using path by default, without this option aiq ""should run in other application\n");printf("\t-M | --multictx: switch of multictx in isp, set 0 to disable, set ""1 to enable. Default: 0\n");printf("\t-I | --camid: camera ctx id, Default 0\n");printf("\t-W | --Width: source width, Default:1920\n");printf("\t-H | --Height: source height, Default:1080\n");printf("\t-w | --width: destination width, Default:720\n");printf("\t-h | --height: destination height, Default:480\n");printf("\t-o | --output: output dirpath, Default:/tmp/\n");printf("\t-r | --rotation: rotation control, Default:0. Values:0/90/180/270\n");printf("\t tip: destination resolution should not over 4096*4096\n");
}RK_S32 ret;
RK_U32 u32SrcWidth = 1920;
RK_U32 u32SrcHeight = 1080;
RK_U32 u32DstWidth = 960;
RK_U32 u32DstHeight = 540;
IMAGE_TYPE_E enPixFmt = IMAGE_TYPE_NV12;
const RK_CHAR *pcIqFileDir = "/oem/etc/iqfiles/";
RK_S32 s32CamId = 0;
RK_U32 u32Rotation = 0;
RK_BOOL bMultictx = RK_FALSE;
RK_CHAR *pDeviceName = "rkispp_scale0";void print_info(void) {printf("#SrcWidth: %d\n", u32SrcWidth);printf("#u32SrcHeight: %d\n", u32SrcHeight);printf("#u32DstWidth: %d\n", u32DstWidth);printf("#u32DstHeight: %d\n", u32DstHeight);printf("#u32Rotation: %d\n", u32Rotation);printf("#OutPath: %s\n", g_pOutPath);printf("#CameraIdx: %d\n\n", s32CamId);printf("#Rkaiq XML DirPath: %s\n", pcIqFileDir);printf("#bMultictx: %d\n\n", bMultictx);
}void set_vi_chn(VI_CHN_ATTR_S *vi_chn_attr) {memset(vi_chn_attr, 0, sizeof(vi_chn_attr));// memset(&vi_chn_attr, 0, sizeof(VI_CHN_ATTR_S));vi_chn_attr->pcVideoNode = pDeviceName;vi_chn_attr->u32BufCnt = 3;vi_chn_attr->u32Width = u32SrcWidth;vi_chn_attr->u32Height = u32SrcHeight;vi_chn_attr->enPixFmt = enPixFmt;vi_chn_attr->enBufType = VI_CHN_BUF_TYPE_MMAP;vi_chn_attr->enWorkMode = VI_WORK_MODE_NORMAL;
}void set_venc_chn(VENC_CHN_ATTR_S *venc_chn_attr) {memset(venc_chn_attr, 0, sizeof(VENC_CHN_ATTR_S));venc_chn_attr->stVencAttr.enType = RK_CODEC_TYPE_JPEG;venc_chn_attr->stVencAttr.imageType = IMAGE_TYPE_NV12;venc_chn_attr->stVencAttr.u32PicWidth = u32SrcWidth;venc_chn_attr->stVencAttr.u32PicHeight = u32SrcHeight;venc_chn_attr->stVencAttr.u32VirWidth = u32SrcWidth;venc_chn_attr->stVencAttr.u32VirHeight = u32SrcHeight;venc_chn_attr->stVencAttr.stAttrJpege.u32ZoomWidth = u32DstWidth;venc_chn_attr->stVencAttr.stAttrJpege.u32ZoomHeight = u32DstHeight;venc_chn_attr->stVencAttr.stAttrJpege.u32ZoomVirWidth = u32DstWidth;venc_chn_attr->stVencAttr.stAttrJpege.u32ZoomVirHeight = u32DstHeight;venc_chn_attr->stVencAttr.enRotation = VENC_ROTATION_180;
}int main(void) {static int picCounter = 0;int c;print_info();rk_aiq_working_mode_t hdr_mode = RK_AIQ_WORKING_MODE_NORMAL;int fps = 30;SAMPLE_COMM_ISP_Init(s32CamId, hdr_mode, bMultictx, pcIqFileDir);SAMPLE_COMM_ISP_Run(s32CamId);SAMPLE_COMM_ISP_SetFrameRate(s32CamId, fps);printf("init sys\n");ret = RK_MPI_SYS_Init();if (ret) {printf("Sys Init failed! ret=%d\n", ret);return -1;}printf("1\n");VI_CHN_ATTR_S vi_chn_attr;set_vi_chn(&vi_chn_attr);printf("2\n");ret = RK_MPI_VI_SetChnAttr(s32CamId, 1, &vi_chn_attr);ret |= RK_MPI_VI_EnableChn(s32CamId, 1);printf("3\n");if (ret) {printf("Create Vi failed! ret=%d\n", ret);return -1;}printf("create channel \n");VENC_CHN_ATTR_S venc_chn_attr;set_venc_chn(&venc_chn_attr);ret = RK_MPI_VENC_CreateChn(0, &venc_chn_attr);if (ret) {printf("Create Venc failed! ret=%d\n", ret);return -1;}MPP_CHN_S stEncChn;stEncChn.enModId = RK_ID_VENC;stEncChn.s32ChnId = 0;printf("reg out cb\n");ret = RK_MPI_SYS_RegisterOutCb(&stEncChn, video_packet_cb);if (ret) {printf("Register Output callback failed! ret=%d\n", ret);return -1;}// The encoder defaults to continuously receiving frames from the previous// stage. Before performing the bind operation, set s32RecvPicNum to 0 to// make the encoding enter the pause state.VENC_RECV_PIC_PARAM_S stRecvParam;stRecvParam.s32RecvPicNum = 0;RK_MPI_VENC_StartRecvFrame(0, &stRecvParam);// bind vi ch 1 to venc ch 0printf("bind vi and venc\n");MPP_CHN_S stSrcChn;stSrcChn.enModId = RK_ID_VI;stSrcChn.s32ChnId = 1;MPP_CHN_S stDestChn;stDestChn.enModId = RK_ID_VENC;stDestChn.s32ChnId = 0;ret = RK_MPI_SYS_Bind(&stSrcChn, &stDestChn);if (ret) {printf("Bind VI[1] to VENC[0]::JPEG failed! ret=%d\n", ret);return -1;}#if 0printf("init rgn\n");RK_MPI_VENC_RGN_Init(0, NULL);BITMAP_S BitMap;BitMap.enPixelFormat = PIXEL_FORMAT_ARGB_8888;BitMap.u32Width = 64;BitMap.u32Height = 256;BitMap.pData = malloc(BitMap.u32Width * 4 * BitMap.u32Height);RK_U8 *ColorData = (RK_U8 *) BitMap.pData;RK_U16 ColorBlockSize = BitMap.u32Height * BitMap.u32Width;set_argb8888_buffer((RK_U32 *) ColorData, ColorBlockSize / 4, TEST_ARGB32_YELLOW);set_argb8888_buffer((RK_U32 *) (ColorData + ColorBlockSize), ColorBlockSize / 4, TEST_ARGB32_TRANS);set_argb8888_buffer((RK_U32 *) (ColorData + 2 * ColorBlockSize), ColorBlockSize / 4, TEST_ARGB32_RED);set_argb8888_buffer((RK_U32 *) (ColorData + 3 * ColorBlockSize), ColorBlockSize / 4, TEST_ARGB32_BLUE);printf("create rgn\n");// Case 1: Canvas and bitmap are equal in sizeOSD_REGION_INFO_S RngInfo;RngInfo.enRegionId = REGION_ID_0;RngInfo.u32PosX = 0;RngInfo.u32PosY = 0;RngInfo.u32Width = 64;RngInfo.u32Height = 256;RngInfo.u8Enable = 1;RngInfo.u8Inverse = 0;RK_MPI_VENC_RGN_SetBitMap(0, &RngInfo, &BitMap);
#endifprintf("%s initial finish\n", __func__);// signal(SIGINT, sigterm_handler);char cmd[64];// int qfactor = 0;VENC_JPEG_PARAM_S stJpegParam;// printf("#Usage: input 'quit' to exit programe!\n peress any other key to capture one picture to file\n");
#if 0stJpegParam.u32Qfactor = 99;RK_MPI_VENC_SetJpegParam(0, &stJpegParam);stRecvParam.s32RecvPicNum = 1;ret = RK_MPI_VENC_StartRecvFrame(0, &stRecvParam);if (ret) {printf("RK_MPI_VENC_StartRecvFrame failed!\n");return -1;}
#endif
#if 1stJpegParam.u32Qfactor = 99;RK_MPI_VENC_SetJpegParam(0, &stJpegParam);printf("main start\n");while (1) {
//
//        if (qfactor >= 99)
//            qfactor = 1;
//        else
//            qfactor = ((qfactor + 10) > 99) ? 99 : (qfactor + 10);//  printf("qfactor = %d\n", qfactor);// printf("running main\n");stRecvParam.s32RecvPicNum = 1;ret = RK_MPI_VENC_StartRecvFrame(0, &stRecvParam);if (ret) {printf("RK_MPI_VENC_StartRecvFrame failed!\n");break;}getPicture = false;while (!getPicture) {usleep(10000); // sleep 30 ms.}picCounter++;if (picCounter > 10) {// break;}// usleep(30000); // sleep 30 ms.}
#endifRK_MPI_SYS_UnBind(&stSrcChn, &stDestChn);RK_MPI_VENC_DestroyChn(0);RK_MPI_VI_DisableChn(s32CamId, 1);if (pcIqFileDir) {SAMPLE_COMM_ISP_Stop(s32CamId);}printf("%s exit!\n", __func__);return 0;
}

上面的代码执行起来, 会不停的删除之前的图片,抓取jpeg编码后的数据,写入新的同名图片, 保存在一个nginx的www目录下面, 方便我们后期用一个自动刷新的网站来显示使用yolov5做predict之前的图片.

这样我们就获得了一张从摄像头获取的jpeg图片. 且是不断刷新的.
然后使用前面说的rknn的示例代码, 进行推测:
注意几点:

  1. 使用模型要复制到app执行的目录下面, 名字是yolov5s_relu_rv1109_rv1126_out_opt.rknn
  2. COCO的标签也需要复制过去
  3. 原本执行的参数, 我直接写死了, 省得每次都要打参数进去.
  4. 输出路径同为nginx的www目录, 不过我的nginx的是跑在我开发环境的ubuntu上面的, 所以目录不能搞乱了, 其实可以考虑把nginx跑在开发板上, 只是需要拿nginx源码编译一下就行.

具体代码main.cc如下:

/*-------------------------------------------Includes
-------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <dlfcn.h>
#include <vector>
#include <string>#define _BASETSD_H#define STB_IMAGE_IMPLEMENTATION#include "stb/stb_image.h"#define STB_IMAGE_RESIZE_IMPLEMENTATION#include <stb/stb_image_resize.h>#define STB_IMAGE_WRITE_IMPLEMENTATION#include "stb/stb_image_write.h"#undef cimg_display
#define cimg_display 0
#undef cimg_use_jpeg
#define cimg_use_jpeg 1
#undef cimg_use_png
#define cimg_use_png 1#include "CImg/CImg.h"#include "drm_func.h"
#include "rga_func.h"
#include "rknn_api.h"
#include "postprocess.h"#define PERF_WITH_POST 1
#define COCO_IMG_NUMBER 5000using namespace cimg_library;/*-------------------------------------------Functions
-------------------------------------------*/
static void printRKNNTensor(rknn_tensor_attr *attr) {printf("index=%d name=%s n_dims=%d dims=[%d %d %d %d] n_elems=%d size=%d ""fmt=%d type=%d qnt_type=%d fl=%d zp=%d scale=%f\n",attr->index, attr->name, attr->n_dims, attr->dims[3], attr->dims[2],attr->dims[1], attr->dims[0], attr->n_elems, attr->size, 0, attr->type,attr->qnt_type, attr->fl, attr->zp, attr->scale);
}double __get_us(struct timeval t) { return (t.tv_sec * 1000000 + t.tv_usec); }rknn_context ctx;
int status = 0;
void *drm_buf = NULL;
int drm_fd = -1;
int buf_fd = -1; // converted from buffer handle
unsigned int handle;
size_t actual_size = 0;
int img_width = 0;
int img_height = 0;
int img_channel = 0;
rga_context rga_ctx;
drm_context drm_ctx;
const float nms_threshold = 0.65;
const float conf_threshold = 0.2;
struct timeval start_time, stop_time;
int ret;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;
}static unsigned char *
load_image(const char *image_path, int *org_height, int *org_width, int *org_ch, rknn_tensor_attr *input_attr) {int req_height = 0;int req_width = 0;int req_channel = 0;switch (input_attr->fmt) {case RKNN_TENSOR_NHWC:req_height = input_attr->dims[2];req_width = input_attr->dims[1];req_channel = input_attr->dims[0];break;case RKNN_TENSOR_NCHW:req_height = input_attr->dims[1];req_width = input_attr->dims[0];req_channel = input_attr->dims[2];break;default:printf("meet unsupported layout\n");return NULL;}// printf("w=%d,h=%d,c=%d, fmt=%d\n", req_width, req_height, req_channel, input_attr->fmt);int height = 0;int width = 0;int channel = 0;unsigned char *image_data = stbi_load(image_path, &width, &height, &channel, req_channel);if (image_data == NULL) {printf("load image-%s failed!\n", image_path);return NULL;}if (channel == 1) {printf("image is grey, convert to RGB");void *rgb_data = malloc(width * height * 3);for (int i = 0; i < height; i++) {for (int j = 0; j < width; j++) {int offset = (i * width + j) * 3;((unsigned char *) rgb_data)[offset] = ((unsigned char *) image_data)[offset];((unsigned char *) rgb_data)[offset + 1] = ((unsigned char *) image_data)[offset];((unsigned char *) rgb_data)[offset + 2] = ((unsigned char *) image_data)[offset];}}free(image_data);image_data = (unsigned char *) rgb_data;channel = 3;}if (width % 4 != 0) {int new_width = width + (4 - width % 4);printf("%d is not pixel align, resize to %d, this will make the result shift slightly\n", width, new_width);void *resize_data = malloc(new_width * height * channel);stbir_resize_uint8(image_data, width, height, 0, (unsigned char *) resize_data, new_width, height, 0, channel);free(image_data);image_data = (unsigned char *) resize_data;*org_width = new_width;} else {*org_width = width;}*org_height = height;*org_ch = channel;return image_data;
}void predict(rknn_tensor_attr *output_attrs, rknn_output *outputs, rknn_input *inputs, rknn_input_output_num *io_num,int input_width, int input_height, int input_channel, rknn_tensor_attr *input_attrs, void *resize_buf) {char *image_name = "/mnt/www/rknn_before.jpeg";unsigned char *input_data = NULL;/* Input preprocess */// Load imageCImg<unsigned char> img(image_name);input_data = load_image(image_name, &img_height, &img_width, &img_channel, input_attrs);if (!input_data) {return;}printf("init drm\n");// DRM alloc bufferdrm_fd = drm_init(&drm_ctx);drm_buf = drm_buf_alloc(&drm_ctx, drm_fd, img_width, img_height, input_channel * 8,&buf_fd, &handle, &actual_size);memcpy(drm_buf, input_data, img_width * img_height * input_channel);// Letter box resizeprintf("resize\n");float img_wh_ratio = (float) img_width / (float) img_height;float input_wh_ratio = (float) input_width / (float) input_height;float resize_scale = 0;int resize_width;int resize_height;int h_pad;int w_pad;if (img_wh_ratio >= input_wh_ratio) {//pad height dimresize_scale = (float) input_width / (float) img_width;resize_width = input_width;resize_height = (int) ((float) img_height * resize_scale);w_pad = 0;h_pad = (input_height - resize_height) / 2;} else {//pad width dimresize_scale = (float) input_height / (float) img_height;resize_width = (int) ((float) img_width * resize_scale);resize_height = input_height;w_pad = (input_width - resize_width) / 2;;h_pad = 0;}// printf("w_pad: %d, h_pad: %d\n", w_pad, h_pad);// printf("resize_width: %d, resize_height: %d\n", resize_width, resize_height);printf("init rga_ctx\n");// Init rga contextRGA_init(&rga_ctx);img_resize_slow(&rga_ctx, drm_buf, img_width, img_height, resize_buf, resize_width, resize_height, w_pad,h_pad);inputs[0].buf = resize_buf;gettimeofday(&start_time, NULL);rknn_inputs_set(ctx, io_num->n_input, inputs);printf("rknn run\n");ret = rknn_run(ctx, NULL);ret = rknn_outputs_get(ctx, io_num->n_output, outputs, NULL);printf("post process\n");/* Post process */detect_result_group_t detect_result_group;std::vector<float> out_scales;std::vector<uint8_t> out_zps;for (int i = 0; i < io_num->n_output; ++i) {out_scales.push_back(output_attrs[i].scale);out_zps.push_back(output_attrs[i].zp);}printf("post process u8\n");post_process_u8((uint8_t *) outputs[0].buf, (uint8_t *) outputs[1].buf, (uint8_t *) outputs[2].buf,input_height, input_width,h_pad, w_pad, resize_scale, conf_threshold, nms_threshold, out_zps, out_scales,&detect_result_group);printf("get time\n");gettimeofday(&stop_time, NULL);printf("once run use %f ms\n",(__get_us(stop_time) - __get_us(start_time)) / 1000);printf("draw object\n");// Draw Objectsconst unsigned char blue[] = {0, 0, 255};char score_result[64];for (int i = 0; i < detect_result_group.count; i++) {detect_result_t *det_result = &(detect_result_group.results[i]);printf("%s @ (%d %d %d %d) %f\n",det_result->name,det_result->box.left, det_result->box.top, det_result->box.right, det_result->box.bottom,det_result->prop);int x1 = det_result->box.left;int y1 = det_result->box.top;int x2 = det_result->box.right;int y2 = det_result->box.bottom;int ret = snprintf(score_result, sizeof score_result, "%f", det_result->prop);//draw boximg.draw_rectangle(x1, y1, x2, y2, blue, 1, ~0U);img.draw_text(x1, y1 - 24, det_result->name, blue);img.draw_text(x1, y1 - 12, score_result, blue);}img.save("/mnt/www/rknn_after.bmp");ret = rknn_outputs_release(ctx, io_num->n_output, outputs);// loop testprintf("loop test\n");int test_count = 50;gettimeofday(&start_time, NULL);for (int i = 0; i < test_count; ++i) {img_resize_slow(&rga_ctx, drm_buf, img_width, img_height, resize_buf, resize_width, resize_height, w_pad,h_pad);rknn_inputs_set(ctx, io_num->n_input, inputs);ret = rknn_run(ctx, NULL);ret = rknn_outputs_get(ctx, io_num->n_output, outputs, NULL);post_process_u8((uint8_t *) outputs[0].buf, (uint8_t *) outputs[1].buf, (uint8_t *) outputs[2].buf,input_height, input_width,h_pad, w_pad, resize_scale, conf_threshold, nms_threshold, out_zps, out_scales,&detect_result_group);ret = rknn_outputs_release(ctx, io_num->n_output, outputs);}gettimeofday(&stop_time, NULL);printf("run loop count = %d , average time: %f ms\n", test_count,(__get_us(stop_time) - __get_us(start_time)) / 1000.0 / test_count);drm_buf_destroy(&drm_ctx, drm_fd, buf_fd, handle, drm_buf, actual_size);drm_deinit(&drm_ctx, drm_fd);free(input_data);
}/*-------------------------------------------* Main Functions
-------------------------------------------*/
int main(int argc, char **argv) {memset(&rga_ctx, 0, sizeof(rga_context));memset(&drm_ctx, 0, sizeof(drm_context));if (argc != 5) {printf("Usage: %s <rknn model> [fp/u8] [single_img/multi_imgs] <path>\n", argv[0]);// return -1;}// model_name = (char *) argv[1];// char *input_type = argv[3];// char *input_path = argv[4];printf("Post process with u8\n");printf("Test with single img\n");/* Create the neural network */printf("Loading model...\n");int model_data_size = 0;char *modelName = "/mnt/my_stuff/yolov5s_relu_rv1109_rv1126_out_opt.rknn";unsigned char *model_data = load_model(modelName, &model_data_size);printf("model_name:%s model_data_size:%d\n", modelName, model_data_size);ret = rknn_init(&ctx, model_data, model_data_size, 0);if (ret < 0) {printf("rknn_init error ret=%d\n", ret);return -1;}printf("Query SDK version...\n");/* Query sdk version */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);/* Get input,output attr */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;}printRKNNTensor(&(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));printRKNNTensor(&(output_attrs[i]));}int input_channel = 3;int input_width = 0;int input_height = 0;if (input_attrs[0].fmt == RKNN_TENSOR_NCHW) {printf("model is NCHW input fmt\n");input_width = input_attrs[0].dims[0];input_height = input_attrs[0].dims[1];} else {printf("model is NHWC input fmt\n");input_width = input_attrs[0].dims[1];input_height = input_attrs[0].dims[2];}printf("model input height=%d, width=%d, channel=%d\n", input_height, input_width, input_channel);/* Init input tensor */rknn_input inputs[1];memset(inputs, 0, sizeof(inputs));inputs[0].index = 0;inputs[0].type = RKNN_TENSOR_UINT8;inputs[0].size = input_width * input_height * input_channel;inputs[0].fmt = RKNN_TENSOR_NHWC;inputs[0].pass_through = 0;/* Init output tensor */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 = 0;}void *resize_buf = malloc(input_height * input_width * input_channel);// unsigned char *input_data = NULL;/* Single img input */printf("Single img input\n");while (1) {predict(output_attrs, outputs, inputs, &io_num,input_width, input_height, input_channel, input_attrs, resize_buf);usleep(10000);}// releaseret = rknn_destroy(ctx);RGA_deinit(&rga_ctx);if (model_data) {free(model_data);}if (resize_buf) {free(resize_buf);}return 0;
}

使用自带的build.sh脚本编译安装就行.

接着 把两个应用跟nginx都跑起来, 就可以看到整个效果了.

在这里插入图片描述

我特么红外又忘了关了。。。

最后这个自动刷新的网站的html脚本如下:

<!DOCTYPE html>
<html><head><title>Welcome to nginx!</title><style>body {width: 35em;margin: 0 auto;font-family: Tahoma, Verdana, Arial, sans-serif;}</style>
</head><body><center><b>Marc's rknn_yolov5 play ground</b></br><img src="rknn_before.jpeg" /> <img src="rknn_after.bmp" /></center></body>
<script language="Javascript">function myrefresh() {window.location.reload();}setTimeout('myrefresh ()', 1000); // 指定 1 秒刷新一次(1401)
</script></html>

http://www.ppmy.cn/news/152383.html

相关文章

Ubuntu下Intel A201 Wifi6驱动安装

新入的一台联想台式机&#xff0c;安装Ubuntu20.04系统后&#xff0c;发现Wifi怎么也不好用。 经过各种折腾&#xff0c;包括升级内核&#xff0c;更新firmware等操作&#xff0c;参考了一系列的文章&#xff0c;最终解决方法如下。 参考文章&#xff1a; (2条消息) Ubuntu2…

java a201游戏_OPPO手机A201 为何下载游戏没这个机型?

MTK可以理解为现在国产手机用的系统。 MTK的优点&#xff1a; MTK的主菜单和子菜单都可以用数字选择&#xff0c;诺基亚的子菜单就要一个个往下按。 用笔画的都知道&#xff0c;诺基亚S40的机子&#xff0c;默认拼音做输入法&#xff0c;不可更改。 诺基亚S40的屏幕亮度和对比度…

OpenGL蓝宝书第八章学习笔记:基元处理之几何着色器

前言 本篇在讲什么 OpenGL蓝宝书第八章学习笔记之几何着色器 本篇适合什么 适合初学OpenGL的小白 本篇需要什么 对C语法有简单认知 对OpenGL有简单认知 最好是有OpenGL超级宝典蓝宝书 依赖Visual Studio编辑器 本篇的特色 具有全流程的图文教学 重实践&#xff0c…

关于vivo手机安装失败的解决办法

真的不想吐槽vivo手机了 连接真机测试安装APP失败报如下错误 Installation did not succeed. The application could not be installed: INSTALL_FAILED_TEST_ONLY Installation failed due to: null Retry 解决办法如下 打开gradle.properties这个文件&#xff0c;添加如下…

vivoy85a参数配置_vivo Y85手机详细配置参数和图鉴

最新的vivo新品发布会上了,最新发布了一款千元手机vivo y58,这款手机怎么样呢?下面就让小编来大家看下这款手机的详细配置参数和图赏吧。 vivo Y85 废话不多说,直接上vivo Y85配置参数,包含了价格与各硬件,如下参数表所示。 vivo Y85配置参数 屏幕规格 6.26英寸2280x1080…

vivo手机刷鸿蒙教程,vivo手机怎么刷机_vivo手机刷机全教程

现在全中国的人用vivo手机的应该有一百个人里面有十几个,那么vivo手机怎么进行刷机呢,这样就可以安装自己喜欢的系统,或者自己的手机密码忘了还可以通过刷机打开。 1.最直接简单的办法 手机关机,按关机键和音量上键,双清手机 去vivo官网下载对应机型的安装包,存在手机根目…

vivo手机哪款性价比高质量好 2022

iQOOZ5是我用过的体验中最舒服的千元机&#xff0c;绝对值得爆炸的神机。首先Z5采用骁龙778G处理器&#xff0c;778G处理器不仅性能强&#xff0c;而且耗电也非常无敌。所有778G模型的续航表现都很好&#xff0c;例如小米Civi、荣光50、GT母版等&#xff0c;iQOZ5的电池容量达到…

什么是 TypeScript ? 快速上手 TypeScript

什么是 TypeScript &#xff1f; TypeScript是一种由微软开发的开源编程语言&#xff0c;它是JavaScript语言的一个超集&#xff0c;支持JavaScript中的所有语法和特性&#xff0c;并在此基础上添加了一些新的特性。 TypeScript与JavaScript最大的不同是它引入了静态类型检查机…