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);