Files
wehub-resource-sync c8a779b1bb
Docker Image CI / build-ubuntu2004 (push) Waiting to run
chore: import upstream snapshot with attribution
2026-07-13 13:36:55 +08:00

291 lines
11 KiB
Plaintext

/*
* 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 "common/kernels/kernel.h"
#include <algorithm>
#include <array>
#include <math.h>
#include <stdio.h>
namespace nvinfer1
{
namespace plugin
{
using std::max;
using std::min;
// BBD2P KERNEL
template <typename T_DELTAS,
DLayout_t L_DELTAS,
typename TV_PROPOSALS,
DLayout_t L_PROPOSALS,
typename T_FGSCORES,
DLayout_t L_FGSCORES>
__global__ void bboxDeltas2Proposals_kernel(
int N,
int A,
int H,
int W,
const float* __restrict__ anchors,
const float* __restrict__ imInfo,
int featureStride,
float minSize,
const T_DELTAS* __restrict__ deltas,
TV_PROPOSALS* __restrict__ proposals,
T_FGSCORES* __restrict__ scores)
{
int tid = threadIdx.x + blockIdx.x * blockDim.x;
if (tid < N * A * H * W)
{ // TODO this can be a loop.
// Find out the index of bounding box for the output
int cnt = tid;
// width index
int w = cnt % W;
cnt = cnt / W;
// height index
int h = cnt % H;
cnt = cnt / H;
// anchor box index
int a = cnt % A;
cnt = cnt / A;
// batch index
int n = cnt;
int hw = h * W + w;
// Get the height and width of the original input image
float imHeight = imInfo[3 * n];
float imWidth = imInfo[3 * n + 1];
// Point to the right anchor box
float4 anchor = ((float4*) anchors)[a];
// Get anchor box coordinates
float a_ctr_x = anchor.x;
float a_ctr_y = anchor.y;
float a_w = anchor.z;
float a_h = anchor.w;
// NCHW format
// Find out the starting position of the bounding box in the input (predicted bounding box offsets)
int id = ((tid - hw) * 4) + hw;
T_DELTAS dx;
T_DELTAS dy;
T_DELTAS dw;
T_DELTAS dh;
if (L_DELTAS == NCHW)
{
// The offsets between adjacent coordinates on linear memory is H * W
dx = deltas[id];
dy = deltas[id + 1 * H * W];
dw = deltas[id + 2 * H * W];
dh = deltas[id + 3 * H * W];
}
// NC4HW format
else if (L_DELTAS == NC4HW)
{
dx = deltas[tid * 4 + 0];
dy = deltas[tid * 4 + 1];
dw = deltas[tid * 4 + 2];
dh = deltas[tid * 4 + 3];
}
/*
* Calculate the coordinates of decoded bounding box on the original input image scale
* Only works if param.minBoxSize == param.featureStride
*/
float ctr_x = a_ctr_x + w * featureStride;
float ctr_y = a_ctr_y + h * featureStride;
// float ctr_x = (w + 0.5) * featureStride;
// float ctr_y = (h + 0.5) * featureStride;
/*
* Decode the predicted bounding box
* The decoded bounding boxes has coordinates of [x_topleft, y_topleft, x_bottomright, y_bottomright]
* The units are in pixels
*/
ctr_x = ctr_x + dx * a_w;
ctr_y = ctr_y + dy * a_h;
float b_w = __expf(dw) * a_w;
float b_h = __expf(dh) * a_h;
float bx = ctr_x - (b_w / 2);
float by = ctr_y - (b_h / 2);
float bz = ctr_x + (b_w / 2);
float bw = ctr_y + (b_h / 2);
TV_PROPOSALS bbox;
// Make sure that the decoded bouding box go outside of the original input image
bbox.x = fminf(fmaxf(bx, 0.0f), imWidth - 1.0f);
bbox.y = fminf(fmaxf(by, 0.0f), imHeight - 1.0f);
bbox.z = fminf(fmaxf(bz, 0.0f), imWidth - 1.0f);
bbox.w = fminf(fmaxf(bw, 0.0f), imHeight - 1.0f);
// Put the decoded bounding box information to the outputs
if (L_PROPOSALS == NC4HW)
{
proposals[tid] = bbox;
}
int ininf = 0xff800000;
float ninf = *(float*) &ininf;
// minBoxSize at the original input image scale
float scaledMinSize = minSize * imInfo[3 * n + 2];
// Set the objectness score to -inf if the predicted bounding box has edgth length less than the minimal box size expected.
if (bbox.z - bbox.x + 1 < scaledMinSize || bbox.w - bbox.y + 1 < scaledMinSize)
{
if (L_FGSCORES == NCHW)
scores[tid] = ninf;
}
}
}
// BBD2P KERNEL LAUNCHER
template <typename T_DELTAS,
DLayout_t L_DELTAS,
typename TV_PROPOSALS,
DLayout_t L_PROPOSALS,
typename T_FGSCORES,
DLayout_t L_FGSCORES>
pluginStatus_t bboxDeltas2Proposals_gpu(cudaStream_t stream,
int N,
int A,
int H,
int W,
const float* imInfo,
int featureStride,
float minBoxSize,
const float* anchors,
const void* deltas,
void* propos,
void* scores)
{
const int BS = 32;
const int GS = ((N * A * H * W) + BS - 1) / BS;
bboxDeltas2Proposals_kernel<T_DELTAS, L_DELTAS, TV_PROPOSALS, L_PROPOSALS, T_FGSCORES, L_FGSCORES><<<GS, BS, 0, stream>>>(N, A, H, W,
anchors,
imInfo,
featureStride,
minBoxSize,
(T_DELTAS*) deltas,
(TV_PROPOSALS*) propos,
(T_FGSCORES*) scores);
DEBUG_PRINTF("&&&& [bboxD2P] POST LAUNCH\n");
DEBUG_PRINTF("&&&& [bboxD2P] PROPOS %u\n", hash(propos, N * A * H * W * 4 * sizeof(float)));
CSC(cudaGetLastError(), STATUS_FAILURE);
return STATUS_SUCCESS;
}
// BBD2P LAUNCH CONFIG {{{
typedef pluginStatus_t (*bd2pFun)(cudaStream_t,
int,
int,
int,
int,
const float*,
int,
float,
const float*,
const void*,
void*,
void*);
struct bd2pLaunchConfig
{
DataType t_deltas;
DLayout_t l_deltas;
DataType t_proposals;
DLayout_t l_proposals;
DataType t_scores;
DLayout_t l_scores;
bd2pFun function;
bd2pLaunchConfig(DataType t_deltas, DLayout_t l_deltas, DataType t_proposals, DLayout_t l_proposals,
DataType t_scores, DLayout_t l_scores)
: t_deltas(t_deltas)
, l_deltas(l_deltas)
, t_proposals(t_proposals)
, l_proposals(l_proposals)
, t_scores(t_scores)
, l_scores(l_scores)
, function(nullptr)
{
}
bd2pLaunchConfig(DataType t_deltas, DLayout_t l_deltas, DataType t_proposals, DLayout_t l_proposals, DataType t_scores, DLayout_t l_scores, bd2pFun function)
: t_deltas(t_deltas)
, l_deltas(l_deltas)
, t_proposals(t_proposals)
, l_proposals(l_proposals)
, t_scores(t_scores)
, l_scores(l_scores)
, function(function)
{
}
bool operator==(bd2pLaunchConfig const& other) const
{
return t_deltas == other.t_deltas && l_deltas == other.l_deltas && t_proposals == other.t_proposals && l_proposals == other.l_proposals && t_scores == other.t_scores && l_scores == other.l_scores;
}
};
#define FLOAT32 nvinfer1::DataType::kFLOAT
static std::array<bd2pLaunchConfig, 2> bd2pLCOptions = {
bd2pLaunchConfig(FLOAT32, NC4HW, FLOAT32, NC4HW, FLOAT32, NCHW, bboxDeltas2Proposals_gpu<float, NC4HW, float4, NC4HW, float, NCHW>),
bd2pLaunchConfig(FLOAT32, NCHW, FLOAT32, NC4HW, FLOAT32, NCHW, bboxDeltas2Proposals_gpu<float, NCHW, float4, NC4HW, float, NCHW>)};
// BBD2P
pluginStatus_t bboxDeltas2Proposals(cudaStream_t stream,
const int N,
const int A,
const int H,
const int W,
const int featureStride,
const float minBoxSize,
const float* imInfo,
const float* anchors,
const DataType t_deltas,
const DLayout_t l_deltas,
const void* deltas,
const DataType t_proposals,
const DLayout_t l_proposals,
void* proposals,
const DataType t_scores,
const DLayout_t l_scores,
void* scores)
{
bd2pLaunchConfig lc = bd2pLaunchConfig(t_deltas, l_deltas, t_proposals, l_proposals, t_scores, l_scores);
for (unsigned i = 0; i < bd2pLCOptions.size(); i++)
{
if (lc == bd2pLCOptions[i])
{
DEBUG_PRINTF("BBD2P kernel %d\n", i);
return bd2pLCOptions[i].function(stream,
N, A, H, W,
imInfo,
featureStride,
minBoxSize,
anchors,
deltas,
proposals,
scores);
}
}
return STATUS_BAD_PARAM;
}
} // namespace plugin
} // namespace nvinfer1