diff --git a/bin/models/road_seg/tzroad_seg240108_310p.om b/bin/models/road_seg/tzroad_seg240108_310p.om new file mode 100755 index 0000000..474aa9c --- /dev/null +++ b/bin/models/road_seg/tzroad_seg240108_310p.om diff --git a/build/src/Makefile b/build/src/Makefile index 9137579..a53a705 100644 --- a/build/src/Makefile +++ b/build/src/Makefile @@ -20,6 +20,7 @@ INCLUDES = -I$(PROJ_ALL_PATH)/src/common \ -I$(PROJ_ALL_PATH)/src/common/dvpp \ -I$(PROJ_ALL_PATH)/src/common/cnn \ -I$(PROJ_ALL_PATH)/src/common/cnn_cls \ + -I$(PROJ_ALL_PATH)/src/common/road_cnn \ -I$(PROJ_ALL_PATH)/src/common/dvppx \ -I$(PROJ_ALL_PATH)/src/common/model_process \ -I$(CUR_PROJ_PATH)/../va \ @@ -65,6 +66,7 @@ SRCS := $(wildcard $(CUR_PROJ_PATH)/*.cpp) \ $(wildcard $(CUR_PROJ_PATH)/common/*.cpp) \ $(wildcard $(CUR_PROJ_PATH)/common/dvpp/*.cpp) \ $(wildcard $(CUR_PROJ_PATH)/common/cnn_cls/*.cpp) \ + $(wildcard $(CUR_PROJ_PATH)/common/road_cnn/*.cpp) \ $(wildcard $(CUR_PROJ_PATH)/common/cnn/*.cpp) \ $(wildcard $(CUR_PROJ_PATH)/common/dvppx/*.cpp) \ $(wildcard $(CUR_PROJ_PATH)/common/model_process/*.cpp) \ @@ -95,6 +97,9 @@ $(TARGET):$(OBJS) %.o:$(CUR_PROJ_PATH)/common/cnn_cls/%.cpp $(XX) $(CXXFLAGS) -c $< +%.o:$(CUR_PROJ_PATH)/common/road_cnn/%.cpp + $(XX) $(CXXFLAGS) -c $< + %.o:$(CUR_PROJ_PATH)/common/dvppx/%.cpp $(XX) $(CXXFLAGS) -c $< diff --git a/src/PicAnalysis.cpp b/src/PicAnalysis.cpp index f8723d6..33d2649 100644 --- a/src/PicAnalysis.cpp +++ b/src/PicAnalysis.cpp @@ -50,7 +50,12 @@ int PicAnalysis::init(int dev_id) { // return -1; // } - ret = m_motor_phone_algorithm.init(dev_id); + // ret = m_motor_phone_algorithm.init(dev_id); + // if(0 != ret){ + // return -1; + // } + + ret = m_road_seg_algorithm.init(dev_id); if(0 != ret){ return -1; } @@ -117,7 +122,9 @@ int PicAnalysis::analysis_sync(vector vec_file_path){ // m_motor_rainshed_algorithm.detect(vec_img); - m_motor_phone_algorithm.detect(vec_img); + // m_motor_phone_algorithm.detect(vec_img); + + m_road_seg_algorithm.detect(vec_img); LOG_INFO("analysis_sync finished!"); diff --git a/src/PicAnalysis.h b/src/PicAnalysis.h index 95805eb..07353d3 100644 --- a/src/PicAnalysis.h +++ b/src/PicAnalysis.h @@ -6,6 +6,7 @@ #include "./ai_engine_module/HumanCarAnalysis.h" #include "./ai_engine_module/MotorRainshedAnalysis.h" #include "./ai_engine_module/MotorPhoneAnalysis.h" +#include "./ai_engine_module/RoadSegAnalysis.h" using namespace std; @@ -35,6 +36,7 @@ private: HumanCarAnalysis m_human_car_algorithm; MotorRainshedAnalysis m_motor_rainshed_algorithm; MotorPhoneAnalysis m_motor_phone_algorithm; + RoadSegAnalysis m_road_seg_algorithm; }; diff --git a/src/ai_engine_module/RoadSegAnalysis.cpp b/src/ai_engine_module/RoadSegAnalysis.cpp new file mode 100644 index 0000000..1eed41b --- /dev/null +++ b/src/ai_engine_module/RoadSegAnalysis.cpp @@ -0,0 +1,79 @@ +#include "RoadSegAnalysis.h" +#include "road_seg.h" + +RoadSegAnalysis::RoadSegAnalysis(/* args */) +{ +} + +RoadSegAnalysis::~RoadSegAnalysis() +{ + release(); +} + +int RoadSegAnalysis::init(int devId){ + ACL_CALL(aclrtCreateContext(&ctx, devId), SY_SUCCESS, SY_FAILED); + + rs_param param; + param.modelNames = "./models/road_seg/tzroad_seg240108_310p.om"; + param.thresld = 0.25; + param.devId = devId; + + cout << "rs_init start " << endl; + int ret = rs_init(&m_handle, param); + if (ret != 0) { + return -1; + } + + cout << "rs_init success " << endl; + + return SY_SUCCESS; +} + +int RoadSegAnalysis::detect(vector vec_img){ + + ACL_CALL(aclrtSetCurrentContext(ctx), SY_SUCCESS, SY_FAILED); + + const int batchsize = vec_img.size(); + rs_result results[batchsize]; + const int fea_size = 360*640; + for (int b = 0; b < batchsize; b++) { + results[b].seg_array = new unsigned char[fea_size]; + results[b].direct_seg = new unsigned char[fea_size]; + } + + int ret = SY_FAILED; + + do + { + ret = rs_batch(m_handle, vec_img.data(), batchsize, results); + if (SY_SUCCESS != ret) { + printf("mrc_batch failed!"); + break; + } + + // todo 结果处理 + } while (0); + + for (int b = 0; b < batchsize; b++) { + delete[] results[b].seg_array; results[b].seg_array = NULL; + delete[] results[b].direct_seg; results[b].direct_seg = NULL; + } + + return ret; +} + +int RoadSegAnalysis::release() { + + ACL_CALL(aclrtSetCurrentContext(ctx), SY_SUCCESS, SY_FAILED); + + if (m_handle) { + rs_release(&m_handle); + } + + if(ctx){ + aclrtDestroyContext(ctx); + ctx = nullptr; + } + + return SY_SUCCESS; +} \ No newline at end of file diff --git a/src/ai_engine_module/RoadSegAnalysis.h b/src/ai_engine_module/RoadSegAnalysis.h new file mode 100644 index 0000000..f3271bd --- /dev/null +++ b/src/ai_engine_module/RoadSegAnalysis.h @@ -0,0 +1,20 @@ +#include "include.h" + +class RoadSegAnalysis +{ +public: + RoadSegAnalysis(/* args */); + ~RoadSegAnalysis(); + + int init(int devId); + + int detect(vector vec_img); + +private: + int release(); + +private: + void* m_handle{nullptr}; + aclrtContext ctx{nullptr}; +}; + diff --git a/src/ai_engine_module/road_seg.cpp b/src/ai_engine_module/road_seg.cpp new file mode 100755 index 0000000..9c7f4ab --- /dev/null +++ b/src/ai_engine_module/road_seg.cpp @@ -0,0 +1,435 @@ +#include "road_seg.h" +#include "sy_errorinfo.h" +#include "road_extractor.h" +#include "dvpp_processx.h" +#include +#include +#include "stream_data.h" +#include +#include +#include +#include + + +using namespace atlas_utils; +using namespace std; + +struct Resource { + aclrtContext ctx; + aclrtStream stream; +}; + +typedef struct Tools { + Resource src; + ROADExtract* roadsegExtract; + DvppProcessx* dvpp; + +}Tools; + + +int rs_init(void **handle, rs_param param){ + + int ret = SY_SUCCESS; + Tools* tools = new Tools; + // init resource + ACL_CALL(aclrtCreateStream(&tools->src.stream), ACL_SUCCESS, SY_FAILED); + + // head_shoulder detection init + tools->roadsegExtract = new ROADExtract(); + tools->roadsegExtract->config.confThr = param.thresld; + + ret = tools->roadsegExtract->Init(param.modelNames); + if (ret != SY_SUCCESS) { + delete tools->roadsegExtract; + tools->roadsegExtract = nullptr; + return SY_FAILED; + } + + tools->dvpp = new DvppProcessx(); + tools->dvpp->InitResource(tools->src.stream); + + *handle = tools; + + return SY_SUCCESS; +} + +namespace road_seg_7cls +{ + int lane_cls_classes = 6; //5 + 1 + int road_seg_classes = 9; //8类别+背景 + int direct_seg_classes = 5; //4类别+背景 + std::vector lane_softmax(const std::vector& x) { + std::vector result(x.size()); + // 实现softmax逻辑 + float max_val = *std::max_element(x.begin(), x.end()); + float sum = 0.0; + for (size_t i = 0; i < x.size(); i++) { + result[i] = std::exp(x[i] - max_val); + sum += result[i]; + } + for (size_t i = 0; i < x.size(); i++) { + result[i] /= sum; + } + + return result; + } + + std::vector lane_linspace(float start, float end, int n) { + std::vector result; + float step = (end - start) / (n - 1); + for (int i = 0; i < n; i++) { + result.push_back(start + step * i); + } + return result; + } + + bool Lane_IOU(const std::vector& parent_box, const std::vector& compared_box, int threshold) { + // 实现Lane_IOU逻辑 + int y = lane_cls_classes, length = y + 2, offset_start = y + 3; + + int n_offsets = 72; + int n_strips = n_offsets - 1; + + int start_a = static_cast((parent_box[y] * n_strips) + 0.5); + int start_b = static_cast((compared_box[y] * n_strips) + 0.5); + int start = std::max(start_a, start_b); + int end_a = start_a + static_cast(parent_box[length]) - 1 + 0.5 - ((parent_box[length] - 1 < 0) ? 1 : 0); + int end_b = start_b + static_cast(compared_box[length]) - 1 + 0.5 - ((compared_box[length] - 1 < 0) ? 1 : 0); + int end = std::min(std::min(end_a, end_b), n_strips); + if (end - start < 0) { + return false; + } + int dist = 0; + for (int i = offset_start + start; i < offset_start + end; i++) { + if (i > (offset_start + end)) { + break; + } + if (parent_box[i] < compared_box[i]) { + dist += (compared_box[i] - parent_box[i]); + } else { + dist += (parent_box[i] - compared_box[i]); + } + } + return dist < (threshold * (end - start + 1)); + } + + void Lane_nms(const std::vector>& proposals, std::vector &keep_index, size_t &num_to_keep, const std::vector& scores, int overlap = 50, int top_k = 4) { + // 实现Lane_nms逻辑 + /*std::vector sorted_score = scores; + std::sort(sorted_score.begin(), sorted_score.end(), std::greater());*/ + std::vector indices(scores.size()); + for (size_t i = 0; i < indices.size(); i++) { + indices[i] = i; + } + std::sort(indices.begin(), indices.end(), [&](int a, int b) { return scores[a] > scores[b]; }); + + std::vector r_filters(scores.size(), 0); + + for (size_t i = 0; i < indices.size(); i++) { + int indice = indices[i]; + if (r_filters[i] == 1) { // continue if this proposal is filtered by nms before + continue; + } + keep_index.push_back(indice); + if (keep_index.size() > static_cast(top_k)) { // break if more than top_k + break; + } + if (i == indices.size() - 1) { // break if indice is the last one + break; + } + std::vector sub_indices(indices.begin() + i + 1, indices.end()); + for (size_t sub_i = 0; sub_i < sub_indices.size(); sub_i++) { + int sub_indice = sub_indices[sub_i]; + bool r_filter = Lane_IOU(proposals[indice], proposals[sub_indice], overlap); + if (r_filter) { + r_filters[i + 1 + sub_i] = 1; + } + } + } + + num_to_keep = static_cast(keep_index.size()); + } + + + int predictions_to_pred(const std::vector>& predictions, rs_lane* reg_array, int n_strips, int n_offsets) { + std::vector prior_ys = lane_linspace(1.0, 0.0, n_offsets); + int lane_count = 0; + int start_x = lane_cls_classes + 1, start_y = lane_cls_classes, offset_start = lane_cls_classes + 4, length_ = lane_cls_classes + 3; + for (const auto& lane : predictions) { + std::vector lane_xs(lane.begin() + offset_start, lane.end()); // normalized value + int start = std::min(std::max(0, static_cast(std::round(lane[start_y] * n_strips))), n_strips); + int length = static_cast(std::round(lane[length_])); + int end = start + length - 1; + end = std::min(end, static_cast(prior_ys.size()) - 1); + /* + std::vector mask(prior_ys.size(), false); + for (int i = 0; i < start; i++) { + if (lane_xs[i] >= 0.0 && lane_xs[i] <= 1.0) { + mask[i] = true; + } + } + for (int i = end + 1; i < static_cast(prior_ys.size()); i++) { + if (lane_xs[i] >= 0.0 && lane_xs[i] <= 1.0) { + mask[i] = true; + } + }*/ + + std::fill(lane_xs.begin() + end + 1, lane_xs.end(), -2); + std::fill(lane_xs.begin(), lane_xs.begin() + start, -2); + + std::vector lane_ys; + for (size_t i = 0; i < prior_ys.size(); i++) { + // if (!mask[i]) { + if (lane_xs[i] >= 0) { + lane_ys.push_back(prior_ys[i]); + } + } + + std::vector lane_xs_new; + for (size_t i = 0; i < prior_ys.size(); i++) { + // if (!mask[i]) { + if (lane_xs[i] >= 0) { + lane_xs_new.push_back(lane_xs[i]); + } + } + + + if (lane_xs_new.empty()) { + continue; + } + + int lane_xs_new_size = lane_xs_new.size(); + // if (lane_xs_new_size <= 1) { + // continue; + // } + + if (lane_xs_new_size > 180) { + lane_xs_new_size = 180; + } + + int count = 0; + #if 1 + for (size_t i = 0; i < lane_xs_new_size; i++) { + // float lane_x = lane_xs_new[i], lane_y = lane_ys[i]; + float lane_x = lane_xs_new[i] * 640; + float lane_y = lane_ys[i] * 360; + reg_array[lane_count].points[count].x_ = lane_x; + reg_array[lane_count].points[count].y_ = lane_y; + // printf("lane_x:%f lane_y:%f %d %d\n", lane_x, lane_y, reg_array[lane_count].points[count].x_, reg_array[lane_count].points[count].y_); + count ++; + } + #endif + + reg_array[lane_count].start_x = lane[start_x]* 640; + reg_array[lane_count].start_y = lane[start_y]* 360; + + + std::vector lane_info(lane.begin()+1, lane.begin()+lane_cls_classes); // 去除背景类别 + std::vector softmax_res = lane_softmax(lane_info); + reg_array[lane_count].cls = std::distance(softmax_res.begin(),std::max_element(softmax_res.begin(),softmax_res.end())) + 1; + reg_array[lane_count].conf = *(std::max_element(softmax_res.begin(),softmax_res.end())); + reg_array[lane_count].num_points = count; + lane_count ++; + } + return lane_count; + } + + // 统一求nms + int get_lanes(const vector output, rs_lane* reg_array, float conf_threshold, int nms_thres, int max_lanes) { + + int stride1 = 192, stride2 = 82, num_points = 72, input_width = 640, input_height = 360; + int theta = lane_cls_classes + 2, length = lane_cls_classes + 3; + int n_strips = num_points - 1, n_offsets = num_points; + std::vector> predictions, nms_predictions; + std::vector scores; + for (int i = 0; i < stride1; i++) { + std::vector pred_score(output.begin() + i*stride2, output.begin() + i*stride2+lane_cls_classes); // 存储类别得分 + std::vector softmax_res = lane_softmax(pred_score); + std::vector selected_scores(softmax_res.begin()+1, softmax_res.begin()+lane_cls_classes); // 选择目标类别的概率值,去除背景类别 + float max_score = *std::max_element(selected_scores.begin(), selected_scores.end()); + if (max_score >= conf_threshold) { + std::vector pred(output.begin() + i*stride2, output.begin() + (i+1)*stride2); + nms_predictions.push_back(pred); + predictions.push_back(pred); + scores.push_back(max_score); + } + } + + for (auto& row : nms_predictions) { + row[theta] *= n_strips; + for (size_t i = length; i < row.size(); i++) { + row[i] *= (input_width - 1); + } + } + + std::vector keep; + size_t num_to_keep; + Lane_nms(nms_predictions, keep, num_to_keep, scores, nms_thres, max_lanes); + keep.resize(num_to_keep); + + std::vector> final_predictions; + for (auto& index : keep) { + predictions[index][length] = round(predictions[index][length] * n_strips); + final_predictions.push_back(predictions[index]); + } + + int lane_count = predictions_to_pred(final_predictions, reg_array, n_strips, n_offsets); + return lane_count; + } + + // 对每个类别分别求nms + int get_lanesV2(const vector output, rs_lane* reg_array, float conf_threshold, int nms_thres, int max_lanes) { + + int stride1 = 192, stride2 = 82, num_points = 72, input_width = 640, input_height = 360; + int theta = lane_cls_classes + 2, length = lane_cls_classes + 3; + int n_strips = num_points - 1, n_offsets = num_points; + + std::vector> final_predictions; + for (int cls = 0; cls < lane_cls_classes; cls++) { + std::vector> predictions, nms_predictions; + std::vector scores; + for (int i = 0; i < stride1; i++) { + std::vector pred_score(output.begin() + i*stride2, output.begin() + i*stride2+lane_cls_classes); // 存储类别得分 + std::vector softmax_res = lane_softmax(pred_score); + std::vector selected_scores(softmax_res.begin()+1, softmax_res.begin()+lane_cls_classes); // 选择目标类别的概率值,去除背景类别 + + auto iter = std::max_element(selected_scores.begin(), selected_scores.end()); + int indice = std::distance(selected_scores.begin(), iter); + float max_score = *iter; + if (indice == cls && max_score >= conf_threshold) { + std::vector pred(output.begin() + i*stride2, output.begin() + (i+1)*stride2); + nms_predictions.push_back(pred); + predictions.push_back(pred); + scores.push_back(max_score); + } + } + + for (auto& row : nms_predictions) { + row[theta] *= n_strips; + for (size_t i = length; i < row.size(); i++) { + row[i] *= (input_width - 1); + } + } + + std::vector keep; + size_t num_to_keep; + Lane_nms(nms_predictions, keep, num_to_keep, scores, nms_thres, max_lanes); + keep.resize(num_to_keep); + + + for (auto& index : keep) { + predictions[index][length] = round(predictions[index][length] * n_strips); + final_predictions.push_back(predictions[index]); + } + } + + int lane_count = predictions_to_pred(final_predictions, reg_array, n_strips, n_offsets); + return lane_count; + } + + + // 获取道路分割结果中最大值的索引(类别) + // int road_seg_show(const float* inference_features, uint8_t *road_seg) { + int road_seg_show(const vector inference_features, uint8_t *road_seg, int seg_num_cls) { + int h = 360, w = 640; + int step_size = h*w; + for (int i = 0; i < h; i++) { + for (int j = 0; j < w; j++) { + float max_score = 0; int max_cls = 0; + for (int k = 0; k < seg_num_cls; k++) { + int cur_steps = i*w+j+k*step_size; + if (inference_features[cur_steps] > max_score) { + max_score = inference_features[cur_steps]; + max_cls = k; + } + } + // if (max_cls == 5 || max_cls == 6) max_cls = 0; // 将分割的车道线变成背景,防止混淆================ + road_seg[i*w+j] = max_cls; + } + } + + return 0; + } +} + +int rs_process(void *handle, sy_img img_data, rs_result result) +{ + return rs_batch(handle, &img_data, 1, &result); +} + +int rs_batch(void * handle, sy_img *image_data_array, int batchsize, rs_result *result){ + Tools* tools = (Tools*) handle; + + int inputW = tools->roadsegExtract->GetInputWidth(); + int inputH = tools->roadsegExtract->GetInputHeight(); + + //printf("debug inputw:%d,inputh:%d\n",inputW,inputH); + + for (int b = 0; b < batchsize; b++) { + if (image_data_array[b].data_ == NULL || image_data_array[b].w_ == 0 || image_data_array[b].h_ == 0) { + ERROR_LOG(" RoadSegExtract get null input ptr!"); + return SY_FAILED; + } + + ImageData resizeImg, src; + // Utils::CopysyImageDataToDvpp(src, image_data_array[b]); + ACL_CALL(Utils::CopysyImageDataToDvppV2(src, image_data_array[b]), SY_SUCCESS, SY_FAILED); + ACL_CALL(tools->dvpp->CropAndPadding(resizeImg, src, inputW, inputH), SY_SUCCESS, SY_FAILED); + // forward + // double t1, t2; + // t1 = msecond(); + int ret = tools->roadsegExtract->Inference(resizeImg); + if (ret != SY_SUCCESS) { + return SY_MODEL_FORWARD_ERROR; + } + // t2 = msecond(); + // printf("debug infer time: %.2f\n", t2 - t1); + + vector detRes; + ret = tools->roadsegExtract->PostProcess(detRes); + if (ret != SY_SUCCESS) { + return SY_MODEL_GETRESULT_ERROR; + } + + int lane_length = 192 * 82; + int roadseg_length = 360 * 640 * road_seg_7cls::road_seg_classes; + std::vector clane_detection(detRes.begin(), detRes.begin() + lane_length); + std::vector croad_segmentation(detRes.begin() + lane_length, detRes.begin() + lane_length + roadseg_length); + std::vector cdirect_segmentation(detRes.begin() + lane_length + roadseg_length, detRes.end()); + + int res = road_seg_7cls::road_seg_show(croad_segmentation, result[b].seg_array, road_seg_7cls::road_seg_classes); + res = road_seg_7cls::road_seg_show(cdirect_segmentation, result[b].direct_seg, road_seg_7cls::direct_seg_classes); + float conf_threshold = 0.4; + int nms_thres = 50, max_lanes = 21; + int lane_count = road_seg_7cls::get_lanesV2(clane_detection, result[b].reg_array, conf_threshold, nms_thres, max_lanes); + result[b].lane_count = lane_count; + + vector().swap(detRes); + vector().swap(clane_detection); + vector().swap(croad_segmentation); + vector().swap(cdirect_segmentation); + } + + return SY_SUCCESS; +} + +void rs_release(void **handle) { + if (*handle) { + Tools* tools = (Tools*) *handle; + if (tools->roadsegExtract) { + delete tools->roadsegExtract; + tools->roadsegExtract = nullptr; + } + if (tools->dvpp) { + delete tools->dvpp; + tools->dvpp = nullptr; + } + // aclFinalize(); + delete tools; + tools = NULL; + } +} + +const char * rs_get_version() { + return "road_seg_vdec_arm_v310p_0.0.2.20240110_without_timelimit"; +} \ No newline at end of file diff --git a/src/ai_engine_module/road_seg.h b/src/ai_engine_module/road_seg.h new file mode 100755 index 0000000..f763f5b --- /dev/null +++ b/src/ai_engine_module/road_seg.h @@ -0,0 +1,121 @@ +/************************************************************************* +* Version: road_seg_v0.0.0.20230313 +* CopyRight : 中国科学院自动化所模式识别实验室图像视频组 +* UpdateDate: +* Content : 道路分割 +*************************************************************************/ +#ifndef ROADSEG_H_ +#define ROADSEG_H_ + +#if _MSC_VER +#ifdef ROADSEG_EXPORTS +#define ROADSEG_API __declspec(dllexport) +#else +#define ROADSEG_API __declspec(dllimport) +#endif +#else +#define ROADSEG_API __attribute__ ((visibility ("default"))) +#endif + +#include "sy_common.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +#ifndef __RS_LANE__ +#define __RS_LANE__ +typedef struct rs_lane { + sy_point points[180]; // 车道线上的点坐标数组 + int num_points; // 车道线上点的数量 + float start_x; // 起始点x坐标 + float start_y; // 起始点y坐标 + float cls; // 车道线类别 1-实线 2-虚线 + float conf; // 车道线置信度 +}rs_lane; +#endif + +#ifndef __rs_RESULT__ +#define __rs_RESULT__ + typedef struct rs_result + { + rs_lane reg_array[20]; + int lane_count; + unsigned char *seg_array; + unsigned char *direct_seg; + }rs_result; +#endif + +#ifndef __rs_PARAM__ +#define __rs_PARAM__ + typedef struct rs_param + { + int devId; //运行卡号 + char* modelNames; + float thresld; //检测阈值 默认为0.3 + }rs_param; +#endif + + /************************************************************************* + * FUNCTION: rs_init + * PURPOSE: 载入模型 + * PARAM: + [in] handle - 句柄 + [in] params - 参数 + * RETURN: 成功(0)或者错误代码 + * NOTES: + *************************************************************************/ + ROADSEG_API int rs_init(void ** handle, rs_param param); + + /************************************************************************* + * FUNCTION: rs_process + * PURPOSE: 车颜色识别 + * PARAM: + [in] handle - 检测句柄 + [in] img_data - 图像数据 + [in] result - 结果 内存在外部申请 + * RETURN: 成功(0) 或 错误代码(< 0) + * NOTES: + *************************************************************************/ + ROADSEG_API int rs_process(void *handle, sy_img img_data, rs_result result); + + /************************************************************************* + * FUNCTION: rs_batch + * PURPOSE: 车颜色识别 batch + * PARAM: + [in] handle - 检测句柄 + [in] img_data_array - 图像数据 + [in] batch_size - 图像数目 + [in] result - 结果 内存在外部申请 + * RETURN: 成功(0) 或 错误代码(< 0) + * NOTES: + *************************************************************************/ + ROADSEG_API int rs_batch(void *handle, sy_img* img_data_array, int batch_size, rs_result* result); + + + /************************************************************************* + * FUNCTION: rs_release + * PURPOSE: 释放 + * PARAM: + [in] handle - handle + * RETURN: NULL + * NOTES: + *************************************************************************/ + ROADSEG_API void rs_release(void ** handle); + + + /************************************************************************* + * FUNCTION: rs_get_version + * PURPOSE: + * PARAM: NULL + * RETURN: 版本号 + * NOTES: + *************************************************************************/ + ROADSEG_API const char * rs_get_version(); + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/src/common/road_cnn/road_extractor.cpp b/src/common/road_cnn/road_extractor.cpp new file mode 100755 index 0000000..924a14d --- /dev/null +++ b/src/common/road_cnn/road_extractor.cpp @@ -0,0 +1,83 @@ +#include "road_extractor.h" +#include +#include "acl/acl.h" +#include "model_process.h" +#include "sy_errorinfo.h" +#include +#include +#include + +using namespace std; + +namespace atlas_utils { + +int ROADExtract::Init(const char* modelPath) { + ACL_CALL(aclrtGetRunMode(&runMode_), SY_SUCCESS, SY_FAILED);//获取当前昇腾AI软件栈的运行模式,根据不同的运行模式,后续的接口调用方式不同 + ACL_CALL(model_.LoadModelFromFileWithMem(modelPath), SY_SUCCESS, SY_FAILED);//从文件加载离线模型数据,由用户自行管理模型运行的内存 + ACL_CALL(model_.CreateDesc(), SY_SUCCESS, SY_FAILED);//获取模型的描述信息 + ACL_CALL(model_.CreateOutput(outDims_), SY_SUCCESS, SY_FAILED); + ACL_CALL(model_.GetInputDims(inDims_), SY_SUCCESS, SY_FAILED); + modelHeight_ = inDims_[0][1]; + modelWidth_ = inDims_[0][2]; + + return SY_SUCCESS; +} + + +int ROADExtract::Inference(ImageData& input) { + model_.CreateInput(input.data.get(), input.size); + ACL_CALL(model_.Execute(), SY_SUCCESS, SY_FAILED); + model_.DestroyInput(); //需调用CreateInput的销毁类接口DestroyInput!!! + return SY_SUCCESS; +} + +int ROADExtract::GetInputWidth() { + return modelWidth_; +} + +int ROADExtract::GetInputHeight() { + return modelHeight_; +} + +int ROADExtract::PostProcess(vector& results) { + aclmdlDataset* modelOutput = model_.GetModelOutputData(); + int outDatasetNum = aclmdlGetDatasetNumBuffers(modelOutput); + for (int i = 0; i < outDatasetNum; i++) { + aclDataBuffer* dataBuffer = aclmdlGetDatasetBuffer(modelOutput, i); + if (dataBuffer == nullptr) { + return SY_FAILED; + } + + uint32_t dataBufferSize = aclGetDataBufferSize(dataBuffer); + void* data = aclGetDataBufferAddr(dataBuffer); + if (data == nullptr) { + return SY_FAILED; + } + + int length = dataBufferSize/sizeof(float); + // float outInfo[length]; //栈上分配,受栈大小限制,数组过大可能导致栈溢出 + float* outInfo = new float[length]; //堆上分配 + if (runMode_ == ACL_HOST) { + ACL_CALL(aclrtMemcpy(outInfo, dataBufferSize, data, dataBufferSize, ACL_MEMCPY_DEVICE_TO_HOST),ACL_SUCCESS, SY_FAILED); + } + else { + ACL_CALL(aclrtMemcpy(outInfo, dataBufferSize, data, dataBufferSize, ACL_MEMCPY_DEVICE_TO_DEVICE),ACL_SUCCESS, SY_FAILED); + } + + for(uint32_t b = 0; b < length; b++) { + results.emplace_back(outInfo[b]); + } + + delete[] outInfo; outInfo = nullptr; + } + + return SY_SUCCESS; +} + +void ROADExtract::Release() { + model_.Unload(); + model_.DestroyDesc(); + model_.DestroyOutput(); +} + +} diff --git a/src/common/road_cnn/road_extractor.h b/src/common/road_cnn/road_extractor.h new file mode 100755 index 0000000..e7c2860 --- /dev/null +++ b/src/common/road_cnn/road_extractor.h @@ -0,0 +1,52 @@ +#ifndef _ROAD_EXTRACT_H_ +#define _ROAD_EXTRACT_H_ + +#include +#include "utils.h" +#include "acl/acl.h" +#include "model_process.h" + +using namespace std; + +namespace atlas_utils { + + +#ifndef DATA_TYPE_SIZE +#define DATA_TYPE_SIZE 4 +#endif + +class ROADExtract { +public: + struct ConfigParams { + float confThr = 0.0; + }; + + ROADExtract() {} + ~ROADExtract() { + Release(); + } + + int Init(const char* modelPath); + int Inference(ImageData& input); + int PostProcess(vector& result); + + int GetInputWidth(); + int GetInputHeight(); + + ConfigParams config; + +private: + void Release(); + + vector> outDims_; + vector> inDims_; + ModelProcess model_; + uint32_t modelWidth_; + uint32_t modelHeight_; + aclrtRunMode runMode_; + +}; + +} + +#endif