Compare commits
23 Commits
oldversion
...
5.26last
Author | SHA1 | Date | |
---|---|---|---|
96745618e4 | |||
48afdbf662 | |||
6111475b3f | |||
060d02d7d9 | |||
c05c6d23aa | |||
a386df5401 | |||
81af2e2fa0 | |||
4794a062dc | |||
e8732009f2 | |||
f48627f6fa | |||
e2e229ebf0 | |||
fe65c81e3f | |||
bf45251b76 | |||
9da1ec5861 | |||
6a65fce840 | |||
a9eb288f8d | |||
b7ba69c736 | |||
bec8a43c72 | |||
8c0451dae8 | |||
9e6195c5ca | |||
4866767048 | |||
4cc773d30c | |||
e16eb29887 |
@ -1,6 +1,8 @@
|
||||
# rknn_yolo_EAI_pic
|
||||
# 本串口协议必备要求:先发送在接收
|
||||
|
||||
### 作者:崔志佳
|
||||
## 注:本项目已经通过串口测试(传感器为115200,摄像头为9500),每次报警前会识别设备名称序号,然后反馈到串口输出序列中
|
||||
|
||||
# rknn_yolo_EAI_pic
|
||||
|
||||
#### 简要说明
|
||||
|
||||
@ -8,7 +10,7 @@
|
||||
集成了从串口读取红外温度数据,到达阈值后报警并运行rknn模型
|
||||
|
||||
需注意运行该例程需要将npu驱动更新为1.7.3版本
|
||||
|
||||
|
||||
本项目只适用于EAI-YOLOV5
|
||||
详情请参考EAI官网:https://www.easy-eai.com/document_details/3/342
|
||||
|
||||
|
81
include/jlinux_uart.h
Normal file
81
include/jlinux_uart.h
Normal file
@ -0,0 +1,81 @@
|
||||
/***********************************************************************
|
||||
* @file jlinux_uart.h
|
||||
JLINUX_UART
|
||||
* @brief header file
|
||||
* @history
|
||||
* Date Version Author description
|
||||
* ========== ======= ========= =======================================
|
||||
* 2022-07-27 V1.0 Lucky,lukai@jovision.com Create
|
||||
*
|
||||
* @Copyright (C) 2022 Jovision Technology Co., Ltd.
|
||||
***********************************************************************/
|
||||
#ifndef __JLINUX_UART_H__
|
||||
#define __JLINUX_UART_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
typedef struct _uart_ctx *juart_hdl_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int baudrate; //波特率:1200/2400/4800/9600/19200/38400/57600/115200/230400/380400/460800/921600
|
||||
int datawidth; //数据位宽度:5/6/7/8
|
||||
int stopbit; //停止位宽度:1/2
|
||||
int parity; //奇偶校验:0无校验,1奇校验,2偶校验
|
||||
}JUartAttr_t;
|
||||
|
||||
/**
|
||||
*@brief 打开串口设备设备,如果是485设备请配合jctrl_rs485相关接口使用
|
||||
*@param name 设备名称,如:/dev/ttyS0
|
||||
*@return 句柄
|
||||
*/
|
||||
juart_hdl_t juart_open(const char *name);
|
||||
|
||||
/**
|
||||
*@brief 关闭串口
|
||||
*@param handle 句柄
|
||||
*/
|
||||
int juart_close(juart_hdl_t handle);
|
||||
|
||||
/**
|
||||
*@brief 配置串口属性
|
||||
*@param handle 句柄
|
||||
*@param attr 属性
|
||||
*/
|
||||
int juart_set_attr(juart_hdl_t handle, JUartAttr_t *attr);
|
||||
|
||||
int juart_get_fd(juart_hdl_t uart);
|
||||
/**
|
||||
*@brief 通过串口发送数据
|
||||
*@param handle 句柄
|
||||
*@param data 数据buffer
|
||||
*@param len 数据长度
|
||||
*@return 0成功
|
||||
*/
|
||||
int juart_send(juart_hdl_t handle, char *data, int len);
|
||||
|
||||
/**
|
||||
*@brief 通过串口接受数据
|
||||
*@param handle 句柄
|
||||
*@param data 数据buffer
|
||||
*@param len buffer的长度
|
||||
*@param timeout 超时毫秒
|
||||
*@return 收到数据的长度
|
||||
*/
|
||||
int juart_recv(juart_hdl_t handle, char *data, int len, int timeout);
|
||||
|
||||
/**
|
||||
*@brief 设置rs485模式
|
||||
*@param handle 句柄
|
||||
*@param mode 0:发送后立刻置为接收状态;非0:发送后保持发送状态
|
||||
*@return 0 成功
|
||||
*/
|
||||
int juart_set_rs485(juart_hdl_t handle, int mode);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // __JLINUX_UART_H__
|
1826
src/6.10main .cpp
Normal file
1826
src/6.10main .cpp
Normal file
File diff suppressed because it is too large
Load Diff
313
src/jlinux_uart.cpp
Normal file
313
src/jlinux_uart.cpp
Normal file
@ -0,0 +1,313 @@
|
||||
/***********************************************************************
|
||||
* @file jctrl_uart.cpp
|
||||
JCTRL_UART
|
||||
* @brief header file
|
||||
* @history
|
||||
* Date Version Author description
|
||||
* ========== ======= ========= =======================================
|
||||
* 2022-07-21 V1.0 Lucky,lukai@jovision.com Create
|
||||
*
|
||||
* @Copyright (C) 2022 Jovision Technology Co., Ltd.
|
||||
***********************************************************************/
|
||||
#include <termios.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <linux/stat.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/serial.h>
|
||||
#include "jlinux_uart.h"
|
||||
|
||||
struct _uart_ctx{
|
||||
int fd;
|
||||
};
|
||||
|
||||
int _get_baudrate(int nBaud)
|
||||
{
|
||||
switch(nBaud)
|
||||
{
|
||||
case 1200:
|
||||
return B1200; //注:B1200为系统定义
|
||||
case 2400:
|
||||
return B2400;
|
||||
case 4800:
|
||||
return B4800;
|
||||
case 9600:
|
||||
return B9600;
|
||||
case 19200 :
|
||||
return B19200;
|
||||
case 38400:
|
||||
return B38400;
|
||||
case 57600:
|
||||
return B57600;
|
||||
case 115200:
|
||||
return B115200;
|
||||
default:
|
||||
return B2400;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
juart_hdl_t juart_open(const char *name){
|
||||
juart_hdl_t uart = new _uart_ctx;
|
||||
uart->fd = open(name, O_RDWR | O_NONBLOCK | O_NOCTTY | O_EXCL|O_SYNC);
|
||||
return uart;
|
||||
}
|
||||
int juart_close(juart_hdl_t uart){
|
||||
if(uart->fd>0)
|
||||
close(uart->fd);
|
||||
uart->fd = 0;
|
||||
return 0;
|
||||
}
|
||||
int juart_get_fd(juart_hdl_t uart){
|
||||
return uart->fd;
|
||||
}
|
||||
int juart_set_attr(juart_hdl_t uart, JUartAttr_t *attr){
|
||||
if (uart->fd <= 0)
|
||||
{
|
||||
printf("jv_uart_recv_ex fd error\n");
|
||||
return -1;
|
||||
}
|
||||
struct termios newtio, oldtio;
|
||||
memset(&oldtio, 0, sizeof(oldtio));
|
||||
/* save the old serial port configuration */
|
||||
if (tcgetattr(uart->fd, &oldtio) != 0) {
|
||||
perror("set_port/tcgetattr");
|
||||
return -1;
|
||||
}
|
||||
memset(&newtio, 0, sizeof(newtio));
|
||||
//设置波特率
|
||||
int nBaud = _get_baudrate(attr->baudrate);
|
||||
switch (nBaud)
|
||||
{
|
||||
case B300:
|
||||
case B1200:
|
||||
case B2400:
|
||||
case B4800:
|
||||
case B9600:
|
||||
case B19200:
|
||||
case B38400:
|
||||
case B57600:
|
||||
case B115200:
|
||||
cfsetospeed(&newtio, nBaud);
|
||||
cfsetispeed(&newtio, nBaud);
|
||||
break;
|
||||
default:
|
||||
printf("jv_uart_set_attr:Unsupported baudrate!\n");
|
||||
return -1;
|
||||
}
|
||||
/* ignore modem control lines and enable receiver */
|
||||
newtio.c_cflag |= CLOCAL | CREAD;
|
||||
newtio.c_cflag &= ~CSIZE;
|
||||
/* set character size */
|
||||
switch (attr->datawidth) {
|
||||
case 5:
|
||||
newtio.c_cflag |= CS5;
|
||||
break;
|
||||
case 6:
|
||||
newtio.c_cflag |= CS6;
|
||||
break;
|
||||
case 7:
|
||||
newtio.c_cflag |= CS7;
|
||||
break;
|
||||
case 8:
|
||||
default:
|
||||
newtio.c_cflag |= CS8;
|
||||
break;
|
||||
}
|
||||
/* set the stop bits */
|
||||
switch (attr->stopbit) {
|
||||
default:
|
||||
case 1:
|
||||
newtio.c_cflag &= ~CSTOPB;
|
||||
break;
|
||||
case 2:
|
||||
newtio.c_cflag |= CSTOPB;
|
||||
break;
|
||||
}
|
||||
/* set the parity */
|
||||
switch (attr->parity) {
|
||||
case 'o':
|
||||
case 'O':
|
||||
case 1:
|
||||
newtio.c_cflag |= PARENB;
|
||||
newtio.c_cflag |= PARODD;
|
||||
newtio.c_iflag |= INPCK;
|
||||
break;
|
||||
case 'e':
|
||||
case 'E':
|
||||
case 2:
|
||||
newtio.c_cflag |= PARENB;
|
||||
newtio.c_cflag &= ~PARODD;
|
||||
newtio.c_iflag |= INPCK;
|
||||
break;
|
||||
case 'n':
|
||||
case 'N':
|
||||
case 0:
|
||||
default:
|
||||
newtio.c_cflag &= ~PARENB;
|
||||
newtio.c_iflag &= ~INPCK;
|
||||
break;
|
||||
}
|
||||
/* Raw input */
|
||||
newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
|
||||
/* Software flow control is disabled */
|
||||
newtio.c_iflag &= ~(IXON | IXOFF | IXANY);
|
||||
/* Raw ouput */
|
||||
newtio.c_oflag &=~ OPOST;
|
||||
/* set timeout in deciseconds for non-canonical read */
|
||||
newtio.c_cc[VTIME] = 0;
|
||||
/* set minimum number of characters for non-canonical read */
|
||||
newtio.c_cc[VMIN] = 0;
|
||||
/* flushes data received but not read */
|
||||
tcflush(uart->fd, TCIFLUSH);
|
||||
/* set the parameters associated with the terminal from
|
||||
the termios structure and the change occurs immediately */
|
||||
if ((tcsetattr(uart->fd, TCSANOW, &newtio)) != 0) {
|
||||
perror("set_port/tcsetattr");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int juart_send(juart_hdl_t uart, char *data, int len){
|
||||
if (uart->fd > 0)
|
||||
{
|
||||
int ret = write(uart->fd, data, len);
|
||||
if (ret == len)
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
int _modbus_rtu_select(juart_hdl_t uart, struct timeval *tv)
|
||||
{
|
||||
fd_set rfds;
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(uart->fd, &rfds);
|
||||
int s_rc;
|
||||
while ((s_rc = select(uart->fd+1, &rfds, NULL, NULL, tv)) == -1) {
|
||||
if (errno == EINTR) {
|
||||
fprintf(stderr, "A non blocked signal was caught\n");
|
||||
/* Necessary after an error */
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(uart->fd, &rfds);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (s_rc == 0) {
|
||||
/* Timeout */
|
||||
errno = ETIMEDOUT;
|
||||
return -1;
|
||||
}
|
||||
return s_rc;
|
||||
}
|
||||
int juart_recv(juart_hdl_t uart, char *data, int len, int timeout){
|
||||
if (uart->fd > 0)
|
||||
{
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = timeout*1000;
|
||||
if(_modbus_rtu_select(uart, &tv) > 0){
|
||||
return read(uart->fd, data, len);
|
||||
}
|
||||
return -1;
|
||||
}else{
|
||||
usleep(timeout*1000);
|
||||
}
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*@brief 接收串口数据扩展接口,从收到start开始接收,到收到stop返回
|
||||
*@param handle 句柄
|
||||
*@param data 接收数据缓存
|
||||
*@param len 缓存大小
|
||||
*@param start 数据头标志:前nstart个字节
|
||||
*@param nstart 数据头字节数
|
||||
*@param stop 数据截止标志:后nstop个字节
|
||||
*@param nstop 数据截止标志的字节数
|
||||
*/
|
||||
extern "C" int juart_recv_ex(juart_hdl_t handle, char *data, int len, char *start, int nstart, char *stop, int nstop, int timeout);
|
||||
int juart_recv_ex(juart_hdl_t uart, char *data, int len, char *start, int nstart, char *stop, int nstop, int timeout){
|
||||
if (uart->fd <= 0)
|
||||
{
|
||||
printf("jv_uart_recv_ex fd error\n");
|
||||
return -1;
|
||||
}
|
||||
int offset = 0;
|
||||
int offset_end = 0;
|
||||
int bytes_read = 0;
|
||||
while (1)
|
||||
{
|
||||
bytes_read = read(uart->fd, &data[offset], 1);
|
||||
if (bytes_read == 1 && offset < nstart && data[offset] == start[offset])
|
||||
{
|
||||
offset++;
|
||||
}
|
||||
if (offset == nstart)
|
||||
break;
|
||||
if (bytes_read < 1)
|
||||
usleep(0);
|
||||
}
|
||||
while (offset < len)
|
||||
{
|
||||
if (data[offset] == stop[offset_end])
|
||||
{
|
||||
offset_end++;
|
||||
}
|
||||
if (offset_end == nstop)
|
||||
break;
|
||||
bytes_read = read(uart->fd, &data[offset], 1);
|
||||
if (bytes_read == 1)
|
||||
{
|
||||
offset++;
|
||||
}
|
||||
else
|
||||
{
|
||||
usleep(0);
|
||||
}
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
/**
|
||||
*@brief 设置rs485模式
|
||||
*@param handle 句柄
|
||||
*@param mode 0:发送后立刻置为接收状态;非0:发送后保持发送状态
|
||||
*@return 0 成功
|
||||
*/
|
||||
int juart_set_rs485(juart_hdl_t handle, int mode)
|
||||
{
|
||||
struct serial_rs485 rs485;
|
||||
if (ioctl(handle->fd, TIOCGRS485, &rs485) == -1)
|
||||
{
|
||||
printf("TIOCGRS485 ioctl error.\n");
|
||||
return -1;
|
||||
}
|
||||
rs485.flags |= SER_RS485_ENABLED;
|
||||
if (mode == 0)
|
||||
{
|
||||
rs485.flags &= ~SER_RS485_RTS_ON_SEND;
|
||||
rs485.flags |= SER_RS485_RTS_AFTER_SEND;
|
||||
}
|
||||
else
|
||||
{
|
||||
rs485.flags |= SER_RS485_RTS_ON_SEND;
|
||||
rs485.flags &= ~SER_RS485_RTS_AFTER_SEND;
|
||||
}
|
||||
rs485.delay_rts_before_send = 0;
|
||||
rs485.delay_rts_after_send = 0;
|
||||
if (ioctl(handle->fd, TIOCSRS485, &rs485) == -1)
|
||||
{
|
||||
printf("TIOCSRS485 ioctrl error.\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
1811
src/main.cpp
1811
src/main.cpp
File diff suppressed because it is too large
Load Diff
@ -62,6 +62,8 @@ void *upload_message_controller(void *args);
|
||||
void *heart_beat(void *args); //上传心跳检测
|
||||
void *distortion(void *args); //矫正
|
||||
void *read_serial_thread(void *args); //读取串口传来的红外温度数据
|
||||
void *storage_serial_thread(void *args);
|
||||
|
||||
|
||||
struct Alarm {
|
||||
int ifalarm;
|
||||
|
@ -1,374 +1,374 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
#include <fcntl.h>
|
||||
#include <opencv2/opencv.hpp>
|
||||
#include "yolov5_detect.h"
|
||||
#include "rknn_api.h"
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
|
||||
|
||||
//unsigned char *model;
|
||||
//detection* dets;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static int letter_box(cv::Mat input_image, cv::Mat *output_image, int model_input_size)
|
||||
{
|
||||
int input_width, input_height;
|
||||
|
||||
input_width = input_image.cols;
|
||||
input_height = input_image.rows;
|
||||
float ratio;
|
||||
ratio = min((float)model_input_size / input_width, (float)model_input_size / input_height);
|
||||
|
||||
int new_width, new_height;
|
||||
new_width = round(ratio * input_width );
|
||||
new_height = round(ratio * input_height);
|
||||
|
||||
|
||||
int height_padding = 0;
|
||||
int width_padding = 0;
|
||||
int top = 0;
|
||||
int bottom = 0;
|
||||
int left = 0;
|
||||
int right = 0;
|
||||
if( new_width >= new_height)
|
||||
{
|
||||
height_padding = new_width - new_height;
|
||||
if( (height_padding % 2) == 0 )
|
||||
{
|
||||
top = (int)((float)(height_padding/2));
|
||||
bottom = (int)((float)(height_padding/2));
|
||||
}
|
||||
else
|
||||
{
|
||||
top = (int)((float)(height_padding/2));
|
||||
bottom = (int)((float)(height_padding/2))+1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
width_padding = new_height - new_width;
|
||||
if( (width_padding % 2) == 0 )
|
||||
{
|
||||
left = (int)((float)(width_padding/2));
|
||||
right = (int)((float)(width_padding/2));
|
||||
}
|
||||
else
|
||||
{
|
||||
left = (int)((float)(width_padding/2));
|
||||
right = (int)((float)(width_padding/2))+1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
cv::Mat resize_img;
|
||||
|
||||
cv::resize(input_image, resize_img, cv::Size(new_width, new_height));
|
||||
cv::copyMakeBorder(resize_img, *output_image, top, bottom, left, right, cv::BORDER_CONSTANT, cv::Scalar(0, 0, 0));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int yolov5_detect_init(rknn_context *ctx, const char * path)
|
||||
{
|
||||
int ret;
|
||||
|
||||
// Load model
|
||||
FILE *fp = fopen(path, "rb");
|
||||
if(fp == NULL)
|
||||
{
|
||||
printf("fopen %s fail!\n", path);
|
||||
return -1;
|
||||
}
|
||||
fseek(fp, 0, SEEK_END); //fp指向end,fseek(FILE *stream, long offset, int fromwhere);
|
||||
int model_len = ftell(fp); //相对文件首偏移
|
||||
unsigned char *model_data = (unsigned char*)malloc(model_len);
|
||||
|
||||
fseek(fp, 0, SEEK_SET); //SEEK_SET为文件头
|
||||
if(model_len != fread(model_data, 1, model_len, fp))
|
||||
{
|
||||
printf("fread %s fail!\n", path);
|
||||
free(model_data);
|
||||
return -1;
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
//init
|
||||
ret = rknn_init(ctx, model_data, model_len, RKNN_FLAG_PRIOR_MEDIUM);
|
||||
if(ret < 0)
|
||||
{
|
||||
printf("rknn_init fail! ret=%d\n", ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(model_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int scale_coords(yolov5_detect_result_group_t *detect_result_group, int img_width, int img_height, int model_size)
|
||||
{
|
||||
for (int i = 0; i < detect_result_group->count; i++)
|
||||
{
|
||||
yolov5_detect_result_t *det_result = &(detect_result_group->results[i]);
|
||||
|
||||
|
||||
int x1 = det_result->box.left;
|
||||
int y1 = det_result->box.top;
|
||||
int x2 = det_result->box.right;
|
||||
int y2 = det_result->box.bottom;
|
||||
|
||||
|
||||
if( img_width >= img_height )
|
||||
{
|
||||
int image_max_len = img_width;
|
||||
float gain;
|
||||
gain = (float)model_size / image_max_len;
|
||||
int resized_height = img_height * gain;
|
||||
int height_pading = (model_size - resized_height)/2;
|
||||
y1 = (y1 - height_pading);
|
||||
y2 = (y2 - height_pading);
|
||||
x1 = int(x1 / gain);
|
||||
y1 = int(y1 / gain);
|
||||
x2 = int(x2 / gain);
|
||||
y2 = int(y2 / gain);
|
||||
|
||||
det_result->box.left = x1;
|
||||
det_result->box.top = y1;
|
||||
det_result->box.right = x2;
|
||||
det_result->box.bottom = y2;
|
||||
}
|
||||
else
|
||||
{
|
||||
int image_max_len = img_height;
|
||||
float gain;
|
||||
gain = (float)model_size / image_max_len;
|
||||
int resized_width = img_width * gain;
|
||||
int width_pading = (model_size - resized_width)/2;
|
||||
x1 = (x1 - width_pading);
|
||||
x2 = (x2 - width_pading);
|
||||
x1 = int(x1 / gain);
|
||||
y1 = int(y1 / gain);
|
||||
x2 = int(x2 / gain);
|
||||
y2 = int(y2 / gain);
|
||||
|
||||
det_result->box.left = x1;
|
||||
det_result->box.top = y1;
|
||||
det_result->box.right = x2;
|
||||
det_result->box.bottom = y2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int yolov5_detect_run(rknn_context ctx, cv::Mat input_image, yolov5_detect_result_group_t *detect_result_group)
|
||||
{
|
||||
int img_width = 0;
|
||||
int img_height = 0;
|
||||
int img_channel = 0;
|
||||
|
||||
size_t actual_size = 0;
|
||||
const float vis_threshold = 0.1;
|
||||
const float nms_threshold = 0.5;
|
||||
const float conf_threshold = 0.2;
|
||||
int ret;
|
||||
|
||||
img_width = input_image.cols;
|
||||
img_height = input_image.rows;
|
||||
|
||||
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;
|
||||
}
|
||||
//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", height, width,
|
||||
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;
|
||||
}
|
||||
|
||||
cv::Mat letter_image;
|
||||
letter_box(input_image, &letter_image, input_width);
|
||||
inputs[0].buf = letter_image.data;
|
||||
|
||||
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
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
yolov5_post_process_u8((uint8_t *)outputs[0].buf, (uint8_t *)outputs[1].buf, (uint8_t *)outputs[2].buf, input_height, input_width,
|
||||
conf_threshold, nms_threshold, out_zps, out_scales, detect_result_group);
|
||||
|
||||
|
||||
/*
|
||||
yolov5_post_process_fp((float *)outputs[0].buf, (float *)outputs[1].buf, (float *)outputs[2].buf, input_height, input_width,
|
||||
conf_threshold, nms_threshold, &detect_result_group);
|
||||
*/
|
||||
|
||||
rknn_outputs_release(ctx, io_num.n_output, outputs);
|
||||
|
||||
scale_coords(detect_result_group, img_width, img_height, input_width);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int yolov5_detect_release(rknn_context ctx)
|
||||
{
|
||||
rknn_destroy(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) {
|
||||
std::string ret;
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
unsigned char char_array_3[3];
|
||||
unsigned char char_array_4[4];
|
||||
|
||||
while (in_len--) {
|
||||
char_array_3[i++] = *(bytes_to_encode++);
|
||||
if (i == 3) {
|
||||
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
|
||||
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
|
||||
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
|
||||
char_array_4[3] = char_array_3[2] & 0x3f;
|
||||
|
||||
for(i = 0; (i <4) ; i++)
|
||||
ret += base64_chars[char_array_4[i]];
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (i) {
|
||||
for(j = i; j < 3; j++)
|
||||
char_array_3[j] = '\0';
|
||||
|
||||
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
|
||||
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
|
||||
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
|
||||
char_array_4[3] = char_array_3[2] & 0x3f;
|
||||
|
||||
for (j = 0; (j < i + 1); j++)
|
||||
ret += base64_chars[char_array_4[j]];
|
||||
|
||||
while((i++ < 3))
|
||||
ret += '=';
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline bool is_base64(unsigned char c) {
|
||||
return (isalnum(c) || (c == '+') || (c == '/'));
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
#include <fcntl.h>
|
||||
#include <opencv2/opencv.hpp>
|
||||
#include "yolov5_detect.h"
|
||||
#include "rknn_api.h"
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
|
||||
|
||||
//unsigned char *model;
|
||||
//detection* dets;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static int letter_box(cv::Mat input_image, cv::Mat *output_image, int model_input_size)
|
||||
{
|
||||
int input_width, input_height;
|
||||
|
||||
input_width = input_image.cols;
|
||||
input_height = input_image.rows;
|
||||
float ratio;
|
||||
ratio = min((float)model_input_size / input_width, (float)model_input_size / input_height);
|
||||
|
||||
int new_width, new_height;
|
||||
new_width = round(ratio * input_width );
|
||||
new_height = round(ratio * input_height);
|
||||
|
||||
|
||||
int height_padding = 0;
|
||||
int width_padding = 0;
|
||||
int top = 0;
|
||||
int bottom = 0;
|
||||
int left = 0;
|
||||
int right = 0;
|
||||
if( new_width >= new_height)
|
||||
{
|
||||
height_padding = new_width - new_height;
|
||||
if( (height_padding % 2) == 0 )
|
||||
{
|
||||
top = (int)((float)(height_padding/2));
|
||||
bottom = (int)((float)(height_padding/2));
|
||||
}
|
||||
else
|
||||
{
|
||||
top = (int)((float)(height_padding/2));
|
||||
bottom = (int)((float)(height_padding/2))+1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
width_padding = new_height - new_width;
|
||||
if( (width_padding % 2) == 0 )
|
||||
{
|
||||
left = (int)((float)(width_padding/2));
|
||||
right = (int)((float)(width_padding/2));
|
||||
}
|
||||
else
|
||||
{
|
||||
left = (int)((float)(width_padding/2));
|
||||
right = (int)((float)(width_padding/2))+1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
cv::Mat resize_img;
|
||||
|
||||
cv::resize(input_image, resize_img, cv::Size(new_width, new_height));
|
||||
cv::copyMakeBorder(resize_img, *output_image, top, bottom, left, right, cv::BORDER_CONSTANT, cv::Scalar(0, 0, 0));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int yolov5_detect_init(rknn_context *ctx, const char * path)
|
||||
{
|
||||
int ret;
|
||||
|
||||
// Load model
|
||||
FILE *fp = fopen(path, "rb");
|
||||
if(fp == NULL)
|
||||
{
|
||||
printf("fopen %s fail!\n", path);
|
||||
return -1;
|
||||
}
|
||||
fseek(fp, 0, SEEK_END); //fp指向end,fseek(FILE *stream, long offset, int fromwhere);
|
||||
int model_len = ftell(fp); //相对文件首偏移
|
||||
unsigned char *model_data = (unsigned char*)malloc(model_len);
|
||||
|
||||
fseek(fp, 0, SEEK_SET); //SEEK_SET为文件头
|
||||
if(model_len != fread(model_data, 1, model_len, fp))
|
||||
{
|
||||
printf("fread %s fail!\n", path);
|
||||
free(model_data);
|
||||
return -1;
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
//init
|
||||
ret = rknn_init(ctx, model_data, model_len, RKNN_FLAG_PRIOR_MEDIUM);
|
||||
if(ret < 0)
|
||||
{
|
||||
printf("rknn_init fail! ret=%d\n", ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(model_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int scale_coords(yolov5_detect_result_group_t *detect_result_group, int img_width, int img_height, int model_size)
|
||||
{
|
||||
for (int i = 0; i < detect_result_group->count; i++)
|
||||
{
|
||||
yolov5_detect_result_t *det_result = &(detect_result_group->results[i]);
|
||||
|
||||
|
||||
int x1 = det_result->box.left;
|
||||
int y1 = det_result->box.top;
|
||||
int x2 = det_result->box.right;
|
||||
int y2 = det_result->box.bottom;
|
||||
|
||||
|
||||
if( img_width >= img_height )
|
||||
{
|
||||
int image_max_len = img_width;
|
||||
float gain;
|
||||
gain = (float)model_size / image_max_len;
|
||||
int resized_height = img_height * gain;
|
||||
int height_pading = (model_size - resized_height)/2;
|
||||
y1 = (y1 - height_pading);
|
||||
y2 = (y2 - height_pading);
|
||||
x1 = int(x1 / gain);
|
||||
y1 = int(y1 / gain);
|
||||
x2 = int(x2 / gain);
|
||||
y2 = int(y2 / gain);
|
||||
|
||||
det_result->box.left = x1;
|
||||
det_result->box.top = y1;
|
||||
det_result->box.right = x2;
|
||||
det_result->box.bottom = y2;
|
||||
}
|
||||
else
|
||||
{
|
||||
int image_max_len = img_height;
|
||||
float gain;
|
||||
gain = (float)model_size / image_max_len;
|
||||
int resized_width = img_width * gain;
|
||||
int width_pading = (model_size - resized_width)/2;
|
||||
x1 = (x1 - width_pading);
|
||||
x2 = (x2 - width_pading);
|
||||
x1 = int(x1 / gain);
|
||||
y1 = int(y1 / gain);
|
||||
x2 = int(x2 / gain);
|
||||
y2 = int(y2 / gain);
|
||||
|
||||
det_result->box.left = x1;
|
||||
det_result->box.top = y1;
|
||||
det_result->box.right = x2;
|
||||
det_result->box.bottom = y2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int yolov5_detect_run(rknn_context ctx, cv::Mat input_image, yolov5_detect_result_group_t *detect_result_group)
|
||||
{
|
||||
int img_width = 0;
|
||||
int img_height = 0;
|
||||
int img_channel = 0;
|
||||
|
||||
size_t actual_size = 0;
|
||||
const float vis_threshold = 0.1;
|
||||
const float nms_threshold = 0.5;
|
||||
const float conf_threshold = 0.2;
|
||||
int ret;
|
||||
|
||||
img_width = input_image.cols;
|
||||
img_height = input_image.rows;
|
||||
|
||||
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;
|
||||
}
|
||||
//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", height, width,
|
||||
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;
|
||||
}
|
||||
|
||||
cv::Mat letter_image;
|
||||
letter_box(input_image, &letter_image, input_width);
|
||||
inputs[0].buf = letter_image.data;
|
||||
|
||||
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
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
yolov5_post_process_u8((uint8_t *)outputs[0].buf, (uint8_t *)outputs[1].buf, (uint8_t *)outputs[2].buf, input_height, input_width,
|
||||
conf_threshold, nms_threshold, out_zps, out_scales, detect_result_group);
|
||||
|
||||
|
||||
/*
|
||||
yolov5_post_process_fp((float *)outputs[0].buf, (float *)outputs[1].buf, (float *)outputs[2].buf, input_height, input_width,
|
||||
conf_threshold, nms_threshold, &detect_result_group);
|
||||
*/
|
||||
|
||||
rknn_outputs_release(ctx, io_num.n_output, outputs);
|
||||
|
||||
scale_coords(detect_result_group, img_width, img_height, input_width);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int yolov5_detect_release(rknn_context ctx)
|
||||
{
|
||||
rknn_destroy(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) {
|
||||
std::string ret;
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
unsigned char char_array_3[3];
|
||||
unsigned char char_array_4[4];
|
||||
|
||||
while (in_len--) {
|
||||
char_array_3[i++] = *(bytes_to_encode++);
|
||||
if (i == 3) {
|
||||
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
|
||||
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
|
||||
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
|
||||
char_array_4[3] = char_array_3[2] & 0x3f;
|
||||
|
||||
for(i = 0; (i <4) ; i++)
|
||||
ret += base64_chars[char_array_4[i]];
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (i) {
|
||||
for(j = i; j < 3; j++)
|
||||
char_array_3[j] = '\0';
|
||||
|
||||
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
|
||||
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
|
||||
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
|
||||
char_array_4[3] = char_array_3[2] & 0x3f;
|
||||
|
||||
for (j = 0; (j < i + 1); j++)
|
||||
ret += base64_chars[char_array_4[j]];
|
||||
|
||||
while((i++ < 3))
|
||||
ret += '=';
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline bool is_base64(unsigned char c) {
|
||||
return (isalnum(c) || (c == '+') || (c == '/'));
|
||||
}
|
@ -23,6 +23,7 @@
|
||||
|
||||
|
||||
static char labels[YOLOV5_CLASS_NUM][30] = {"0", "1"};
|
||||
// static char labels[YOLOV5_CLASS_NUM][30] = {"fire"};
|
||||
|
||||
const int anchor0[6] = {10, 13, 16, 30, 33, 23};
|
||||
const int anchor1[6] = {30, 61, 62, 45, 59, 119};
|
||||
|
1175
src/yuanbenmain.cpp
1175
src/yuanbenmain.cpp
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user