Skip to content

Commit e3f46cc

Browse files
Initial media support for G-API background subtraction demo (#3535)
* Switch demo to GFrame input * Refactor MediaCommonCapSrc * Initial media support for G-API bgr subtraction * Initial onevpl suppport * Switch to GFrame * Add flags to readme and help print * Fix background_subtraction_demo_gapi documentation * Round up frame_size by 16 for use_onevpl case. * Update readme * Replace "note:" in readme * Update demos/background_subtraction_demo/cpp_gapi/main.cpp Co-authored-by: Zlobin Vladimir <[email protected]> * Fix warning and add onevpl_pool_size flag * Update demos/background_subtraction_demo/cpp_gapi/README.md Co-authored-by: Zlobin Vladimir <[email protected]> * Update demos/background_subtraction_demo/cpp_gapi/README.md Co-authored-by: Zlobin Vladimir <[email protected]> * Update demos/background_subtraction_demo/cpp_gapi/main.cpp Co-authored-by: Zlobin Vladimir <[email protected]> * Fix comments to review * Update demos/background_subtraction_demo/cpp_gapi/background_subtraction_demo_gapi.hpp Co-authored-by: Zlobin Vladimir <[email protected]> * Update demos/background_subtraction_demo/cpp_gapi/README.md Co-authored-by: Zlobin Vladimir <[email protected]> * Update demos/background_subtraction_demo/cpp_gapi/background_subtraction_demo_gapi.hpp Co-authored-by: Zlobin Vladimir <[email protected]> * Update demos/background_subtraction_demo/cpp_gapi/README.md Co-authored-by: Zlobin Vladimir <[email protected]> * Update background_subtraction_demo_gapi.hpp * Update background_subtraction_demo_gapi.hpp * Update background_subtraction_demo_gapi.hpp * Update README.md * Fix flag message Co-authored-by: Zlobin Vladimir <[email protected]>
1 parent 94a2811 commit e3f46cc

File tree

7 files changed

+164
-13
lines changed

7 files changed

+164
-13
lines changed

demos/background_subtraction_demo/cpp_gapi/README.md

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ This demo shows how to perform background subtraction using G-API.
55
> **NOTE**: Only batch size of 1 is supported.
66
77
## How It Works
8-
The demo application expects an instance-segmentation-security-???? or trimap free background matting based on pixel-level segmentation approach model in the Intermediate Representation (IR) format.
8+
The demo application expects an instance-segmentation-security-???? or trimap free background matting based on pixel-level segmentation approach model in the Intermediate Representation (IR) format. Please note, that there aren't background matting models in `OpenModelZoo` collection.
99

1010
1. for instance segmentation models based on `Mask RCNN` approach:
1111
* One input: `image` for input image.
@@ -54,6 +54,34 @@ omz_converter --list models.lst
5454

5555
> **NOTE**: Refer to the tables [Intel's Pre-Trained Models Device Support](../../../models/intel/device_support.md) and [Public Pre-Trained Models Device Support](../../../models/public/device_support.md) for the details on models inference support at different devices.
5656
57+
58+
### OneVPL Support
59+
60+
Demo provides functionality to use [OneVPL](https://github.com/oneapi-src/oneVPL#-video-processing-library) video decoding.
61+
Example:
62+
```sh
63+
./background_subtraction_demo_gapi/ -m <path_to_model> -i <path_to_video_file> -use_onevpl
64+
```
65+
66+
In order to provide additional configuration paramaters use `-onevpl_params`:
67+
```sh
68+
./background_subtraction_demo_gapi/ -m <path_to_model> -i <path_to_raw_file> -use_onevpl -onevpl_params="mfxImplDescription.mfxDecoderDescription.decoder.CodecID:MFX_CODEC_HEVC"
69+
```
70+
>**NOTE**: Only raw formats such as `h264`, `h265` etc are supported on Linux.
71+
Working with raw formats user always must specify `codec` type via `-onevpl_params`. See example below.
72+
73+
To build OpenCV G-API with `oneVPL` support follow instruction:
74+
[Building G-API with oneVPL Toolkit support](https://github.com/opencv/opencv/wiki/Graph-API#building-with-onevpl-toolkit-support)
75+
76+
#### Troubleshooting
77+
During execution `oneVPL` might report warnings that tell the user that source can be configurable more accurate.
78+
79+
For example:
80+
```
81+
cv::gapi::wip::onevpl::VPLLegacyDecodeEngine::process_error [000001CED3851C70] error: cv::gapi::wip::onevpl::CachedPool::find_free - cannot get free surface from pool, size: 5
82+
```
83+
This might be fixed by increasing pool size using `-onevpl_pool_size` parameter.
84+
5785
## Running
5886

5987
Run the application with the `-h` option to see the following usage message:
@@ -82,6 +110,9 @@ Options:
82110
-blur_bgr Optional. Blur background.
83111
-target_bgr Optional. Background onto which to composite the output (by default to green field).
84112
-u Optional. List of monitors to show initially.
113+
-use_onevpl Optional. Use onevpl video decoding.
114+
-onevpl_params Optional. Parameters for onevpl video decoding. OneVPL source can be fine-grained by providing configuration parameters. Format: <prop name>:<value>,<prop name>:<value> Several important configuration parameters: 'mfxImplDescription.mfxDecoderDescription.decoder.CodecID' values: https://spec.oneapi.io/onevpl/2.7.0/API_ref/VPL_enums.html?highlight=mfx_codec_hevc#codecformatfourcc and 'mfxImplDescription.AccelerationMode' values: https://spec.oneapi.io/onevpl/2.7.0/API_ref/VPL_disp_api_enum.html?highlight=d3d11#mfxaccelerationmode(see `MFXSetConfigFilterProperty` by https://spec.oneapi.io/versions/latest/elements/oneVPL/source/index.html)
115+
-onevpl_pool_size OneVPL source applies this parameter as preallocated frames pool size. 0 leaves frames pool size default for your system. This parameter doesn't have a god default value. It must be adjusted for specific execution (video, model, system ...).
85116
86117
Available target devices: <targets>
87118
```

demos/background_subtraction_demo/cpp_gapi/background_subtraction_demo_gapi.hpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,18 @@ static const char blur_bgr_message[] = "Optional. Blur background.";
3333
static const char target_bgr_message[] =
3434
"Optional. Background onto which to composite the output (by default to green field).";
3535
static const char utilization_monitors_message[] = "Optional. List of monitors to show initially.";
36+
static const char use_onevpl_message[] = "Optional. Use onevpl video decoding.";
37+
static const char onevpl_params_message[] = "Optional. Parameters for onevpl video decoding. "
38+
"OneVPL source can be fine-grained by providing configuration parameters. "
39+
"Format: <prop name>:<value>,<prop name>:<value> "
40+
"Several important configuration parameters: "
41+
"-mfxImplDescription.mfxDecoderDescription.decoder.CodecID "
42+
"values: https://spec.oneapi.io/onevpl/2.7.0/API_ref/VPL_enums.html?highlight=mfx_codec_hevc#codecformatfourcc"
43+
"-mfxImplDescription.AccelerationMode "
44+
"values: https://spec.oneapi.io/onevpl/2.7.0/API_ref/VPL_disp_api_enum.html?highlight=d3d11#mfxaccelerationmode"
45+
"(see `MFXSetConfigFilterProperty` by https://spec.oneapi.io/versions/latest/elements/oneVPL/source/index.html)";
46+
static const char onevpl_pool_size_message[] = "OneVPL source applies this parameter as preallocated frames pool size. 0 leaves frames pool size default for your system. "
47+
"This parameter doesn't have a god default value. It must be adjusted for specific execution (video, model, system, ...).";
3648

3749
DEFINE_bool(h, false, help_message);
3850
DEFINE_string(res, "1280x720", camera_resolution_message);
@@ -47,6 +59,9 @@ DEFINE_bool(no_show, false, no_show_message);
4759
DEFINE_string(target_bgr, "", target_bgr_message);
4860
DEFINE_uint32(blur_bgr, 0, blur_bgr_message);
4961
DEFINE_string(u, "", utilization_monitors_message);
62+
DEFINE_bool(use_onevpl, false, use_onevpl_message);
63+
DEFINE_string(onevpl_params, "", onevpl_params_message);
64+
DEFINE_uint32(onevpl_pool_size, 0, onevpl_pool_size_message);
5065

5166
/**
5267
* \brief This function shows a help message
@@ -74,4 +89,7 @@ static void showUsage() {
7489
std::cout << " -blur_bgr \"<integer>\" " << blur_bgr_message << std::endl;
7590
std::cout << " -target_bgr " << target_bgr_message << std::endl;
7691
std::cout << " -u " << utilization_monitors_message << std::endl;
92+
std::cout << " -use_onevpl " << use_onevpl_message << std::endl;
93+
std::cout << " -onevpl_params " << onevpl_params_message << std::endl;
94+
std::cout << " -onevpl_pool_size " << onevpl_pool_size_message << std::endl;
7795
}

demos/background_subtraction_demo/cpp_gapi/include/custom_kernels.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class NNBGReplacer {
4343
NNBGReplacer() = default;
4444
virtual ~NNBGReplacer() = default;
4545
NNBGReplacer(const std::string& model_path);
46-
virtual cv::GMat replace(cv::GMat, const cv::Size&, cv::GMat) = 0;
46+
virtual cv::GMat replace(cv::GFrame, cv::GMat, const cv::Size&, cv::GMat) = 0;
4747
const std::string& getName() {
4848
return m_tag;
4949
}
@@ -58,7 +58,7 @@ class NNBGReplacer {
5858
class MaskRCNNBGReplacer : public NNBGReplacer {
5959
public:
6060
MaskRCNNBGReplacer(const std::string& model_path);
61-
cv::GMat replace(cv::GMat, const cv::Size&, cv::GMat) override;
61+
cv::GMat replace(cv::GFrame, cv::GMat, const cv::Size&, cv::GMat) override;
6262

6363
private:
6464
std::string m_input_name;
@@ -70,7 +70,7 @@ class MaskRCNNBGReplacer : public NNBGReplacer {
7070
class BGMattingReplacer : public NNBGReplacer {
7171
public:
7272
BGMattingReplacer(const std::string& model_path);
73-
cv::GMat replace(cv::GMat, const cv::Size&, cv::GMat) override;
73+
cv::GMat replace(cv::GFrame, cv::GMat, const cv::Size&, cv::GMat) override;
7474

7575
private:
7676
std::string m_input_name;

demos/background_subtraction_demo/cpp_gapi/main.cpp

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,10 @@
3535
#include <opencv2/gapi/own/assert.hpp>
3636
#include <opencv2/gapi/streaming/source.hpp>
3737
#include <opencv2/gapi/util/optional.hpp>
38+
#include <opencv2/gapi/streaming/onevpl/source.hpp>
3839
#include <opencv2/highgui.hpp>
3940
#include <opencv2/imgproc.hpp>
41+
4042
#include <openvino/openvino.hpp>
4143

4244
#include <monitors/presenter.h>
@@ -82,6 +84,37 @@ static cv::gapi::GKernelPackage getKernelPackage(const std::string& type) {
8284
GAPI_Assert(false && "Unreachable code!");
8385
}
8486

87+
cv::gapi::wip::onevpl::CfgParam createFromString(const std::string &line) {
88+
using namespace cv::gapi::wip;
89+
90+
if (line.empty()) {
91+
throw std::runtime_error("Cannot parse CfgParam from emply line");
92+
}
93+
94+
std::string::size_type name_endline_pos = line.find(':');
95+
if (name_endline_pos == std::string::npos) {
96+
throw std::runtime_error("Cannot parse CfgParam from: " + line +
97+
"\nExpected separator \":\"");
98+
}
99+
100+
std::string name = line.substr(0, name_endline_pos);
101+
std::string value = line.substr(name_endline_pos + 1);
102+
103+
return cv::gapi::wip::onevpl::CfgParam::create(name, value,
104+
/* vpp params strongly optional */
105+
name.find("vpp.") == std::string::npos);
106+
}
107+
108+
static std::vector<cv::gapi::wip::onevpl::CfgParam> parseVPLParams(const std::string& cfg_params) {
109+
std::vector<cv::gapi::wip::onevpl::CfgParam> source_cfgs;
110+
std::stringstream params_list(cfg_params);
111+
std::string line;
112+
while (std::getline(params_list, line, ',')) {
113+
source_cfgs.push_back(createFromString(line));
114+
}
115+
return source_cfgs;
116+
}
117+
85118
} // namespace util
86119

87120
int main(int argc, char* argv[]) {
@@ -117,9 +150,16 @@ int main(int argc, char* argv[]) {
117150
stringToSize(FLAGS_res));
118151
const auto tmp = cap->read();
119152
cv::Size frame_size = cv::Size{tmp.cols, tmp.rows};
153+
// NB: oneVPL source rounds up frame size by 16
154+
// so size might be different from what ImagesCapture reads.
155+
if (FLAGS_use_onevpl) {
156+
frame_size.width = cv::alignSize(frame_size.width, 16);
157+
frame_size.height = cv::alignSize(frame_size.height, 16);
158+
}
120159

121160
cv::GComputation comp([&] {
122-
cv::GMat in;
161+
cv::GFrame in;
162+
cv::GMat bgr = cv::gapi::streaming::BGR(in);
123163
// NB: target_bgr is optional second input which implies a background
124164
// that will change user video background. If user don't specify
125165
// it and specifies --bgr_blur then second input won't be used since
@@ -128,7 +168,7 @@ int main(int argc, char* argv[]) {
128168

129169
cv::GMat bgr_resized;
130170
if (is_blur && FLAGS_target_bgr.empty()) {
131-
bgr_resized = in;
171+
bgr_resized = bgr;
132172
} else {
133173
target_bgr = cv::util::make_optional<cv::GMat>(cv::GMat());
134174
bgr_resized = cv::gapi::resize(target_bgr.value(), frame_size);
@@ -137,7 +177,7 @@ int main(int argc, char* argv[]) {
137177
auto background =
138178
is_blur ? cv::gapi::blur(bgr_resized, cv::Size(FLAGS_blur_bgr, FLAGS_blur_bgr)) : bgr_resized;
139179

140-
auto result = model->replace(in, frame_size, background);
180+
auto result = model->replace(in, bgr, frame_size, background);
141181

142182
auto graph_inputs = cv::GIn(in);
143183
if (target_bgr.has_value()) {
@@ -176,7 +216,19 @@ int main(int argc, char* argv[]) {
176216
0,
177217
std::numeric_limits<size_t>::max(),
178218
stringToSize(FLAGS_res));
179-
auto pipeline_inputs = cv::gin(cv::gapi::wip::make_src<custom::CommonCapSrc>(cap));
219+
cv::gapi::wip::IStreamSource::Ptr media_cap;
220+
if (FLAGS_use_onevpl) {
221+
auto onevpl_params = util::parseVPLParams(FLAGS_onevpl_params);
222+
if (FLAGS_onevpl_pool_size != 0) {
223+
onevpl_params.push_back(
224+
cv::gapi::wip::onevpl::CfgParam::create_frames_pool_size(FLAGS_onevpl_pool_size));
225+
}
226+
media_cap = cv::gapi::wip::make_onevpl_src(FLAGS_i, std::move(onevpl_params));
227+
} else {
228+
media_cap = cv::gapi::wip::make_src<custom::MediaCommonCapSrc>(cap);
229+
}
230+
231+
auto pipeline_inputs = cv::gin(std::move(media_cap));
180232
if (!is_blur && FLAGS_target_bgr.empty()) {
181233
cv::Scalar default_color(155, 255, 120);
182234
pipeline_inputs += cv::gin(cv::Mat(frame_size, CV_8UC3, default_color));

demos/background_subtraction_demo/cpp_gapi/src/custom_kernels.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ custom::MaskRCNNBGReplacer::MaskRCNNBGReplacer(const std::string& model_path) :
169169
}
170170
}
171171

172-
cv::GMat custom::MaskRCNNBGReplacer::replace(cv::GMat in, const cv::Size& in_size, cv::GMat background) {
172+
cv::GMat custom::MaskRCNNBGReplacer::replace(cv::GFrame in, cv::GMat bgr, const cv::Size& in_size, cv::GMat background) {
173173
cv::GInferInputs inputs;
174174
inputs[m_input_name] = in;
175175
auto outputs = cv::gapi::infer<cv::gapi::Generic>(m_tag, inputs);
@@ -181,7 +181,7 @@ cv::GMat custom::MaskRCNNBGReplacer::replace(cv::GMat in, const cv::Size& in_siz
181181
GAPI_Assert(dims.size() == 4u);
182182
auto mask = custom::GCalculateMaskRCNNBGMask::on(in_size, cv::Size(dims[3], dims[2]), labels, boxes, masks);
183183
auto mask3ch = cv::gapi::medianBlur(cv::gapi::merge3(mask, mask, mask), 11);
184-
return (mask3ch & in) + (~mask3ch & background);
184+
return (mask3ch & bgr) + (~mask3ch & background);
185185
}
186186

187187
custom::BGMattingReplacer::BGMattingReplacer(const std::string& model_path) : NNBGReplacer(model_path) {
@@ -196,14 +196,14 @@ custom::BGMattingReplacer::BGMattingReplacer(const std::string& model_path) : NN
196196
m_output_name = m_outputs.begin()->first;
197197
}
198198

199-
cv::GMat custom::BGMattingReplacer::replace(cv::GMat in, const cv::Size& in_size, cv::GMat background) {
199+
cv::GMat custom::BGMattingReplacer::replace(cv::GFrame in, cv::GMat bgr, const cv::Size& in_size, cv::GMat background) {
200200
cv::GInferInputs inputs;
201201
inputs[m_input_name] = in;
202202
auto outputs = cv::gapi::infer<cv::gapi::Generic>(m_tag, inputs);
203203

204204
auto alpha = cv::gapi::resize(custom::GTensorToImg::on(outputs.at(m_output_name)), in_size);
205205
auto alpha3ch = cv::gapi::merge3(alpha, alpha, alpha);
206-
auto in_fp = cv::gapi::convertTo(in, CV_32F);
206+
auto in_fp = cv::gapi::convertTo(bgr, CV_32F);
207207
auto bgr_fp = cv::gapi::convertTo(background, CV_32F);
208208

209209
cv::GScalar one(cv::Scalar::all(1.));

demos/common/cpp_gapi/utils_gapi/include/utils_gapi/stream_source.hpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#include <opencv2/core.hpp>
1010
#include <opencv2/gapi/gmetaarg.hpp>
1111
#include <opencv2/gapi/streaming/source.hpp>
12+
#include <opencv2/gapi/media.hpp>
13+
#include <opencv2/gapi/streaming/cap.hpp>
1214

1315
class ImagesCapture;
1416
namespace cv {
@@ -24,7 +26,7 @@ class CommonCapSrc : public cv::gapi::wip::IStreamSource {
2426
public:
2527
explicit CommonCapSrc(std::shared_ptr<ImagesCapture>& cap);
2628

27-
protected:
29+
public:
2830
std::shared_ptr<ImagesCapture> cap;
2931
cv::Mat first;
3032
bool first_pulled = false;
@@ -34,4 +36,25 @@ class CommonCapSrc : public cv::gapi::wip::IStreamSource {
3436
cv::GMetaArg descr_of() const override;
3537
};
3638

39+
class MediaBGRAdapter final: public cv::MediaFrame::IAdapter {
40+
public:
41+
using Cb = cv::MediaFrame::View::Callback;
42+
43+
explicit MediaBGRAdapter(cv::Mat m, Cb cb = [](){});
44+
45+
cv::GFrameDesc meta() const override;
46+
cv::MediaFrame::View access(cv::MediaFrame::Access) override;
47+
48+
private:
49+
cv::Mat m_mat;
50+
Cb m_cb;
51+
};
52+
53+
class MediaCommonCapSrc : public CommonCapSrc {
54+
using CommonCapSrc::CommonCapSrc;
55+
56+
bool pull(cv::gapi::wip::Data& data);
57+
cv::GMetaArg descr_of() const override;
58+
};
59+
3760
} // namespace custom

demos/common/cpp_gapi/utils_gapi/src/stream_source.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,31 @@ cv::GMetaArg CommonCapSrc::descr_of() const {
4343
GAPI_Assert(!first.empty());
4444
return cv::GMetaArg{cv::descr_of(first)};
4545
}
46+
47+
MediaBGRAdapter::MediaBGRAdapter(cv::Mat m, MediaBGRAdapter::Cb cb)
48+
: m_mat(m), m_cb(cb) {
49+
}
50+
51+
cv::GFrameDesc MediaBGRAdapter::meta() const {
52+
return cv::GFrameDesc{cv::MediaFormat::BGR, m_mat.size()};
53+
}
54+
55+
cv::MediaFrame::View MediaBGRAdapter::access(cv::MediaFrame::Access) {
56+
cv::MediaFrame::View::Ptrs pp = { m_mat.ptr(), nullptr, nullptr, nullptr };
57+
cv::MediaFrame::View::Strides ss = { m_mat.step, 0u, 0u, 0u };
58+
return cv::MediaFrame::View(std::move(pp), std::move(ss), MediaBGRAdapter::Cb{m_cb});
59+
}
60+
61+
bool MediaCommonCapSrc::pull(cv::gapi::wip::Data& data) {
62+
if (CommonCapSrc::pull(data)) {
63+
data = cv::MediaFrame::Create<MediaBGRAdapter>(cv::util::get<cv::Mat>(data));
64+
return true;
65+
}
66+
return false;
67+
}
68+
69+
cv::GMetaArg MediaCommonCapSrc::descr_of() const {
70+
return cv::GMetaArg{cv::GFrameDesc{cv::MediaFormat::BGR,
71+
cv::util::get<cv::GMatDesc>(CommonCapSrc::descr_of()).size}};
72+
}
4673
} // namespace custom

0 commit comments

Comments
 (0)