Skip to content

Commit 16818b0

Browse files
authored
Add detection filtering for SSD wrapper (#207)
* Revisit detections filtering * Refactor predicitons filtering for SSD * Update python implementation * Eliminate extra filtering
1 parent c4e2de9 commit 16818b0

File tree

3 files changed

+55
-27
lines changed

3 files changed

+55
-27
lines changed

model_api/cpp/models/src/detection_model_ssd.cpp

+14-17
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
namespace {
3535
constexpr char saliency_map_name[]{"saliency_map"};
3636
constexpr char feature_vector_name[]{"feature_vector"};
37+
constexpr float box_area_threshold = 1.0f;
3738

3839
struct NumAndStep {
3940
size_t detectionsNum, objectSize;
@@ -83,6 +84,11 @@ std::vector<std::string> filterOutXai(const std::vector<std::string>& names) {
8384
std::copy_if (names.begin(), names.end(), std::back_inserter(filtered), [](const std::string& name){return name != saliency_map_name && name != feature_vector_name;});
8485
return filtered;
8586
}
87+
88+
89+
float clamp_and_round(float val, float min, float max) {
90+
return std::round(std::max(min, std::min(max, val)));
91+
}
8692
}
8793

8894
std::string ModelSSD::ModelType = "ssd";
@@ -214,23 +220,14 @@ std::unique_ptr<ResultBase> ModelSSD::postprocessMultipleOutputs(InferenceResult
214220
desc.confidence = confidence;
215221
desc.labelID = labels[i];
216222
desc.label = getLabelName(desc.labelID);
217-
desc.x = clamp(
218-
round((boxes[i * numAndStep.objectSize] * widthScale - padLeft) * invertedScaleX),
219-
0.f,
220-
floatInputImgWidth);
221-
desc.y = clamp(
222-
round((boxes[i * numAndStep.objectSize + 1] * heightScale - padTop) * invertedScaleY),
223-
0.f,
224-
floatInputImgHeight);
225-
desc.width = clamp(
226-
round((boxes[i * numAndStep.objectSize + 2] * widthScale - padLeft) * invertedScaleX),
227-
0.f,
228-
floatInputImgWidth) - desc.x;
229-
desc.height = clamp(
230-
round((boxes[i * numAndStep.objectSize + 3] * heightScale - padTop) * invertedScaleY),
231-
0.f,
232-
floatInputImgHeight) - desc.y;
233-
result->objects.push_back(desc);
223+
desc.x = clamp_and_round((boxes[i * numAndStep.objectSize] * widthScale - padLeft) * invertedScaleX, 0.f, floatInputImgWidth);
224+
desc.y = clamp_and_round((boxes[i * numAndStep.objectSize + 1] * heightScale - padTop) * invertedScaleY, 0.f, floatInputImgHeight);
225+
desc.width = clamp_and_round((boxes[i * numAndStep.objectSize + 2] * widthScale - padLeft) * invertedScaleX, 0.f, floatInputImgWidth) - desc.x;
226+
desc.height = clamp_and_round((boxes[i * numAndStep.objectSize + 3] * heightScale - padTop) * invertedScaleY, 0.f, floatInputImgHeight) - desc.y;
227+
228+
if (desc.width * desc.height >= box_area_threshold) {
229+
result->objects.push_back(desc);
230+
}
234231
}
235232
}
236233

model_api/python/model_api/models/detection_model.py

+38-8
Original file line numberDiff line numberDiff line change
@@ -104,25 +104,55 @@ def _resize_detections(self, detections, meta):
104104
pad_left = (self.w - round(input_img_widht / inverted_scale_x)) // 2
105105
pad_top = (self.h - round(input_img_height / inverted_scale_y)) // 2
106106

107+
def _clamp_and_round(val, min_value, max_value):
108+
return round(max(min_value, min(max_value, val)))
109+
107110
for detection in detections:
108-
detection.xmin = min(
109-
max(round((detection.xmin * self.w - pad_left) * inverted_scale_x), 0),
111+
detection.xmin = _clamp_and_round(
112+
(detection.xmin * self.w - pad_left) * inverted_scale_x,
113+
0,
110114
input_img_widht,
111115
)
112-
detection.ymin = min(
113-
max(round((detection.ymin * self.h - pad_top) * inverted_scale_y), 0),
116+
detection.ymin = _clamp_and_round(
117+
(detection.ymin * self.h - pad_top) * inverted_scale_y,
118+
0,
114119
input_img_height,
115120
)
116-
detection.xmax = min(
117-
max(round((detection.xmax * self.w - pad_left) * inverted_scale_x), 0),
121+
detection.xmax = _clamp_and_round(
122+
(detection.xmax * self.w - pad_left) * inverted_scale_x,
123+
0,
118124
input_img_widht,
119125
)
120-
detection.ymax = min(
121-
max(round((detection.ymax * self.h - pad_top) * inverted_scale_y), 0),
126+
detection.ymax = _clamp_and_round(
127+
(detection.ymax * self.h - pad_top) * inverted_scale_y,
128+
0,
122129
input_img_height,
123130
)
131+
124132
return detections
125133

134+
def _filter_detections(self, detections, box_area_threshold=0.0):
135+
"""Filters detections by confidence threshold and box size threshold
136+
137+
Args:
138+
detections (List[Detection]): list of detections with coordinates in normalized form
139+
box_area_threshold (float): minimal area of the bounding to be considered
140+
141+
Returns:
142+
- list of detections with confidence above the threshold
143+
"""
144+
filtered_detections = []
145+
for detection in detections:
146+
if (
147+
detection.score < self.confidence_threshold
148+
or (detection.xmax - detection.xmin) * (detection.ymax - detection.ymin)
149+
< box_area_threshold
150+
):
151+
continue
152+
filtered_detections.append(detection)
153+
154+
return filtered_detections
155+
126156
def _add_label_names(self, detections):
127157
"""Adds labels names to detections if they are available
128158

model_api/python/model_api/models/ssd.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ def preprocess(self, inputs):
4141
def postprocess(self, outputs, meta):
4242
detections = self._parse_outputs(outputs)
4343
detections = self._resize_detections(detections, meta)
44+
detections = self._filter_detections(detections, _bbox_area_threshold)
4445
detections = self._add_label_names(detections)
4546
return DetectionResult(
4647
detections,
@@ -74,8 +75,7 @@ def _get_output_parser(
7475
self.raise_error("Unsupported model outputs")
7576

7677
def _parse_outputs(self, outputs):
77-
detections = self.output_parser(outputs)
78-
return [d for d in detections if d.score > self.confidence_threshold]
78+
return self.output_parser(outputs)
7979

8080

8181
def find_layer_by_name(name, layers):
@@ -176,5 +176,6 @@ def __call__(self, outputs):
176176
return detections
177177

178178

179+
_bbox_area_threshold = 1.0
179180
_saliency_map_name = "saliency_map"
180181
_feature_vector_name = "feature_vector"

0 commit comments

Comments
 (0)