/* * SPDX-FileCopyrightText: Copyright (c) 1993-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * 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. */ #include #include namespace nvinfer1 { namespace plugin { #define checkCudaErrors(status_) \ { \ auto const status = status_; \ if (status != 0) \ { \ std::cout << "Cuda failure: " << cudaGetErrorString(status) \ << " at line " << __LINE__ \ << " in file " << __FILE__ \ << " error status: " << status \ << std::endl; \ exit(EXIT_FAILURE); \ } \ } #ifndef M_PI #define M_PI 3.14159265358979323846 #endif __device__ float sigmoid(const float x) { return 1.0f / (1.0f + expf(-x)); } __global__ void postprocess_kernal(const float *cls_input, float const* box_input, const float *dir_cls_input, float *anchors, float *anchors_bottom_height, float *bndbox_output, int *object_counter, const float min_x_range, const float max_x_range, const float min_y_range, const float max_y_range, const int feature_x_size, const int feature_y_size, const int num_anchors, const int num_classes, const int num_box_values, const float score_thresh, const float dir_offset, const float dir_limit_offset, const int num_dir_bins) { int max_box_num = feature_x_size * feature_y_size * num_anchors; int loc_index =blockIdx.x; int batch_idx = blockIdx.x / (feature_x_size * feature_y_size); int loc_index_in_frame = blockIdx.x % (feature_x_size * feature_y_size); int ith_anchor = threadIdx.x; if (ith_anchor >= num_anchors) { return; } int col = loc_index_in_frame % feature_x_size; int row = loc_index_in_frame / feature_x_size; float x_offset = min_x_range + col * (max_x_range - min_x_range) / (feature_x_size - 1); float y_offset = min_y_range + row * (max_y_range - min_y_range) / (feature_y_size - 1); int cls_offset = loc_index * num_classes * num_anchors + ith_anchor * num_classes; float dev_cls[2] = {-1, 0}; const float *scores = cls_input + cls_offset; float max_score = sigmoid(scores[0]); int cls_id = 0; for (int i = 1; i < num_classes; i++) { float cls_score = sigmoid(scores[i]); if (cls_score > max_score) { max_score = cls_score; cls_id = i; } } dev_cls[0] = static_cast(cls_id); dev_cls[1] = max_score; if (dev_cls[1] >= score_thresh) { int box_offset = loc_index * num_anchors * num_box_values + ith_anchor * num_box_values; int dir_cls_offset = loc_index * num_anchors * 2 + ith_anchor * 2; float *anchor_ptr = anchors + ith_anchor * 4; float z_offset = anchor_ptr[2] / 2 + anchors_bottom_height[ith_anchor / 2]; float anchor[7] = {x_offset, y_offset, z_offset, anchor_ptr[0], anchor_ptr[1], anchor_ptr[2], anchor_ptr[3]}; float const* box_encodings = box_input + box_offset; float xa = anchor[0]; float ya = anchor[1]; float za = anchor[2]; float dxa = anchor[3]; float dya = anchor[4]; float dza = anchor[5]; float ra = anchor[6]; float diagonal = sqrtf(dxa * dxa + dya * dya); float be0 = box_encodings[0] * diagonal + xa; float be1 = box_encodings[1] * diagonal + ya; float be2 = box_encodings[2] * dza + za; float be3 = expf(box_encodings[3]) * dxa; float be4 = expf(box_encodings[4]) * dya; float be5 = expf(box_encodings[5]) * dza; float be6 = box_encodings[6] + ra; float yaw; int dir_label = dir_cls_input[dir_cls_offset] > dir_cls_input[dir_cls_offset + 1] ? 0 : 1; float period = 2.0f * float(M_PI) / num_dir_bins; float val = be6 - dir_offset; float dir_rot = val - floor(val / period + dir_limit_offset) * period; yaw = dir_rot + dir_offset + period * dir_label; int resCount = atomicAdd(object_counter + batch_idx, 1); float *data = bndbox_output + (batch_idx * max_box_num + resCount) * 9; data[0] = be0; data[1] = be1; data[2] = be2; data[3] = be3; data[4] = be4; data[5] = be5; data[6] = yaw; data[7] = dev_cls[0]; data[8] = dev_cls[1]; } } void decodeBbox3DLaunch( const int batch_size, const float *cls_input, const float *box_input, const float *dir_cls_input, float *anchors, float *anchors_bottom_height, float *bndbox_output, int *object_counter, const float min_x_range, const float max_x_range, const float min_y_range, const float max_y_range, const int feature_x_size, const int feature_y_size, const int num_anchors, const int num_classes, const int num_box_values, const float score_thresh, const float dir_offset, const float dir_limit_offset, const int num_dir_bins, cudaStream_t stream) { int bev_size = batch_size * feature_x_size * feature_y_size; dim3 threads (num_anchors); dim3 blocks (bev_size); postprocess_kernal<<>> (cls_input, box_input, dir_cls_input, anchors, anchors_bottom_height, bndbox_output, object_counter, min_x_range, max_x_range, min_y_range, max_y_range, feature_x_size, feature_y_size, num_anchors, num_classes, num_box_values, score_thresh, dir_offset, dir_limit_offset, num_dir_bins); checkCudaErrors(cudaGetLastError()); } } // namespace plugin } // namespace nvinfer1