20 std::vector<unsigned int> range(k);
21 std::iota(range.begin(), range.end(), 0);
25 void TopKSort(
unsigned int k,
unsigned int* indices,
const float* values,
unsigned int numElement)
27 std::partial_sort(indices, indices + k, indices + numElement,
28 [&values](
unsigned int i,
unsigned int j) {
return values[i] > values[j]; });
38 float areaI = (boxI[yMax] - boxI[yMin]) * (boxI[xMax] - boxI[xMin]);
39 float areaJ = (boxJ[yMax] - boxJ[yMin]) * (boxJ[xMax] - boxJ[xMin]);
40 float yMinIntersection = std::max(boxI[yMin], boxJ[yMin]);
41 float xMinIntersection = std::max(boxI[xMin], boxJ[xMin]);
42 float yMaxIntersection = std::min(boxI[yMax], boxJ[yMax]);
43 float xMaxIntersection = std::min(boxI[xMax], boxJ[xMax]);
44 float areaIntersection = std::max(yMaxIntersection - yMinIntersection, 0.0f) *
45 std::max(xMaxIntersection - xMinIntersection, 0.0f);
46 float areaUnion = areaI + areaJ - areaIntersection;
47 return areaIntersection / areaUnion;
51 const std::vector<float>& boxCorners,
52 const std::vector<float>& scores,
53 float nmsScoreThreshold,
54 unsigned int maxDetection,
55 float nmsIouThreshold)
58 std::vector<float> scoresAboveThreshold;
59 std::vector<unsigned int> indicesAboveThreshold;
60 for (
unsigned int i = 0; i < numBoxes; ++i)
62 if (scores[i] >= nmsScoreThreshold)
64 scoresAboveThreshold.push_back(scores[i]);
65 indicesAboveThreshold.push_back(i);
70 unsigned int numAboveThreshold = armnn::numeric_cast<unsigned int>(scoresAboveThreshold.size());
71 std::vector<unsigned int> sortedIndices =
GenerateRangeK(numAboveThreshold);
72 TopKSort(numAboveThreshold, sortedIndices.data(), scoresAboveThreshold.data(), numAboveThreshold);
75 unsigned int numOutput = std::min(maxDetection, numAboveThreshold);
76 std::vector<unsigned int> outputIndices;
77 std::vector<bool> visited(numAboveThreshold,
false);
80 for (
unsigned int i = 0; i < numAboveThreshold; ++i)
82 if (outputIndices.size() >= numOutput)
86 if (!visited[sortedIndices[i]])
88 outputIndices.push_back(indicesAboveThreshold[sortedIndices[i]]);
89 for (
unsigned int j = i + 1; j < numAboveThreshold; ++j)
91 unsigned int iIndex = indicesAboveThreshold[sortedIndices[i]] * 4;
92 unsigned int jIndex = indicesAboveThreshold[sortedIndices[j]] * 4;
95 visited[sortedIndices[j]] =
true;
100 return outputIndices;
104 unsigned int numSelected,
105 const std::vector<float>& boxCorners,
106 const std::vector<unsigned int>& outputIndices,
107 const std::vector<unsigned int>& selectedBoxes,
108 const std::vector<unsigned int>& selectedClasses,
109 const std::vector<float>& selectedScores,
110 float* detectionBoxes,
111 float* detectionScores,
112 float* detectionClasses,
113 float* numDetections)
115 for (
unsigned int i = 0; i < numOutput; ++i)
117 unsigned int boxIndex = i * 4;
120 unsigned int boxCornorIndex = selectedBoxes[outputIndices[i]] * 4;
121 detectionScores[i] = selectedScores[outputIndices[i]];
122 detectionClasses[i] = armnn::numeric_cast<float>(selectedClasses[outputIndices[i]]);
123 detectionBoxes[boxIndex] = boxCorners[boxCornorIndex];
124 detectionBoxes[boxIndex + 1] = boxCorners[boxCornorIndex + 1];
125 detectionBoxes[boxIndex + 2] = boxCorners[boxCornorIndex + 2];
126 detectionBoxes[boxIndex + 3] = boxCorners[boxCornorIndex + 3];
130 detectionScores[i] = 0.0f;
131 detectionClasses[i] = 0.0f;
132 detectionBoxes[boxIndex] = 0.0f;
133 detectionBoxes[boxIndex + 1] = 0.0f;
134 detectionBoxes[boxIndex + 2] = 0.0f;
135 detectionBoxes[boxIndex + 3] = 0.0f;
138 numDetections[0] = armnn::numeric_cast<float>(numSelected);
152 float* detectionBoxes,
153 float* detectionClasses,
154 float* detectionScores,
155 float* numDetections)
157 IgnoreUnused(anchorsInfo, detectionClassesInfo, detectionScoresInfo, numDetectionsInfo);
163 const unsigned int numBoxes = boxEncodingsInfo.
GetShape()[1];
166 for (
unsigned int i = 0; i < numBoxes; ++i)
169 float boxEncodingY = boxEncodings.
Get();
170 float anchorY = anchors.
Get();
176 float boxEncodingX = boxEncodings.
Get();
177 float anchorX = anchors.
Get();
183 float boxEncodingH = boxEncodings.
Get();
184 float anchorH = anchors.
Get();
190 float boxEncodingW = boxEncodings.
Get();
191 float anchorW = anchors.
Get();
196 float yCentre = boxEncodingY / desc.
m_ScaleY * anchorH + anchorY;
197 float xCentre = boxEncodingX / desc.
m_ScaleX * anchorW + anchorX;
199 float halfH = 0.5f * expf(boxEncodingH / desc.
m_ScaleH) * anchorH;
200 float halfW = 0.5f * expf(boxEncodingW / desc.
m_ScaleW) * anchorW;
202 unsigned int indexY = i * 4;
203 unsigned int indexX = indexY + 1;
204 unsigned int indexH = indexX + 1;
205 unsigned int indexW = indexH + 1;
208 boxCorners[indexY] = yCentre - halfH;
210 boxCorners[indexX] = xCentre - halfW;
212 boxCorners[indexH] = yCentre + halfH;
214 boxCorners[indexW] = xCentre + halfW;
223 std::vector<float> decodedScores;
224 decodedScores.reserve(numScores);
226 for (
unsigned int i = 0u; i < numScores; ++i)
228 decodedScores.emplace_back(scores.
Get());
237 std::vector<float> classScores(numBoxes);
239 std::vector<unsigned int> selectedBoxesAfterNms;
240 selectedBoxesAfterNms.reserve(numBoxes);
242 std::vector<float> selectedScoresAfterNms;
243 selectedBoxesAfterNms.reserve(numScores);
245 std::vector<unsigned int> selectedClasses;
250 for (
unsigned int i = 0; i < numBoxes; ++i)
252 classScores[i] = decodedScores[i * numClassesWithBg + c + 1];
261 for (
unsigned int i = 0; i < selectedIndices.size(); ++i)
263 selectedBoxesAfterNms.push_back(selectedIndices[i]);
264 selectedScoresAfterNms.push_back(classScores[selectedIndices[i]]);
265 selectedClasses.push_back(c);
270 unsigned int numSelected = armnn::numeric_cast<unsigned int>(selectedBoxesAfterNms.size());
274 std::vector<unsigned int> outputIndices =
GenerateRangeK(numSelected);
275 TopKSort(numOutput, outputIndices.data(), selectedScoresAfterNms.data(), numSelected);
278 selectedBoxesAfterNms, selectedClasses, selectedScoresAfterNms,
279 detectionBoxes, detectionScores, detectionClasses, numDetections);
287 std::vector<float> maxScores;
288 std::vector<unsigned int>boxIndices;
289 std::vector<unsigned int>maxScoreClasses;
291 for (
unsigned int box = 0; box < numBoxes; ++box)
293 unsigned int scoreIndex = box * numClassesWithBg + 1;
297 TopKSort(numClassesPerBox, maxScoreIndices.data(),
300 for (
unsigned int i = 0; i < numClassesPerBox; ++i)
302 maxScores.push_back(decodedScores[scoreIndex + maxScoreIndices[i]]);
303 maxScoreClasses.push_back(maxScoreIndices[i]);
304 boxIndices.push_back(box);
309 std::vector<unsigned int> selectedIndices =
NonMaxSuppression(numBoxes, boxCorners, maxScores,
314 unsigned int numSelected = armnn::numeric_cast<unsigned int>(selectedIndices.size());
318 boxIndices, maxScoreClasses, maxScores,
319 detectionBoxes, detectionScores, detectionClasses, numDetections);