[clean] code

This commit is contained in:
dianjixz
2024-11-22 16:17:23 +08:00
parent a02304cba2
commit a4ab2ace0f
20 changed files with 125 additions and 5316 deletions
@@ -23,7 +23,7 @@ LINK_SEARCH_PATH += [ADir('../static_lib')]
REQUIREMENTS += ['ax_engine', 'ax_interpreter', 'ax_sys']
REQUIREMENTS += ['onnxruntime', 'samplerate']
INCLUDE += [ADir('../include')]
INCLUDE += [ADir('src/runner'), ADir('../include/onnxruntime/core/session')]
STATIC_FILES += [AFile('melotts_zh-cn.json')]
+1 -2
View File
@@ -21,8 +21,7 @@ LDFLAGS+=['-Wl,-rpath=/opt/m5stack/lib', '-Wl,-rpath=/usr/local/m5stack/lib', '-
LINK_SEARCH_PATH += [ADir('../static_lib')]
REQUIREMENTS += ['ax_engine', 'ax_interpreter', 'ax_sys']
INCLUDE += [ADir('src/runner')]
INCLUDE += [ADir('../include/opencv4')]
INCLUDE += [ADir('../include'), ADir('../include/opencv4')]
static_file = Glob('../static_lib/module-llm/libabsl_*')
static_file = Glob('../static_lib/libopencv-4.6-aarch64-none/lib/lib*')
@@ -7,24 +7,27 @@
* written consent of Axera Semiconductor (Ningbo) Co., Ltd.
*
**************************************************************************************************/
#include "detection.hpp"
#define UNUSE_STRUCT_OBJECT
#include "EngineWrapper.hpp"
#include "utils/io.hpp"
#include <cstdlib>
#include "base/detection.hpp"
static const char *strAlgoModelType[AX_ENGINE_VIRTUAL_NPU_BUTT] = {"1.6T", "3.2T"};
static const char* strAlgoModelType[AX_ENGINE_VIRTUAL_NPU_BUTT] = {"1.6T", "3.2T"};
/// @brief npu type
typedef enum axNPU_TYPE_E {
AX_NPU_DEFAULT = 0, /* running under default NPU according to system */
AX_STD_VNPU_1 = (1 << 0), /* running under STD VNPU1 */
AX_STD_VNPU_2 = (1 << 1), /* running under STD VNPU2 */
AX_STD_VNPU_3 = (1 << 2), /* running under STD VNPU3 */
AX_BL_VNPU_1 = (1 << 3), /* running under BIG-LITTLE VNPU1 */
AX_BL_VNPU_2 = (1 << 4) /* running under BIG-LITTLE VNPU2 */
AX_STD_VNPU_1 = (1 << 0), /* running under STD VNPU1 */
AX_STD_VNPU_2 = (1 << 1), /* running under STD VNPU2 */
AX_STD_VNPU_3 = (1 << 2), /* running under STD VNPU3 */
AX_BL_VNPU_1 = (1 << 3), /* running under BIG-LITTLE VNPU1 */
AX_BL_VNPU_2 = (1 << 4) /* running under BIG-LITTLE VNPU2 */
} AX_NPU_TYPE_E;
static AX_S32 CheckModelVNpu(const std::string &strModel, const AX_ENGINE_MODEL_TYPE_T &eModelType, const AX_S32 &nNpuType, AX_U32 &nNpuSet) {
static AX_S32 CheckModelVNpu(const std::string& strModel, const AX_ENGINE_MODEL_TYPE_T& eModelType,
const AX_S32& nNpuType, AX_U32& nNpuSet)
{
AX_ENGINE_NPU_ATTR_T stNpuAttr;
memset(&stNpuAttr, 0x00, sizeof(stNpuAttr));
@@ -32,29 +35,27 @@ static AX_S32 CheckModelVNpu(const std::string &strModel, const AX_ENGINE_MODEL_
if (ret == 0) {
// VNPU DISABLE
if (stNpuAttr.eHardMode == AX_ENGINE_VIRTUAL_NPU_DISABLE) {
nNpuSet = 0x01; // NON-VNPU (0b111)
nNpuSet = 0x01; // NON-VNPU (0b111)
}
// STD VNPU
else if (stNpuAttr.eHardMode == AX_ENGINE_VIRTUAL_NPU_BUTT) {
// 7.2T & 10.8T no allow
if (eModelType == AX_ENGINE_MODEL_TYPE1
|| eModelType == AX_ENGINE_MODEL_TYPE1) {
if (eModelType == AX_ENGINE_MODEL_TYPE1 || eModelType == AX_ENGINE_MODEL_TYPE1) {
return -1;
}
// default STD VNPU2
if (nNpuType == 0) {
nNpuSet = 0x02; // VNPU2 (0b010)
}
else {
nNpuSet = 0x02; // VNPU2 (0b010)
} else {
if (nNpuType & AX_STD_VNPU_1) {
nNpuSet |= 0x01; // VNPU1 (0b001)
nNpuSet |= 0x01; // VNPU1 (0b001)
}
if (nNpuType & AX_STD_VNPU_2) {
nNpuSet |= 0x02; // VNPU2 (0b010)
nNpuSet |= 0x02; // VNPU2 (0b010)
}
if (nNpuType & AX_STD_VNPU_3) {
nNpuSet |= 0x04; // VNPU3 (0b100)
nNpuSet |= 0x04; // VNPU3 (0b100)
}
}
}
@@ -69,14 +70,13 @@ static AX_S32 CheckModelVNpu(const std::string &strModel, const AX_ENGINE_MODEL_
if (nNpuType == 0) {
// 7.2T default BL VNPU1
if (eModelType == AX_ENGINE_MODEL_TYPE1) {
nNpuSet = 0x01; // VNPU1 (0b001)
nNpuSet = 0x01; // VNPU1 (0b001)
}
// 3.6T default BL VNPU2
else {
nNpuSet = 0x02; // VNPU2 (0b010)
nNpuSet = 0x02; // VNPU2 (0b010)
}
}
else {
} else {
// 7.2T
if (eModelType == AX_ENGINE_MODEL_TYPE1) {
// no allow set to BL VNPU2
@@ -84,22 +84,21 @@ static AX_S32 CheckModelVNpu(const std::string &strModel, const AX_ENGINE_MODEL_
return -1;
}
if (nNpuType & AX_BL_VNPU_1) {
nNpuSet |= 0x01; // VNPU1 (0b001)
nNpuSet |= 0x01; // VNPU1 (0b001)
}
}
// 3.6T
else {
if (nNpuType & AX_BL_VNPU_1) {
nNpuSet |= 0x01; // VNPU1 (0b001)
nNpuSet |= 0x01; // VNPU1 (0b001)
}
if (nNpuType & AX_BL_VNPU_2) {
nNpuSet |= 0x02; // VNPU2 (0b010)
nNpuSet |= 0x02; // VNPU2 (0b010)
}
}
}
}
}
else {
} else {
printf("AX_ENGINE_GetVNPUAttr fail ret = %x\n", ret);
}
@@ -111,27 +110,26 @@ int EngineWrapper::Init(const char* strModelPath, uint32_t nNpuType)
AX_S32 ret = 0;
// 1. load model
AX_BOOL bLoadModelUseCmm = AX_FALSE;
AX_CHAR *pModelBufferVirAddr = nullptr;
AX_BOOL bLoadModelUseCmm = AX_FALSE;
AX_CHAR* pModelBufferVirAddr = nullptr;
AX_U64 u64ModelBufferPhyAddr = 0;
AX_U32 nModelBufferSize = 0;
AX_U32 nModelBufferSize = 0;
std::vector<char> model_buffer;
if (bLoadModelUseCmm) {
if (!utils::read_file(strModelPath, (AX_VOID **)&pModelBufferVirAddr, u64ModelBufferPhyAddr, nModelBufferSize)) {
if (!utils::read_file(strModelPath, (AX_VOID**)&pModelBufferVirAddr, u64ModelBufferPhyAddr, nModelBufferSize)) {
printf("ALGO read model(%s) fail\n", strModelPath);
return -1;
}
}
else {
} else {
if (!utils::read_file(strModelPath, model_buffer)) {
printf("ALGO read model(%s) fail\n", strModelPath);
return -1;
}
pModelBufferVirAddr = model_buffer.data();
nModelBufferSize = model_buffer.size();
nModelBufferSize = model_buffer.size();
}
auto freeModelBuffer = [&]() {
@@ -139,35 +137,34 @@ int EngineWrapper::Init(const char* strModelPath, uint32_t nNpuType)
if (u64ModelBufferPhyAddr != 0) {
AX_SYS_MemFree(u64ModelBufferPhyAddr, &pModelBufferVirAddr);
}
}
else {
} else {
std::vector<char>().swap(model_buffer);
}
return;
};
// 1.1 Get Model Type
AX_ENGINE_MODEL_TYPE_T eModelType = AX_ENGINE_MODEL_TYPE0;
ret = AX_ENGINE_GetModelType(pModelBufferVirAddr, nModelBufferSize, &eModelType);
if (0 != ret || eModelType >= AX_ENGINE_MODEL_TYPE_BUTT) {
printf("%s AX_ENGINE_GetModelType fail ret=%x, eModelType=%d\n", strModelPath, eModelType);
freeModelBuffer();
return -1;
}
AX_ENGINE_MODEL_TYPE_T eModelType = AX_ENGINE_MODEL_TYPE0;
ret = AX_ENGINE_GetModelType(pModelBufferVirAddr, nModelBufferSize, &eModelType);
if (0 != ret || eModelType >= AX_ENGINE_MODEL_TYPE_BUTT) {
printf("%s AX_ENGINE_GetModelType fail ret=%x, eModelType=%d\n", strModelPath, eModelType);
freeModelBuffer();
return -1;
}
// 1.2 Check VNPU
AX_ENGINE_NPU_SET_T nNpuSet = 0;
ret = CheckModelVNpu(strModelPath, eModelType, nNpuType, nNpuSet);
if (0 != ret) {
printf("ALGO CheckModelVNpu fail\n");
freeModelBuffer();
return -1;
}
AX_ENGINE_NPU_SET_T nNpuSet = 0;
ret = CheckModelVNpu(strModelPath, eModelType, nNpuType, nNpuSet);
if (0 != ret) {
printf("ALGO CheckModelVNpu fail\n");
freeModelBuffer();
return -1;
}
// 2. create handle
AX_ENGINE_HANDLE handle = nullptr;
ret = AX_ENGINE_CreateHandle(&handle, pModelBufferVirAddr, nModelBufferSize);
auto deinit_handle = [&handle]() {
ret = AX_ENGINE_CreateHandle(&handle, pModelBufferVirAddr, nModelBufferSize);
auto deinit_handle = [&handle]() {
if (handle) {
AX_ENGINE_DestroyHandle(handle);
}
@@ -190,26 +187,26 @@ int EngineWrapper::Init(const char* strModelPath, uint32_t nNpuType)
// 4. set io
m_io_info = nullptr;
ret = AX_ENGINE_GetIOInfo(handle, &m_io_info);
ret = AX_ENGINE_GetIOInfo(handle, &m_io_info);
if (0 != ret) {
return deinit_handle();
}
m_input_num = m_io_info->nInputSize;
m_input_num = m_io_info->nInputSize;
m_output_num = m_io_info->nOutputSize;
// 4.1 query io
// AX_IMG_FORMAT_E eDtype;
// ret = utils::query_model_input_size(m_io_info, m_input_size, eDtype);//FIXME.
// if (0 != ret) {
// printf("model(%s) query model input size fail\n", strModelPath.c_str());
// return deinit_handle();
// }
// AX_IMG_FORMAT_E eDtype;
// ret = utils::query_model_input_size(m_io_info, m_input_size, eDtype);//FIXME.
// if (0 != ret) {
// printf("model(%s) query model input size fail\n", strModelPath.c_str());
// return deinit_handle();
// }
// if (!(eDtype == AX_FORMAT_YUV420_SEMIPLANAR || eDtype == AX_FORMAT_YUV420_SEMIPLANAR_VU ||
// eDtype == AX_FORMAT_RGB888 || eDtype == AX_FORMAT_BGR888)) {
// printf("model(%s) data type is: 0x%02X, unsupport\n", strModelPath, eDtype);
// return deinit_handle();
// }
// if (!(eDtype == AX_FORMAT_YUV420_SEMIPLANAR || eDtype == AX_FORMAT_YUV420_SEMIPLANAR_VU ||
// eDtype == AX_FORMAT_RGB888 || eDtype == AX_FORMAT_BGR888)) {
// printf("model(%s) data type is: 0x%02X, unsupport\n", strModelPath, eDtype);
// return deinit_handle();
// }
// 4.2 brief io
#ifdef __DEBUG__
@@ -217,9 +214,9 @@ int EngineWrapper::Init(const char* strModelPath, uint32_t nNpuType)
utils::brief_io_info(strModelPath, m_io_info);
#endif
//5. Config VNPU
// printf("model(%s) nNpuSet: 0x%08X\n", strModelPath.c_str(), nNpuSet);
// will do nothing for using create handle v2 api
// 5. Config VNPU
// printf("model(%s) nNpuSet: 0x%08X\n", strModelPath.c_str(), nNpuSet);
// will do nothing for using create handle v2 api
// 6. prepare io
// AX_U32 nIoDepth = (stCtx.vecOutputBufferFlag.size() == 0) ? 1 : stCtx.vecOutputBufferFlag.size();
@@ -230,20 +227,20 @@ int EngineWrapper::Init(const char* strModelPath, uint32_t nNpuType)
return deinit_handle();
}
m_handle = handle;
m_handle = handle;
m_hasInit = true;
return 0;
}
int EngineWrapper::SetInput(void* pInput, int index) {
int EngineWrapper::SetInput(void* pInput, int index)
{
return utils::push_io_input(pInput, index, m_io);
}
int EngineWrapper::RunSync()
{
if (!m_hasInit)
return -1;
if (!m_hasInit) return -1;
// 7.3 run & benchmark
auto ret = AX_ENGINE_RunSync(m_handle, &m_io);
@@ -256,25 +253,29 @@ int EngineWrapper::RunSync()
}
const char* CLASS_NAMES[] = {
"person", "bicycle", "car", "motorcycle", "airplane", "bus", "train", "truck", "boat", "traffic light",
"fire hydrant", "stop sign", "parking meter", "bench", "bird", "cat", "dog", "horse", "sheep", "cow",
"elephant", "bear", "zebra", "giraffe", "backpack", "umbrella", "handbag", "tie", "suitcase", "frisbee",
"skis", "snowboard", "sports ball", "kite", "baseball bat", "baseball glove", "skateboard", "surfboard",
"tennis racket", "bottle", "wine glass", "cup", "fork", "knife", "spoon", "bowl", "banana", "apple",
"sandwich", "orange", "broccoli", "carrot", "hot dog", "pizza", "donut", "cake", "chair", "couch",
"potted plant", "bed", "dining table", "toilet", "tv", "laptop", "mouse", "remote", "keyboard", "cell phone",
"microwave", "oven", "toaster", "sink", "refrigerator", "book", "clock", "vase", "scissors", "teddy bear",
"hair drier", "toothbrush"};
"person", "bicycle", "car", "motorcycle", "airplane", "bus", "train",
"truck", "boat", "traffic light", "fire hydrant", "stop sign", "parking meter", "bench",
"bird", "cat", "dog", "horse", "sheep", "cow", "elephant",
"bear", "zebra", "giraffe", "backpack", "umbrella", "handbag", "tie",
"suitcase", "frisbee", "skis", "snowboard", "sports ball", "kite", "baseball bat",
"baseball glove", "skateboard", "surfboard", "tennis racket", "bottle", "wine glass", "cup",
"fork", "knife", "spoon", "bowl", "banana", "apple", "sandwich",
"orange", "broccoli", "carrot", "hot dog", "pizza", "donut", "cake",
"chair", "couch", "potted plant", "bed", "dining table", "toilet", "tv",
"laptop", "mouse", "remote", "keyboard", "cell phone", "microwave", "oven",
"toaster", "sink", "refrigerator", "book", "clock", "vase", "scissors",
"teddy bear", "hair drier", "toothbrush"};
void post_process(AX_ENGINE_IO_INFO_T* io_info, AX_ENGINE_IO_T* io_data, const cv::Mat& mat, int& input_w, int& input_h, int& cls_num, float& prob_threshold, float& nms_threshold, std::vector<detection::Object>& objects)
void post_process(AX_ENGINE_IO_INFO_T* io_info, AX_ENGINE_IO_T* io_data, const cv::Mat& mat, int& input_w, int& input_h,
int& cls_num, float& prob_threshold, float& nms_threshold, std::vector<detection::Object>& objects)
{
// std::vector<detection::Object> objects;
std::vector<detection::Object> proposals;
for (int i = 0; i < 3; ++i)
{
auto feat_ptr = (float*)io_data->pOutputs[i].pVirAddr;
for (int i = 0; i < 3; ++i) {
auto feat_ptr = (float*)io_data->pOutputs[i].pVirAddr;
int32_t stride = (1 << i) * 8;
detection::generate_proposals_yolov8_native(stride, feat_ptr, prob_threshold, proposals, input_w, input_h, cls_num);
detection::generate_proposals_yolov8_native(stride, feat_ptr, prob_threshold, proposals, input_w, input_h,
cls_num);
}
detection::get_out_bbox(proposals, objects, nms_threshold, input_h, input_w, mat.rows, mat.cols);
fprintf(stdout, "detection num: %zu\n", objects.size());
@@ -282,21 +283,25 @@ void post_process(AX_ENGINE_IO_INFO_T* io_info, AX_ENGINE_IO_T* io_data, const c
detection::draw_objects(mat, objects, CLASS_NAMES, "yolo11_out");
}
int EngineWrapper::Post_Process(cv::Mat& mat, int& input_w, int& input_, int& cls_num, float& pron_threshold, float& nms_threshold, std::vector<detection::Object>& objects)
int EngineWrapper::Post_Process(cv::Mat& mat, int& input_w, int& input_, int& cls_num, float& pron_threshold,
float& nms_threshold, std::vector<detection::Object>& objects)
{
post_process(m_io_info, &m_io, mat, input_w, input_, cls_num, pron_threshold, nms_threshold, objects);
return 0;
}
int EngineWrapper::GetOutput(void* pOutput, int index) {
int EngineWrapper::GetOutput(void* pOutput, int index)
{
return utils::push_io_output(pOutput, index, m_io);
}
int EngineWrapper::GetInputSize(int index) {
int EngineWrapper::GetInputSize(int index)
{
return m_io.pInputs[index].nSize;
}
int EngineWrapper::GetOutputSize(int index) {
int EngineWrapper::GetOutputSize(int index)
{
return m_io.pOutputs[index].nSize;
}
@@ -12,16 +12,34 @@
#include <cstdint>
#include <opencv2/opencv.hpp>
#include <base/detection.h>
#include "ax_engine_api.h"
#ifndef UNUSE_STRUCT_OBJECT
namespace detection {
typedef struct Object {
cv::Rect_<float> rect;
int label;
float prob;
cv::Point2f landmark[5];
/* for yolov5-seg */
cv::Mat mask;
std::vector<float> mask_feat;
std::vector<float> kps_feat;
/* for yolov8-obb */
float angle;
} Object;
} // namespace detection
#endif
class EngineWrapper {
public:
EngineWrapper() :
m_hasInit(false),
m_handle(nullptr) {}
EngineWrapper() : m_hasInit(false), m_handle(nullptr)
{
}
~EngineWrapper() {
~EngineWrapper()
{
Release();
}
@@ -31,7 +49,8 @@ public:
int RunSync();
int Post_Process(cv::Mat& mat, int& input_w, int& input_, int& cls_num, float& pron_threshold, float& nms_threshold, std::vector<detection::Object>& objects);
int Post_Process(cv::Mat& mat, int& input_w, int& input_, int& cls_num, float& pron_threshold, float& nms_threshold,
std::vector<detection::Object>& objects);
int GetOutput(void* pOutput, int index);
@@ -43,7 +62,7 @@ public:
protected:
bool m_hasInit;
AX_ENGINE_HANDLE m_handle;
AX_ENGINE_IO_INFO_T *m_io_info{};
AX_ENGINE_IO_INFO_T* m_io_info{};
AX_ENGINE_IO_T m_io{};
int m_input_num{}, m_output_num{};
};
};
@@ -5,8 +5,7 @@
*/
#include "StackFlow.h"
#include "EngineWrapper.hpp"
#include "base/common.hpp"
#include "base/detection.h"
#include "common.hpp"
#include <ax_sys_api.h>
#include <sys/stat.h>
#include <fstream>
@@ -153,7 +152,7 @@ public:
}
std::vector<detection::Object> objects;
yolo_->Post_Process(src, mode_config_.img_w, mode_config_.img_h, mode_config_.cls_num,
mode_config_.pron_threshold, mode_config_.nms_threshold, objects);
mode_config_.pron_threshold, mode_config_.nms_threshold, objects);
std::vector<nlohmann::json> yolo_output;
for (size_t i = 0; i < objects.size(); i++) {
const detection::Object &obj = objects[i];
@@ -1,151 +0,0 @@
/*
* AXERA is pleased to support the open source community by making ax-samples available.
*
* Copyright (c) 2022, AXERA Semiconductor (Shanghai) Co., Ltd. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* 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.
*/
/*
* Author: ls.wang
*/
#pragma once
#include <cstdint>
#include <opencv2/opencv.hpp>
#include <vector>
#include <algorithm>
#include <cmath>
#include <string>
namespace common
{
// opencv mat(h, w)
// resize cv::Size(dstw, dsth)
void get_input_data_no_letterbox(const cv::Mat& mat, std::vector<uint8_t>& image, int model_h, int model_w, bool bgr2rgb = false)
{
cv::Mat img_new(model_h, model_w, CV_8UC3, image.data());
cv::resize(mat, img_new, cv::Size(model_w, model_h));
if (bgr2rgb)
{
cv::cvtColor(img_new, img_new, cv::COLOR_BGR2RGB);
}
}
void get_input_data_letterbox(cv::Mat mat, std::vector<uint8_t>& image, int letterbox_rows, int letterbox_cols, bool bgr2rgb = false)
{
/* letterbox process to support different letterbox size */
float scale_letterbox;
int resize_rows;
int resize_cols;
if ((letterbox_rows * 1.0 / mat.rows) < (letterbox_cols * 1.0 / mat.cols))
{
scale_letterbox = (float)letterbox_rows * 1.0f / (float)mat.rows;
}
else
{
scale_letterbox = (float)letterbox_cols * 1.0f / (float)mat.cols;
}
resize_cols = int(scale_letterbox * (float)mat.cols);
resize_rows = int(scale_letterbox * (float)mat.rows);
cv::Mat img_new(letterbox_rows, letterbox_cols, CV_8UC3, image.data());
cv::resize(mat, mat, cv::Size(resize_cols, resize_rows));
int top = (letterbox_rows - resize_rows) / 2;
int bot = (letterbox_rows - resize_rows + 1) / 2;
int left = (letterbox_cols - resize_cols) / 2;
int right = (letterbox_cols - resize_cols + 1) / 2;
// Letterbox filling
cv::copyMakeBorder(mat, img_new, top, bot, left, right, cv::BORDER_CONSTANT, cv::Scalar(0, 0, 0));
if (bgr2rgb)
{
cv::cvtColor(img_new, img_new, cv::COLOR_BGR2RGB);
}
}
void get_input_data_centercrop(cv::Mat mat, std::vector<uint8_t>& image, int model_h, int model_w, bool bgr2rgb = false)
{
/* letterbox process to support different letterbox size */
/* C2C BGR */
if (mat.channels() == 4)
{
cv::cvtColor(mat, mat, cv::COLOR_BGRA2BGR);
}
if (mat.channels() == 1)
{
cv::cvtColor(mat, mat, cv::COLOR_GRAY2BGR);
}
/* Center */
int h0;
int w0;
if (mat.rows < mat.cols)
{
h0 = 256;
w0 = int(mat.cols * (256.0 / mat.rows));
}
else
{
h0 = int(mat.rows * (256.0 / mat.cols));
w0 = 256;
}
int center_h = int(h0 / 2);
int center_w = int(w0 / 2);
cv::resize(mat, mat, cv::Size(w0, h0));
// cv::imwrite("center.jpg", mat);
/* Crop */
cv::Rect crop_box(center_w - int(model_w / 2), center_h - int(model_h / 2), model_w, model_h);
cv::Mat img_new(model_h, model_w, CV_8UC3, image.data());
cv::Mat mat_crop = mat(crop_box).clone();
// cv::imwrite("mat_crop.jpg", mat_crop);
mat_crop.copyTo(img_new);
// cv::imwrite("img_new.jpg", img_new);
/* SwapRB*/
if (bgr2rgb)
{
cv::cvtColor(img_new, img_new, cv::COLOR_BGR2RGB);
}
}
bool read_file(const char* fn, std::vector<uchar>& data)
{
FILE* fp = fopen(fn, "r");
if (fp != nullptr)
{
fseek(fp, 0L, SEEK_END);
auto len = ftell(fp);
fseek(fp, 0, SEEK_SET);
data.clear();
size_t read_size = 0;
if (len > 0)
{
data.resize(len);
read_size = fread(data.data(), 1, len, fp);
}
fclose(fp);
return read_size == (size_t)len;
}
return false;
}
} // namespace common
@@ -1,22 +0,0 @@
#pragma once
#include <opencv2/opencv.hpp>
namespace detection
{
typedef struct Object
{
cv::Rect_<float> rect;
int label;
float prob;
cv::Point2f landmark[5];
/* for yolov5-seg */
cv::Mat mask;
std::vector<float> mask_feat;
std::vector<float> kps_feat;
/* for yolov8-obb */
float angle;
} Object;
}
File diff suppressed because it is too large Load Diff
@@ -1,432 +0,0 @@
/*
* AXERA is pleased to support the open source community by making ax-samples available.
*
* Copyright (c) 2022, AXERA Semiconductor (Shanghai) Co., Ltd. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* 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.
*/
/*
* Author: hebing
*/
#pragma once
#include <cstdint>
#include <opencv2/opencv.hpp>
#include <vector>
#include <algorithm>
#include <cmath>
#include <string>
#include <iostream>
namespace pose
{
typedef struct
{
float x;
float y;
float score;
} ai_point_t;
struct skeleton
{
int connection[2];
int left_right_neutral;
};
std::vector<skeleton> pairs = {{15, 13, 0},
{13, 11, 0},
{16, 14, 0},
{14, 12, 0},
{11, 12, 0},
{5, 11, 0},
{6, 12, 0},
{5, 6, 0},
{5, 7, 0},
{6, 8, 0},
{7, 9, 0},
{8, 10, 0},
{1, 2, 0},
{0, 1, 0},
{0, 2, 0},
{1, 3, 0},
{2, 4, 0},
{0, 5, 0},
{0, 6, 0}};
std::vector<skeleton> hand_pairs = {{0, 1, 0},
{1, 2, 0},
{2, 3, 0},
{3, 4, 0},
{0, 5, 1},
{5, 6, 1},
{6, 7, 1},
{7, 8, 1},
{0, 9, 2},
{9, 10, 2},
{10, 11, 2},
{11, 12, 2},
{0, 13, 3},
{13, 14, 3},
{14, 15, 3},
{15, 16, 3},
{0, 17, 4},
{17, 18, 4},
{18, 19, 4},
{19, 20, 4}};
std::vector<skeleton> animal_pairs = {{19, 15, 0},
{18, 14, 0},
{17, 13, 0},
{16, 12, 0},
{15, 11, 0},
{14, 10, 0},
{13, 9, 0},
{12, 8, 0},
{11, 6, 0},
{10, 6, 0},
{9, 7, 0},
{8, 7, 0},
{6, 7, 0},
{7, 5, 0},
{5, 4, 0},
{0, 2, 0},
{1, 3, 0},
{0, 1, 0},
{0, 4, 0},
{1, 4, 0}};
typedef struct ai_body_parts_s
{
std::vector<ai_point_t> keypoints;
int32_t img_width = 0;
int32_t img_heigh = 0;
uint64_t timestamp = 0;
} ai_body_parts_s;
typedef struct ai_hand_parts_s
{
std::vector<ai_point_t> keypoints;
int32_t hand_side = 0; //0-left hand,1-right hand
int32_t img_width = 0;
int32_t img_heigh = 0;
uint64_t timestamp = 0;
} ai_hand_parts_s;
typedef struct ai_animal_parts_s
{
std::vector<ai_point_t> keypoints;
int32_t img_width = 0;
int32_t img_heigh = 0;
uint64_t timestamp = 0;
} ai_animal_parts_s;
static inline void find_max_2d(float* buf, int width, int height, int* max_idx_width, int* max_idx_height, float* max_value, int c)
{
float* ptr = buf;
*max_value = -10.f;
*max_idx_width = 0;
*max_idx_height = 0;
for (int h = 0; h < height; h++)
{
for (int w = 0; w < width; w++)
{
float score = ptr[c * height * width + h * width + w];
if (score > *max_value)
{
*max_value = score;
*max_idx_height = h;
*max_idx_width = w;
}
}
}
}
static inline void draw_result(cv::Mat img, ai_body_parts_s& pose, int joints_num, int model_w, int model_h)
{
for (int i = 0; i < joints_num; i++)
{
int x = (int)(pose.keypoints[i].x * img.cols);
int y = (int)(pose.keypoints[i].y * img.rows);
x = std::max(std::min(x, (img.cols - 1)), 0);
y = std::max(std::min(y, (img.rows - 1)), 0);
cv::circle(img, cv::Point(x, y), 4, cv::Scalar(0, 255, 0), cv::FILLED);
}
cv::Scalar color;
cv::Point pt1;
cv::Point pt2;
for (auto& element : pairs)
{
switch (element.left_right_neutral)
{
case 0:
color = cv::Scalar(255, 0, 0);
break;
case 1:
color = cv::Scalar(0, 0, 255);
break;
default:
color = cv::Scalar(0, 255, 0);
}
int x1 = (int)(pose.keypoints[element.connection[0]].x * img.cols);
int y1 = (int)(pose.keypoints[element.connection[0]].y * img.rows);
int x2 = (int)(pose.keypoints[element.connection[1]].x * img.cols);
int y2 = (int)(pose.keypoints[element.connection[1]].y * img.rows);
x1 = std::max(std::min(x1, (img.cols - 1)), 0);
y1 = std::max(std::min(y1, (img.rows - 1)), 0);
x2 = std::max(std::min(x2, (img.cols - 1)), 0);
y2 = std::max(std::min(y2, (img.rows - 1)), 0);
pt1 = cv::Point(x1, y1);
pt2 = cv::Point(x2, y2);
cv::line(img, pt1, pt2, color, 2);
}
}
static inline void draw_animal_result(cv::Mat img, ai_animal_parts_s& pose, int joints_num, int model_w, int model_h)
{
for (int i = 0; i < joints_num; i++)
{
int x = (int)(pose.keypoints[i].x * img.cols);
int y = (int)(pose.keypoints[i].y * img.rows);
x = std::max(std::min(x, (img.cols - 1)), 0);
y = std::max(std::min(y, (img.rows - 1)), 0);
cv::circle(img, cv::Point(x, y), 4, cv::Scalar(0, 255, 0), cv::FILLED);
}
cv::Scalar color;
cv::Point pt1;
cv::Point pt2;
for (auto& element : animal_pairs)
{
switch (element.left_right_neutral)
{
case 0:
color = cv::Scalar(255, 0, 0);
break;
case 1:
color = cv::Scalar(0, 0, 255);
break;
default:
color = cv::Scalar(0, 255, 0);
}
int x1 = (int)(pose.keypoints[element.connection[0]].x * img.cols);
int y1 = (int)(pose.keypoints[element.connection[0]].y * img.rows);
int x2 = (int)(pose.keypoints[element.connection[1]].x * img.cols);
int y2 = (int)(pose.keypoints[element.connection[1]].y * img.rows);
x1 = std::max(std::min(x1, (img.cols - 1)), 0);
y1 = std::max(std::min(y1, (img.rows - 1)), 0);
x2 = std::max(std::min(x2, (img.cols - 1)), 0);
y2 = std::max(std::min(y2, (img.rows - 1)), 0);
pt1 = cv::Point(x1, y1);
pt2 = cv::Point(x2, y2);
cv::line(img, pt1, pt2, color, 2);
}
}
static inline void draw_result(cv::Mat img, ai_body_parts_s& pose, int joints_num, int model_w, int model_h, const detection::Object& obj)
{
for (int i = 0; i < joints_num; i++)
{
int x = (int)(pose.keypoints[i].x);
int y = (int)(pose.keypoints[i].y);
x = std::max(std::min(x, (img.cols - 1)), 0);
y = std::max(std::min(y, (img.rows - 1)), 0);
cv::circle(img, cv::Point(x, y), 4, cv::Scalar(0, 255, 0), cv::FILLED);
}
cv::Scalar color;
cv::Point pt1;
cv::Point pt2;
for (auto& element : pairs)
{
switch (element.left_right_neutral)
{
case 0:
color = cv::Scalar(255, 0, 0);
break;
case 1:
color = cv::Scalar(0, 0, 255);
break;
default:
color = cv::Scalar(0, 255, 0);
}
int x1 = (int)(pose.keypoints[element.connection[0]].x);
int y1 = (int)(pose.keypoints[element.connection[0]].y);
int x2 = (int)(pose.keypoints[element.connection[1]].x);
int y2 = (int)(pose.keypoints[element.connection[1]].y);
x1 = std::max(std::min(x1, (img.cols - 1)), 0);
y1 = std::max(std::min(y1, (img.rows - 1)), 0);
x2 = std::max(std::min(x2, (img.cols - 1)), 0);
y2 = std::max(std::min(y2, (img.rows - 1)), 0);
pt1 = cv::Point(x1, y1);
pt2 = cv::Point(x2, y2);
cv::line(img, pt1, pt2, color, 2);
}
// 画框
cv::rectangle(img, obj.rect, cv::Scalar(255, 0, 0));
char text[256];
sprintf(text, "%s %.1f%%", "person", obj.prob * 100);
int baseLine = 0;
cv::Size label_size = cv::getTextSize(text, cv::FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);
int x = obj.rect.x;
int y = obj.rect.y - label_size.height - baseLine;
if (y < 0)
y = 0;
if (x + label_size.width > img.cols)
x = img.cols - label_size.width;
cv::rectangle(img, cv::Rect(cv::Point(x, y), cv::Size(label_size.width, label_size.height + baseLine)),
cv::Scalar(255, 255, 255), -1);
cv::putText(img, text, cv::Point(x, y + label_size.height), cv::FONT_HERSHEY_SIMPLEX, 0.5,
cv::Scalar(0, 0, 0));
cv::imwrite("./pose_ppl_out.png", img);
}
static inline void draw_result_hand(cv::Mat img, ai_hand_parts_s& pose, int joints_num)
{
for (int i = 0; i < joints_num; i++)
{
int x = (int)(pose.keypoints[i].x * img.cols);
int y = (int)(pose.keypoints[i].y * img.rows);
x = std::max(std::min(x, (img.cols - 1)), 0);
y = std::max(std::min(y, (img.rows - 1)), 0);
cv::circle(img, cv::Point(x, y), 4, cv::Scalar(0, 0, 255), cv::FILLED);
}
cv::Scalar color;
cv::Point pt1;
cv::Point pt2;
for (auto& element : hand_pairs)
{
switch (element.left_right_neutral)
{
case 0:
color = cv::Scalar(10, 215, 255);
break;
case 1:
color = cv::Scalar(255, 115, 55);
break;
case 2:
color = cv::Scalar(5, 255, 55);
break;
case 3:
color = cv::Scalar(25, 15, 255);
break;
default:
color = cv::Scalar(225, 15, 55);
}
int x1 = (int)(pose.keypoints[element.connection[0]].x * img.cols);
int y1 = (int)(pose.keypoints[element.connection[0]].y * img.rows);
int x2 = (int)(pose.keypoints[element.connection[1]].x * img.cols);
int y2 = (int)(pose.keypoints[element.connection[1]].y * img.rows);
x1 = std::max(std::min(x1, (img.cols - 1)), 0);
y1 = std::max(std::min(y1, (img.rows - 1)), 0);
x2 = std::max(std::min(x2, (img.cols - 1)), 0);
y2 = std::max(std::min(y2, (img.rows - 1)), 0);
pt1 = cv::Point(x1, y1);
pt2 = cv::Point(x2, y2);
cv::line(img, pt1, pt2, color, 2);
}
cv::imwrite("./hand_pose_out.png", img);
}
static inline void post_process(float* data, ai_body_parts_s& pose, int joint_num, int img_h, int img_w)
{
int heatmap_width = img_w / 4;
int heatmap_height = img_h / 4;
int max_idx_width, max_idx_height;
float max_score;
ai_point_t kp;
for (int c = 0; c < joint_num; ++c)
{
find_max_2d(data, heatmap_width, heatmap_height, &max_idx_width, &max_idx_height, &max_score, c);
kp.x = (float)max_idx_width / (float)heatmap_width;
kp.y = (float)max_idx_height / (float)heatmap_height;
kp.score = max_score;
pose.keypoints.push_back(kp);
// std::cout << "x: " << pose.keypoints[c].x << ", y: " << pose.keypoints[c].y << ", score: "
// << pose.keypoints[c].score << std::endl;
}
}
static inline void animal_post_process(float* data, ai_animal_parts_s& pose, int joint_num, int img_h, int img_w)
{
int heatmap_width = img_w / 4;
int heatmap_height = img_h / 4;
int max_idx_width, max_idx_height;
float max_score;
ai_point_t kp;
for (int c = 0; c < joint_num; ++c)
{
find_max_2d(data, heatmap_width, heatmap_height, &max_idx_width, &max_idx_height, &max_score, c);
kp.x = (float)max_idx_width / (float)heatmap_width;
kp.y = (float)max_idx_height / (float)heatmap_height;
kp.score = max_score;
pose.keypoints.push_back(kp);
// std::cout << "x: " << pose.keypoints[c].x << ", y: " << pose.keypoints[c].y << ", score: "
// << pose.keypoints[c].score << std::endl;
}
}
static inline void ppl_pose_post_process(float* data1, float* data2, ai_body_parts_s& pose, int joint_num, int img_h, int img_w, int offset_top, int offset_left, int offset_x, int offset_y, float ratio)
{
ai_point_t kp;
for (int c = 0; c < joint_num; ++c)
{
kp.x = (data1[c] / 2 - offset_left) / ratio + offset_x;
kp.y = (data2[c] / 2 - offset_top) / ratio + offset_y;
std::cout << "x1: " << kp.x << ", y1: " << kp.y << std::endl;
pose.keypoints.push_back(kp);
}
}
static inline void post_process_hand(float* point_data, float* score_data, ai_hand_parts_s& pose, int joint_num, int img_h, int img_w)
{
ai_point_t kp;
for (int c = 0; c < joint_num; ++c)
{
kp.x = (float)point_data[c * 3] / img_w;
kp.y = (float)point_data[c * 3 + 1] / img_h;
pose.keypoints.push_back(kp);
}
if (score_data[0] > 0.5)
pose.hand_side = 1;
}
} // namespace pose
@@ -1,33 +0,0 @@
/*
* AXERA is pleased to support the open source community by making ax-samples available.
*
* Copyright (c) 2022, AXERA Semiconductor (Shanghai) Co., Ltd. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* 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.
*/
/*
* Author: ls.wang
*/
#pragma once
#include <cstdint>
namespace classification
{
typedef struct
{
uint32_t id;
float score;
} score;
}
@@ -1,52 +0,0 @@
/*
* AXERA is pleased to support the open source community by making ax-samples available.
*
* Copyright (c) 2022, AXERA Semiconductor (Shanghai) Co., Ltd. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* 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.
*/
/*
* Author: ls.wang
*/
#pragma once
#include <algorithm>
#include <cstdio>
#include <vector>
#include "base/score.hpp"
namespace classification
{
void sort_score(std::vector<score>& array, bool reverse = false)
{
auto compare_func = [](const score& a, const score& b) -> bool
{
return a.score > b.score;
};
std::sort(array.begin(), array.end(), compare_func);
if (reverse) std::reverse(array.begin(), array.end());
}
void print_score(const std::vector<score>& array, const size_t& n)
{
for (size_t i = 0; i < n; i++)
{
fprintf(stdout, "%.4f, %d\n", array[i].score, array[i].id);
}
}
}
@@ -1,47 +0,0 @@
/*
* AXERA is pleased to support the open source community by making ax-samples available.
*
* Copyright (c) 2022, AXERA Semiconductor (Shanghai) Co., Ltd. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* 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.
*/
/*
* Author: hebing
*/
#pragma once
#include <cstdint>
#include <opencv2/opencv.hpp>
#include <vector>
#include <algorithm>
#include <cmath>
#include <string>
namespace transform
{
static void nhwc2nchw(const float* input, float* output, int h, int w, int c)
{
int output_index = 0;
for (int i = 0; i < c; ++i)
{
for (int j = 0; j < h; ++j)
{
for (int k = 0; k < w; ++k)
{
int input_index = j * w * c + k * c + i;
output[output_index++] = input[input_index];
}
}
}
}
} // namespace transform
File diff suppressed because it is too large Load Diff
@@ -1,32 +0,0 @@
/**************************************************************************************************
*
* Copyright (c) 2019-2023 Axera Semiconductor (Ningbo) Co., Ltd. All Rights Reserved.
*
* This source file is the property of Axera Semiconductor (Ningbo) Co., Ltd. and
* may not be copied or distributed in any isomorphic form without the prior
* written consent of Axera Semiconductor (Ningbo) Co., Ltd.
*
**************************************************************************************************/
#ifndef AX_CHECKER_H
#define AX_CHECKER_H
#include "utils/logger.h"
#define CHECK_PTR(p) \
do { \
if (!p) { \
ALOGE("%s nil pointer\n", #p); \
return -1; \
} \
} while (0)
#define CHECK_INITED(p) \
do { \
if (!p->HasInit()) { \
ALOGE("%s has not init\n", #p); \
return -1; \
} \
} while (0)
#endif //AX_CHECKER_H
File diff suppressed because it is too large Load Diff
@@ -1,82 +0,0 @@
/**************************************************************************************************
*
* Copyright (c) 2019-2023 Axera Semiconductor (Ningbo) Co., Ltd. All Rights Reserved.
*
* This source file is the property of Axera Semiconductor (Ningbo) Co., Ltd. and
* may not be copied or distributed in any isomorphic form without the prior
* written consent of Axera Semiconductor (Ningbo) Co., Ltd.
*
**************************************************************************************************/
#ifndef SKEL_LOGGER_H
#define SKEL_LOGGER_H
#include "ax_global_type.h"
#include "ax_sys_log.h"
#include <stdio.h>
#ifdef __cplusplus
extern "C"
{
#endif
//#define SKEL_LOG_TAG "SKEL"
//
//#define ALOGE(fmt, ...) AX_LOG_ERR_EX(SKEL_LOG_TAG, AX_ID_SKEL, fmt, ##__VA_ARGS__)
//#define ALOGW(fmt, ...) AX_LOG_WARN_EX(SKEL_LOG_TAG, AX_ID_SKEL, fmt, ##__VA_ARGS__)
//#define ALOGI(fmt, ...) AX_LOG_INFO_EX(SKEL_LOG_TAG, AX_ID_SKEL, fmt, ##__VA_ARGS__)
//#define ALOGD(fmt, ...) AX_LOG_DBG_EX(SKEL_LOG_TAG, AX_ID_SKEL, fmt, ##__VA_ARGS__)
//#define ALOGN(fmt, ...) AX_LOG_NOTICE_EX(SKEL_LOG_TAG, AX_ID_SKEL, fmt, ##__VA_ARGS__)
typedef enum {
SKEL_LOG_MIN = -1,
SKEL_LOG_EMERGENCY = 0,
SKEL_LOG_ALERT = 1,
SKEL_LOG_CRITICAL = 2,
SKEL_LOG_ERROR = 3,
SKEL_LOG_WARN = 4,
SKEL_LOG_NOTICE = 5,
SKEL_LOG_INFO = 6,
SKEL_LOG_DEBUG = 7,
SKEL_LOG_MAX
} SKEL_LOG_LEVEL_E;
static SKEL_LOG_LEVEL_E log_level = SKEL_LOG_DEBUG;
#if 1
#define MACRO_BLACK "\033[1;30;30m"
#define MACRO_RED "\033[1;30;31m"
#define MACRO_GREEN "\033[1;30;32m"
#define MACRO_YELLOW "\033[1;30;33m"
#define MACRO_BLUE "\033[1;30;34m"
#define MACRO_PURPLE "\033[1;30;35m"
#define MACRO_WHITE "\033[1;30;37m"
#define MACRO_END "\033[0m"
#else
#define MACRO_BLACK
#define MACRO_RED
#define MACRO_GREEN
#define MACRO_YELLOW
#define MACRO_BLUE
#define MACRO_PURPLE
#define MACRO_WHITE
#define MACRO_END
#endif
#define ALOGE(fmt, ...) printf(MACRO_RED "[E][%32s][%4d]: " fmt MACRO_END "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
#define ALOGW(fmt, ...) if (log_level >= SKEL_LOG_WARN) \
printf(MACRO_YELLOW "[W][%32s][%4d]: " fmt MACRO_END "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
#define ALOGI(fmt, ...) if (log_level >= SKEL_LOG_INFO) \
printf(MACRO_GREEN "[I][%32s][%4d]: " fmt MACRO_END "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
#define ALOGD(fmt, ...) if (log_level >= SKEL_LOG_DEBUG) \
printf(MACRO_WHITE "[D][%32s][%4d]: " fmt MACRO_END "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
#define ALOGN(fmt, ...) if (log_level >= SKEL_LOG_NOTICE) \
printf(MACRO_PURPLE "[N][%32s][%4d]: " fmt MACRO_END "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
#ifdef __cplusplus
}
#endif
#endif //SKEL_LOGGER_H
@@ -1,61 +0,0 @@
/*
* AXERA is pleased to support the open source community by making ax-samples available.
*
* Copyright (c) 2022, AXERA Semiconductor (Shanghai) Co., Ltd. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* 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.
*/
/*
* Author: ls.wang
*/
#pragma once
#include <chrono>
class timer
{
private:
std::chrono::system_clock::time_point start_time, end_time;
public:
timer()
{
start();
}
void start()
{
stop();
this->start_time = this->end_time;
}
void stop()
{
#ifdef _MSC_VER
this->end_time = std::chrono::system_clock::now();
#else
this->end_time = std::chrono::high_resolution_clock::now();
#endif
}
float cost()
{
if (this->end_time <= this->start_time)
{
this->stop();
}
auto ms = std::chrono::duration_cast<std::chrono::microseconds>(this->end_time - this->start_time).count();
return static_cast<float>(ms) / 1000.f;
}
};