18 std::vector<unsigned int> range(k);
19 std::iota(range.begin(), range.end(), 0);
23 void TopKSort(
unsigned int k,
unsigned int* indices,
const float* values,
unsigned int numElement)
25 std::partial_sort(indices, indices + k, indices + numElement,
26 [&values](
unsigned int i,
unsigned int j) {
return values[i] > values[j]; });
36 float areaI = (boxI[yMax] - boxI[yMin]) * (boxI[xMax] - boxI[xMin]);
37 float areaJ = (boxJ[yMax] - boxJ[yMin]) * (boxJ[xMax] - boxJ[xMin]);
38 float yMinIntersection = std::max(boxI[yMin], boxJ[yMin]);
39 float xMinIntersection = std::max(boxI[xMin], boxJ[xMin]);
40 float yMaxIntersection = std::min(boxI[yMax], boxJ[yMax]);
41 float xMaxIntersection = std::min(boxI[xMax], boxJ[xMax]);
42 float areaIntersection = std::max(yMaxIntersection - yMinIntersection, 0.0f) *
43 std::max(xMaxIntersection - xMinIntersection, 0.0f);
44 float areaUnion = areaI + areaJ - areaIntersection;
45 return areaIntersection / areaUnion;
49 const std::vector<float>& boxCorners,
50 const std::vector<float>& scores,
51 float nmsScoreThreshold,
52 unsigned int maxDetection,
53 float nmsIouThreshold)
56 std::vector<float> scoresAboveThreshold;
57 std::vector<unsigned int> indicesAboveThreshold;
58 for (
unsigned int i = 0; i < numBoxes; ++i)
60 if (scores[i] >= nmsScoreThreshold)
62 scoresAboveThreshold.push_back(scores[i]);
63 indicesAboveThreshold.push_back(i);
68 unsigned int numAboveThreshold = armnn::numeric_cast<unsigned int>(scoresAboveThreshold.size());
69 std::vector<unsigned int> sortedIndices =
GenerateRangeK(numAboveThreshold);
70 TopKSort(numAboveThreshold, sortedIndices.data(), scoresAboveThreshold.data(), numAboveThreshold);
73 unsigned int numOutput = std::min(maxDetection, numAboveThreshold);
74 std::vector<unsigned int> outputIndices;
75 std::vector<bool> visited(numAboveThreshold,
false);
78 for (
unsigned int i = 0; i < numAboveThreshold; ++i)
80 if (outputIndices.size() >= numOutput)
84 if (!visited[sortedIndices[i]])
86 outputIndices.push_back(indicesAboveThreshold[sortedIndices[i]]);
87 for (
unsigned int j = i + 1; j < numAboveThreshold; ++j)
89 unsigned int iIndex = indicesAboveThreshold[sortedIndices[i]] * 4;
90 unsigned int jIndex = indicesAboveThreshold[sortedIndices[j]] * 4;
93 visited[sortedIndices[j]] =
true;
102 unsigned int numSelected,
103 const std::vector<float>& boxCorners,
104 const std::vector<unsigned int>& outputIndices,
105 const std::vector<unsigned int>& selectedBoxes,
106 const std::vector<unsigned int>& selectedClasses,
107 const std::vector<float>& selectedScores,
108 float* detectionBoxes,
109 float* detectionScores,
110 float* detectionClasses,
111 float* numDetections)
113 for (
unsigned int i = 0; i < numOutput; ++i)
115 unsigned int boxIndex = i * 4;
118 unsigned int boxCornorIndex = selectedBoxes[outputIndices[i]] * 4;
119 detectionScores[i] = selectedScores[outputIndices[i]];
120 detectionClasses[i] = armnn::numeric_cast<float>(selectedClasses[outputIndices[i]]);
121 detectionBoxes[boxIndex] = boxCorners[boxCornorIndex];
122 detectionBoxes[boxIndex + 1] = boxCorners[boxCornorIndex + 1];
123 detectionBoxes[boxIndex + 2] = boxCorners[boxCornorIndex + 2];
124 detectionBoxes[boxIndex + 3] = boxCorners[boxCornorIndex + 3];
128 detectionScores[i] = 0.0f;
129 detectionClasses[i] = 0.0f;
130 detectionBoxes[boxIndex] = 0.0f;
131 detectionBoxes[boxIndex + 1] = 0.0f;
132 detectionBoxes[boxIndex + 2] = 0.0f;
133 detectionBoxes[boxIndex + 3] = 0.0f;
136 numDetections[0] = armnn::numeric_cast<float>(numSelected);
150 float* detectionBoxes,
151 float* detectionClasses,
152 float* detectionScores,
153 float* numDetections)
160 const unsigned int numBoxes = boxEncodingsInfo.
GetShape()[1];
163 for (
unsigned int i = 0; i < numBoxes; ++i)
166 float boxEncodingY = boxEncodings.
Get();
167 float anchorY = anchors.
Get();
173 float boxEncodingX = boxEncodings.
Get();
174 float anchorX = anchors.
Get();
180 float boxEncodingH = boxEncodings.
Get();
181 float anchorH = anchors.
Get();
187 float boxEncodingW = boxEncodings.
Get();
188 float anchorW = anchors.
Get();
193 float yCentre = boxEncodingY / desc.
m_ScaleY * anchorH + anchorY;
194 float xCentre = boxEncodingX / desc.
m_ScaleX * anchorW + anchorX;
196 float halfH = 0.5f * expf(boxEncodingH / desc.
m_ScaleH) * anchorH;
197 float halfW = 0.5f * expf(boxEncodingW / desc.
m_ScaleW) * anchorW;
199 unsigned int indexY = i * 4;
200 unsigned int indexX = indexY + 1;
201 unsigned int indexH = indexX + 1;
202 unsigned int indexW = indexH + 1;
205 boxCorners[indexY] = yCentre - halfH;
207 boxCorners[indexX] = xCentre - halfW;
209 boxCorners[indexH] = yCentre + halfH;
211 boxCorners[indexW] = xCentre + halfW;
217 std::vector<float> decodedScores;
218 decodedScores.reserve(numScores);
220 for (
unsigned int i = 0u; i < numScores; ++i)
222 decodedScores.emplace_back(scores.
Get());
231 std::vector<float> classScores(numBoxes);
233 std::vector<unsigned int> selectedBoxesAfterNms;
234 selectedBoxesAfterNms.reserve(numBoxes);
236 std::vector<float> selectedScoresAfterNms;
237 selectedBoxesAfterNms.reserve(numScores);
239 std::vector<unsigned int> selectedClasses;
244 for (
unsigned int i = 0; i < numBoxes; ++i)
246 classScores[i] = decodedScores[i * numClassesWithBg + c + 1];
255 for (
unsigned int i = 0; i < selectedIndices.size(); ++i)
257 selectedBoxesAfterNms.push_back(selectedIndices[i]);
258 selectedScoresAfterNms.push_back(classScores[selectedIndices[i]]);
259 selectedClasses.push_back(c);
264 unsigned int numSelected = armnn::numeric_cast<unsigned int>(selectedBoxesAfterNms.size());
268 std::vector<unsigned int> outputIndices =
GenerateRangeK(numSelected);
269 TopKSort(numOutput, outputIndices.data(), selectedScoresAfterNms.data(), numSelected);
272 selectedBoxesAfterNms, selectedClasses, selectedScoresAfterNms,
273 detectionBoxes, detectionScores, detectionClasses, numDetections);
281 std::vector<float> maxScores;
282 std::vector<unsigned int>boxIndices;
283 std::vector<unsigned int>maxScoreClasses;
285 for (
unsigned int box = 0; box < numBoxes; ++box)
287 unsigned int scoreIndex = box * numClassesWithBg + 1;
291 TopKSort(numClassesPerBox, maxScoreIndices.data(),
294 for (
unsigned int i = 0; i < numClassesPerBox; ++i)
296 maxScores.push_back(decodedScores[scoreIndex + maxScoreIndices[i]]);
297 maxScoreClasses.push_back(maxScoreIndices[i]);
298 boxIndices.push_back(box);
303 std::vector<unsigned int> selectedIndices =
NonMaxSuppression(numBoxes, boxCorners, maxScores,
308 unsigned int numSelected = armnn::numeric_cast<unsigned int>(selectedIndices.size());
312 boxIndices, maxScoreClasses, maxScores,
313 detectionBoxes, detectionScores, detectionClasses, numDetections);
virtual IType Get() const =0
unsigned int GetNumElements() const
const TensorShape & GetShape() const
Copyright (c) 2021 ARM Limited and Contributors.
void TopKSort(unsigned int k, unsigned int *indices, const float *values, unsigned int numElement)
void DetectionPostProcess(const TensorInfo &boxEncodingsInfo, const TensorInfo &scoresInfo, const TensorInfo &, const TensorInfo &detectionBoxesInfo, const TensorInfo &, const TensorInfo &, const TensorInfo &, const DetectionPostProcessDescriptor &desc, Decoder< float > &boxEncodings, Decoder< float > &scores, Decoder< float > &anchors, float *detectionBoxes, float *detectionClasses, float *detectionScores, float *numDetections)
float IntersectionOverUnion(const float *boxI, const float *boxJ)
std::vector< unsigned int > NonMaxSuppression(unsigned int numBoxes, const std::vector< float > &boxCorners, const std::vector< float > &scores, float nmsScoreThreshold, unsigned int maxDetection, float nmsIouThreshold)
void AllocateOutputData(unsigned int numOutput, unsigned int numSelected, const std::vector< float > &boxCorners, const std::vector< unsigned int > &outputIndices, const std::vector< unsigned int > &selectedBoxes, const std::vector< unsigned int > &selectedClasses, const std::vector< float > &selectedScores, float *detectionBoxes, float *detectionScores, float *detectionClasses, float *numDetections)
std::vector< unsigned int > GenerateRangeK(unsigned int k)
uint32_t m_NumClasses
Number of classes.
float m_NmsScoreThreshold
NMS score threshold.
float m_NmsIouThreshold
Intersection over union threshold.
float m_ScaleY
Center size encoding scale y.
uint32_t m_DetectionsPerClass
Detections per classes, used in Regular NMS.
bool m_UseRegularNms
Use Regular NMS.
uint32_t m_MaxClassesPerDetection
Maximum numbers of classes per detection, used in Fast NMS.
float m_ScaleH
Center size encoding scale height.
float m_ScaleW
Center size encoding scale weight.
float m_ScaleX
Center size encoding scale x.
uint32_t m_MaxDetections
Maximum numbers of detections.