Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added docs/source/_images/roi-exclude-car.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/source/_images/roi-include-car.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
44 changes: 39 additions & 5 deletions docs/source/elements/gvawatermark.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,18 +144,35 @@ Controls the size of text labels displayed on detected objects.

*The default triplex font provides good readability*

### FPS Display
### Label Filtering

**Average FPS Display (`displ-avgfps=true`)**
![Show FPS](../_images/show-avg-fps.png)
You can selectively show or hide detected objects based on their labels using filtering parameters:

*Displays average FPS counter when `gvafpscounter` element is present in pipeline*
**Include Labels (`show-roi=person:car:truck`)**
- Only objects with labels "person", "car", or "truck" will be displayed
- All other detected objects will be hidden
- Useful for focusing on specific object types

e.g `displ-cfg=show-labels=true,show-roi=car`
![Car label included](../_images/roi-include-car.png)

**Exclude Labels (`hide-roi=bottle:cup:laptop`)**
- Objects with labels "bottle", "cup", or "laptop" will be hidden
- All other detected objects will be displayed
- Useful for removing distracting or irrelevant objects from the display

e.g `displ-cfg=show-labels=true,hide-roi=car`
![Car label excluded](../_images/roi-exclude-car.png)

**Filter Priority**
- If both `show-roi` and `hide-roi` are specified, `show-roi` takes precedence
- Empty lists mean no filtering is applied

### Configuration Examples

```bash
# Minimal labels with smaller font
displ-cfg=show-labels=false
displ-cfg=show-labels=true,show-roi=false

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

# Complete custom styling
displ-cfg=font-scale=1.5,thickness=3,color-idx=2,font-type=complex,draw-txt-bg=true

# Show only specific object types
displ-cfg=show-labels=true,show-roi=person:car:truck

# Hide specific object types
displ-cfg=show-labels=true,hide-roi=bottle:cup:laptop

# Combine filtering with styling
displ-cfg=show-labels=true,show-roi=person:car,font-scale=1.2,color-idx=1
```

### FPS Display

**Average FPS Display (`displ-avgfps=true`)**
![Show FPS](../_images/show-avg-fps.png)

*Displays average FPS counter when `gvafpscounter` element is present in pipeline*

106 changes: 67 additions & 39 deletions src/monolithic/gst/elements/gvawatermark/gstgvawatermarkimpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@

#include <array>
#include <exception>
#include <optional>
#include <string>
#include <typeinfo>
#if !defined(ENABLE_VAAPI) || defined(_WIN32)
Expand Down Expand Up @@ -146,6 +147,8 @@ struct Impl {
const GVA::Rect<double> &rectangle, std::vector<render::Prim> &prims) const;
void find_gvafpscounter_element();
void parse_displ_config();
inline bool is_ROI_filtered_out(const std::string &label) const;

std::unique_ptr<Renderer> createRenderer(std::shared_ptr<ColorConverter> converter);

std::unique_ptr<Renderer> createGPURenderer(dlstreamer::ImageFormat format,
Expand Down Expand Up @@ -192,6 +195,8 @@ struct Impl {
uint thickness = DEFAULT_THICKNESS;
int font_type = cv::FONT_HERSHEY_TRIPLEX;
double font_scale = DEFAULT_TEXT_SCALE;
std::optional<std::unordered_set<std::string>> include_labels_filter;
std::optional<std::unordered_set<std::string>> exclude_labels_filter;
} _displCfg;
};

Expand Down Expand Up @@ -899,54 +904,62 @@ bool Impl::render_va(cv::Mat *buffer) {
return true;
}

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

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

clip_rect(rect.x, rect.y, rect.w, rect.h, _vinfo);
auto rect_u32 = roi.rect();
GVA::Rect<double> rect = {safe_convert<double>(rect_u32.x), safe_convert<double>(rect_u32.y),
safe_convert<double>(rect_u32.w), safe_convert<double>(rect_u32.h)};

std::ostringstream text;
const int object_id = roi.object_id();
if (object_id > 0) {
text << object_id << ": ";
color_index = object_id;
}
clip_rect(rect.x, rect.y, rect.w, rect.h, _vinfo);

if (roi.label().size() > 1) {
appendStr(text, roi.label());
text << int(roi.confidence() * 100) << "%";
}
std::ostringstream text;
const int object_id = roi.object_id();
if (object_id > 0) {
text << object_id << ": ";
color_index = object_id;
}

// Prepare primitives for tensors
for (auto &tensor : roi.tensors()) {
preparePrimsForTensor(tensor, rect, prims, color_index);
if (!tensor.is_detection()) {
appendStr(text, tensor.label());
if (roi.label().size() > 1) {
appendStr(text, roi.label());
text << int(roi.confidence() * 100) << "%";
}
}

// set color
Color color = indexToColor(color_index);
if (_displCfg.color_idx != DEFAULT_COLOR_IDX)
color = _default_color;

// put rectangle
cv::Rect bbox_rect(rect.x, rect.y, rect.w, rect.h);
if (!_obb)
prims.emplace_back(render::Rect(bbox_rect, color, _displCfg.thickness, roi.rotation()));

// put text
if (_displCfg.show_labels)
if (text.str().size() != 0) {
cv::Point2f pos(rect.x, rect.y - 5.f);
if (pos.y < 0)
pos.y = rect.y + 30.f;
prims.emplace_back(render::Text(text.str(), pos, _displCfg.font_type, _displCfg.font_scale, color));
// Prepare primitives for tensors
for (auto &tensor : roi.tensors()) {
preparePrimsForTensor(tensor, rect, prims, color_index);
if (!tensor.is_detection()) {
appendStr(text, tensor.label());
}
}

// set color
Color color = indexToColor(color_index);
if (_displCfg.color_idx != DEFAULT_COLOR_IDX)
color = _default_color;

// put rectangle
cv::Rect bbox_rect(rect.x, rect.y, rect.w, rect.h);
if (!_obb)
prims.emplace_back(render::Rect(bbox_rect, color, _displCfg.thickness, roi.rotation()));

// put text
if (_displCfg.show_labels)
if (text.str().size() != 0) {
cv::Point2f pos(rect.x, rect.y - 5.f);
if (pos.y < 0)
pos.y = rect.y + 30.f;
prims.emplace_back(render::Text(text.str(), pos, _displCfg.font_type, _displCfg.font_scale, color));
}
}

// put avg-fps from gvafpscounter element
if (_displ_avgfps) {
std::ostringstream fpstext;
Expand Down Expand Up @@ -1195,6 +1208,21 @@ void Impl::parse_displ_config() {
_displCfg.draw_text_background = (iter->second != "false");
cfg.erase(iter);
}
if (iter = cfg.find("show-roi"); iter != cfg.end()) {
_displCfg.include_labels_filter = std::unordered_set<std::string>();
Utils::parseFilterConfig(iter->second, *_displCfg.include_labels_filter);
cfg.erase(iter);
}
if (iter = cfg.find("hide-roi"); iter != cfg.end()) {
if (_displCfg.include_labels_filter.has_value() && !(_displCfg.include_labels_filter->empty())) {
GST_WARNING("[gvawatermarkimpl] Both 'show-roi' and 'hide-roi' parameters are set, "
"'hide-roi' will be ignored.");
} else {
_displCfg.exclude_labels_filter = std::unordered_set<std::string>();
Utils::parseFilterConfig(iter->second, *_displCfg.exclude_labels_filter);
}
cfg.erase(iter);
}
}
if (iter = cfg.find("thickness"); iter != cfg.end()) {
_displCfg.thickness = std::stoi(iter->second);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,14 @@ enum { PROP_0, PROP_DEVICE, PROP_OBB, PROP_DISPL_AVGFPS, PROP_DISPL_CFG };
"script_simplex, script_complex), default triplex\n" \
"\t\t\tdraw-txt-bg=<bool> enable or disable displaying text labels background, by enabling it the text color " \
"is set to white, default false\n" \
"\t\t\tshow-roi=<string> colon-separated list of labels to include (only these objects will be shown), " \
"default empty\n" \
"\t\t\thide-roi=<string> colon-separated list of labels to exclude (these objects will be hidden), default " \
"empty\n" \
"\t\t\te.g.: displ-cfg=show-labels=false\n" \
"\t\t\te.g.: displ-cfg=font-scale=0.5,thickness=3,color-idx=2,font-type=simplex"
"\t\t\te.g.: displ-cfg=font-scale=0.5,thickness=3,color-idx=2,font-type=simplex\n" \
"\t\t\te.g.: displ-cfg=show-labels=true,show-roi=person:car:truck\n" \
"\t\t\te.g.: displ-cfg=show-labels=true,hide-roi=bottle:cup"

G_END_DECLS

Expand Down
11 changes: 10 additions & 1 deletion src/utils/utils.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (C) 2018-2025 Intel Corporation
* Copyright (C) 2018-2026 Intel Corporation
*
* SPDX-License-Identifier: MIT
******************************************************************************/
Expand Down Expand Up @@ -46,6 +46,15 @@ std::vector<std::string> splitString(const std::string &input, char delimiter) {
return tokens;
}

void parseFilterConfig(const std::string &config_str, std::unordered_set<std::string> &filtered_set, char delimiter) {
auto labels = splitString(config_str, delimiter);
for (const auto &label : labels) {
if (filtered_set.count(label) == 0) {
filtered_set.insert(label);
}
}
}

std::map<std::string, std::string> stringToMap(const std::string &s, char rec_delim /*= ','*/,
char kv_delim /*= '='*/) {
std::string key, val;
Expand Down
14 changes: 13 additions & 1 deletion src/utils/utils.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (C) 2018-2025 Intel Corporation
* Copyright (C) 2018-2026 Intel Corporation
*
* SPDX-License-Identifier: MIT
******************************************************************************/
Expand All @@ -16,6 +16,7 @@
#include <set>
#include <sstream>
#include <string>
#include <unordered_set>
#include <vector>

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

/**
* Parses a label filter configuration string in the format `label1:label2:label3:...`.
* Labels values are added to the output set for filtering.
*
* @param config_str The configuration string to parse (e.g., "person:car:bike").
* @param filtered_set Output set that will contain only the relevant labels.
* @param delimiter The delimiter used to separate label entries (default is ':').
*/
void parseFilterConfig(const std::string &config_str, std::unordered_set<std::string> &filtered_set,
char delimiter = ':');

/**
* Converts string in format `key1=val1,key2=val2,...` to key/value pairs.
*
Expand Down
Loading