Skip to content

Commit e2fc774

Browse files
committed
[GST gvawatermark] Add inclusive/exclusive label filtering
Implement object label filtering functionality that allows users to control which detected objects are highlighted with watermark based on their classification labels. - Add include-labels and exclude-labels parameters to displ-cfg - Support colon-delimited label specification (e.g., "person:car:bicycle") - Precedence logic where inclusion filters above exclusion filters - Add parseFilterConfig utility function for label parsing - Update documentation with filtering parameter usage examples Signed-off-by: Walid <walid.aly@intel.com>
1 parent 0721145 commit e2fc774

File tree

7 files changed

+134
-45
lines changed

7 files changed

+134
-45
lines changed
229 KB
Loading
1.18 MB
Loading

docs/source/elements/gvawatermark.md

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -144,18 +144,35 @@ Controls the size of text labels displayed on detected objects.
144144
145145
*The default triplex font provides good readability*
146146
147-
### FPS Display
147+
### Label Filtering
148148
149-
**Average FPS Display (`displ-avgfps=true`)**
150-
![Show FPS](../_images/show-avg-fps.png)
149+
You can selectively show or hide detected objects based on their labels using filtering parameters:
151150
152-
*Displays average FPS counter when `gvafpscounter` element is present in pipeline*
151+
**Include Labels (`show-roi=person:car:truck`)**
152+
- Only objects with labels "person", "car", or "truck" will be displayed
153+
- All other detected objects will be hidden
154+
- Useful for focusing on specific object types
155+
156+
e.g `displ-cfg=show-labels=true,show-roi=car`
157+
![Car label included](../_images/roi-include-car.png)
158+
159+
**Exclude Labels (`hide-roi=bottle:cup:laptop`)**
160+
- Objects with labels "bottle", "cup", or "laptop" will be hidden
161+
- All other detected objects will be displayed
162+
- Useful for removing distracting or irrelevant objects from the display
163+
164+
e.g `displ-cfg=show-labels=true,hide-roi=car`
165+
![Car label excluded](../_images/roi-exclude-car.png)
166+
167+
**Filter Priority**
168+
- If both `show-roi` and `hide-roi` are specified, `show-roi` takes precedence
169+
- Empty lists mean no filtering is applied
153170
154171
### Configuration Examples
155172
156173
```bash
157174
# Minimal labels with smaller font
158-
displ-cfg=show-labels=false
175+
displ-cfg=show-labels=true,show-roi=false
159176

160177
# Large text with background
161178
displ-cfg=font-scale=2.0,draw-txt-bg=true
@@ -165,4 +182,21 @@ displ-cfg=color-idx=0,thickness=1,font-type=simplex
165182

166183
# Complete custom styling
167184
displ-cfg=font-scale=1.5,thickness=3,color-idx=2,font-type=complex,draw-txt-bg=true
185+
186+
# Show only specific object types
187+
displ-cfg=show-labels=true,show-roi=person:car:truck
188+
189+
# Hide specific object types
190+
displ-cfg=show-labels=true,hide-roi=bottle:cup:laptop
191+
192+
# Combine filtering with styling
193+
displ-cfg=show-labels=true,show-roi=person:car,font-scale=1.2,color-idx=1
168194
```
195+
196+
### FPS Display
197+
198+
**Average FPS Display (`displ-avgfps=true`)**
199+
![Show FPS](../_images/show-avg-fps.png)
200+
201+
*Displays average FPS counter when `gvafpscounter` element is present in pipeline*
202+

src/monolithic/gst/elements/gvawatermark/gstgvawatermarkimpl.cpp

Lines changed: 67 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040

4141
#include <array>
4242
#include <exception>
43+
#include <optional>
4344
#include <string>
4445
#include <typeinfo>
4546
#if !defined(ENABLE_VAAPI) || defined(_WIN32)
@@ -146,6 +147,8 @@ struct Impl {
146147
const GVA::Rect<double> &rectangle, std::vector<render::Prim> &prims) const;
147148
void find_gvafpscounter_element();
148149
void parse_displ_config();
150+
inline bool is_ROI_filtered_out(const std::string &label) const;
151+
149152
std::unique_ptr<Renderer> createRenderer(std::shared_ptr<ColorConverter> converter);
150153

151154
std::unique_ptr<Renderer> createGPURenderer(dlstreamer::ImageFormat format,
@@ -192,6 +195,8 @@ struct Impl {
192195
uint thickness = DEFAULT_THICKNESS;
193196
int font_type = cv::FONT_HERSHEY_TRIPLEX;
194197
double font_scale = DEFAULT_TEXT_SCALE;
198+
std::optional<std::unordered_set<std::string>> include_labels_filter;
199+
std::optional<std::unordered_set<std::string>> exclude_labels_filter;
195200
} _displCfg;
196201
};
197202

@@ -899,54 +904,62 @@ bool Impl::render_va(cv::Mat *buffer) {
899904
return true;
900905
}
901906

902-
void Impl::preparePrimsForRoi(GVA::RegionOfInterest &roi, std::vector<render::Prim> &prims) const {
903-
size_t color_index = roi.label_id();
907+
inline bool Impl::is_ROI_filtered_out(const std::string &label) const {
908+
return _displCfg.include_labels_filter.has_value()
909+
? (_displCfg.include_labels_filter->count(label) == 0)
910+
: (_displCfg.exclude_labels_filter.has_value() && _displCfg.exclude_labels_filter->count(label) != 0);
911+
}
904912

905-
auto rect_u32 = roi.rect();
906-
GVA::Rect<double> rect = {safe_convert<double>(rect_u32.x), safe_convert<double>(rect_u32.y),
907-
safe_convert<double>(rect_u32.w), safe_convert<double>(rect_u32.h)};
913+
void Impl::preparePrimsForRoi(GVA::RegionOfInterest &roi, std::vector<render::Prim> &prims) const {
914+
if (!is_ROI_filtered_out(roi.label())) {
915+
size_t color_index = roi.label_id();
908916

909-
clip_rect(rect.x, rect.y, rect.w, rect.h, _vinfo);
917+
auto rect_u32 = roi.rect();
918+
GVA::Rect<double> rect = {safe_convert<double>(rect_u32.x), safe_convert<double>(rect_u32.y),
919+
safe_convert<double>(rect_u32.w), safe_convert<double>(rect_u32.h)};
910920

911-
std::ostringstream text;
912-
const int object_id = roi.object_id();
913-
if (object_id > 0) {
914-
text << object_id << ": ";
915-
color_index = object_id;
916-
}
921+
clip_rect(rect.x, rect.y, rect.w, rect.h, _vinfo);
917922

918-
if (roi.label().size() > 1) {
919-
appendStr(text, roi.label());
920-
text << int(roi.confidence() * 100) << "%";
921-
}
923+
std::ostringstream text;
924+
const int object_id = roi.object_id();
925+
if (object_id > 0) {
926+
text << object_id << ": ";
927+
color_index = object_id;
928+
}
922929

923-
// Prepare primitives for tensors
924-
for (auto &tensor : roi.tensors()) {
925-
preparePrimsForTensor(tensor, rect, prims, color_index);
926-
if (!tensor.is_detection()) {
927-
appendStr(text, tensor.label());
930+
if (roi.label().size() > 1) {
931+
appendStr(text, roi.label());
932+
text << int(roi.confidence() * 100) << "%";
928933
}
929-
}
930934

931-
// set color
932-
Color color = indexToColor(color_index);
933-
if (_displCfg.color_idx != DEFAULT_COLOR_IDX)
934-
color = _default_color;
935-
936-
// put rectangle
937-
cv::Rect bbox_rect(rect.x, rect.y, rect.w, rect.h);
938-
if (!_obb)
939-
prims.emplace_back(render::Rect(bbox_rect, color, _displCfg.thickness, roi.rotation()));
940-
941-
// put text
942-
if (_displCfg.show_labels)
943-
if (text.str().size() != 0) {
944-
cv::Point2f pos(rect.x, rect.y - 5.f);
945-
if (pos.y < 0)
946-
pos.y = rect.y + 30.f;
947-
prims.emplace_back(render::Text(text.str(), pos, _displCfg.font_type, _displCfg.font_scale, color));
935+
// Prepare primitives for tensors
936+
for (auto &tensor : roi.tensors()) {
937+
preparePrimsForTensor(tensor, rect, prims, color_index);
938+
if (!tensor.is_detection()) {
939+
appendStr(text, tensor.label());
940+
}
948941
}
949942

943+
// set color
944+
Color color = indexToColor(color_index);
945+
if (_displCfg.color_idx != DEFAULT_COLOR_IDX)
946+
color = _default_color;
947+
948+
// put rectangle
949+
cv::Rect bbox_rect(rect.x, rect.y, rect.w, rect.h);
950+
if (!_obb)
951+
prims.emplace_back(render::Rect(bbox_rect, color, _displCfg.thickness, roi.rotation()));
952+
953+
// put text
954+
if (_displCfg.show_labels)
955+
if (text.str().size() != 0) {
956+
cv::Point2f pos(rect.x, rect.y - 5.f);
957+
if (pos.y < 0)
958+
pos.y = rect.y + 30.f;
959+
prims.emplace_back(render::Text(text.str(), pos, _displCfg.font_type, _displCfg.font_scale, color));
960+
}
961+
}
962+
950963
// put avg-fps from gvafpscounter element
951964
if (_displ_avgfps) {
952965
std::ostringstream fpstext;
@@ -1195,6 +1208,21 @@ void Impl::parse_displ_config() {
11951208
_displCfg.draw_text_background = (iter->second != "false");
11961209
cfg.erase(iter);
11971210
}
1211+
if (iter = cfg.find("show-roi"); iter != cfg.end()) {
1212+
_displCfg.include_labels_filter = std::unordered_set<std::string>();
1213+
Utils::parseFilterConfig(iter->second, *_displCfg.include_labels_filter);
1214+
cfg.erase(iter);
1215+
}
1216+
if (iter = cfg.find("hide-roi"); iter != cfg.end()) {
1217+
if (_displCfg.include_labels_filter.has_value() && !(_displCfg.include_labels_filter->empty())) {
1218+
GST_WARNING("[gvawatermarkimpl] Both 'show-roi' and 'hide-roi' parameters are set, "
1219+
"'hide-roi' will be ignored.");
1220+
} else {
1221+
_displCfg.exclude_labels_filter = std::unordered_set<std::string>();
1222+
Utils::parseFilterConfig(iter->second, *_displCfg.exclude_labels_filter);
1223+
}
1224+
cfg.erase(iter);
1225+
}
11981226
}
11991227
if (iter = cfg.find("thickness"); iter != cfg.end()) {
12001228
_displCfg.thickness = std::stoi(iter->second);

src/monolithic/gst/elements/gvawatermark/gstgvawatermarkimpl.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,14 @@ enum { PROP_0, PROP_DEVICE, PROP_OBB, PROP_DISPL_AVGFPS, PROP_DISPL_CFG };
8282
"script_simplex, script_complex), default triplex\n" \
8383
"\t\t\tdraw-txt-bg=<bool> enable or disable displaying text labels background, by enabling it the text color " \
8484
"is set to white, default false\n" \
85+
"\t\t\tshow-roi=<string> colon-separated list of labels to include (only these objects will be shown), " \
86+
"default empty\n" \
87+
"\t\t\thide-roi=<string> colon-separated list of labels to exclude (these objects will be hidden), default " \
88+
"empty\n" \
8589
"\t\t\te.g.: displ-cfg=show-labels=false\n" \
86-
"\t\t\te.g.: displ-cfg=font-scale=0.5,thickness=3,color-idx=2,font-type=simplex"
90+
"\t\t\te.g.: displ-cfg=font-scale=0.5,thickness=3,color-idx=2,font-type=simplex\n" \
91+
"\t\t\te.g.: displ-cfg=show-labels=true,show-roi=person:car:truck\n" \
92+
"\t\t\te.g.: displ-cfg=show-labels=true,hide-roi=bottle:cup"
8793

8894
G_END_DECLS
8995

src/utils/utils.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,15 @@ std::vector<std::string> splitString(const std::string &input, char delimiter) {
4646
return tokens;
4747
}
4848

49+
void parseFilterConfig(const std::string &config_str, std::unordered_set<std::string> &filtered_set, char delimiter) {
50+
auto labels = splitString(config_str, delimiter);
51+
for (const auto &label : labels) {
52+
if (filtered_set.count(label) == 0) {
53+
filtered_set.insert(label);
54+
}
55+
}
56+
}
57+
4958
std::map<std::string, std::string> stringToMap(const std::string &s, char rec_delim /*= ','*/,
5059
char kv_delim /*= '='*/) {
5160
std::string key, val;

src/utils/utils.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <set>
1717
#include <sstream>
1818
#include <string>
19+
#include <unordered_set>
1920
#include <vector>
2021

2122
#ifdef _MSC_VER
@@ -55,6 +56,17 @@ std::string join(Iter begin, Iter end, char delimiter = ',') {
5556
return result.str();
5657
}
5758

59+
/**
60+
* Parses a label filter configuration string in the format `label1:label2:label3:...`.
61+
* Labels values are added to the output set for filtering.
62+
*
63+
* @param config_str The configuration string to parse (e.g., "person:car:bike").
64+
* @param filtered_set Output set that will contain only the relevant labels.
65+
* @param delimiter The delimiter used to separate label entries (default is ':').
66+
*/
67+
void parseFilterConfig(const std::string &config_str, std::unordered_set<std::string> &filtered_set,
68+
char delimiter = ':');
69+
5870
/**
5971
* Converts string in format `key1=val1,key2=val2,...` to key/value pairs.
6072
*

0 commit comments

Comments
 (0)