Skip to content

[G-API] Added Y, UV accessors for cv::MediaFrame#19325

Merged
alalek merged 1 commit intoopencv:masterfrom
AsyaPronina:asyadev/extract_y
Mar 24, 2021
Merged

[G-API] Added Y, UV accessors for cv::MediaFrame#19325
alalek merged 1 commit intoopencv:masterfrom
AsyaPronina:asyadev/extract_y

Conversation

@AsyaPronina
Copy link
Copy Markdown
Contributor

@AsyaPronina AsyaPronina commented Jan 15, 2021

Pull Request Readiness Checklist

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

  • I agree to contribute to the project under Apache 2 License.
  • To the best of my knowledge, the proposed patch is not based on a code under GPL or other license that is incompatible with OpenCV
  • The PR is proposed to proper branch
  • There is reference to original bug report and related work
  • There is accuracy test, performance test and test data in opencv_extra repository, if applicable
    Patch to opencv_extra has the same branch name.
  • The feature is well documented and sample code can be built with the project CMake

This PR adds two operations to retrieve Y and UV GMat-s from GFrame.

force_builders=Custom,Custom Win,Custom Mac
build_gapi_standalone:Linux x64=ade-0.1.1f
build_gapi_standalone:Win64=ade-0.1.1f
build_gapi_standalone:Mac=ade-0.1.1f
build_gapi_standalone:Linux x64 Debug=ade-0.1.1f

build_image:Custom=centos:7
buildworker:Custom=linux-1
build_gapi_standalone:Custom=ade-0.1.1f

build_image:Custom=ubuntu-openvino-2021.1.0:20.04
build_image:Custom Win=openvino-2021.1.0
build_image:Custom Mac=openvino-2021.1.0

test_modules:Custom=gapi
test_modules:Custom Win=gapi
test_modules:Custom Mac=gapi

buildworker:Custom=linux-1
// disabled due high memory usage: test_opencl:Custom=ON
test_opencl:Custom=OFF
test_bigdata:Custom=1
test_filter:Custom=*

@AsyaPronina AsyaPronina force-pushed the asyadev/extract_y branch 3 times, most recently from 37060c6 to 2387594 Compare January 15, 2021 01:35
@AsyaPronina AsyaPronina requested a review from dmatveev January 15, 2021 01:36
@AsyaPronina AsyaPronina force-pushed the asyadev/extract_y branch 2 times, most recently from ef03dd7 to 033ac49 Compare January 15, 2021 18:06
@TolyaTalamanov
Copy link
Copy Markdown
Contributor

Consider to use openvino:2021

Copy link
Copy Markdown
Contributor

@TolyaTalamanov TolyaTalamanov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good, but let's discuss adapter logic locally

@AsyaPronina AsyaPronina force-pushed the asyadev/extract_y branch 9 times, most recently from ae01eb2 to 4102140 Compare March 18, 2021 08:04
@TolyaTalamanov TolyaTalamanov self-requested a review March 19, 2021 12:03
Copy link
Copy Markdown
Contributor

@TolyaTalamanov TolyaTalamanov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

Great, thanks!

@AsyaPronina AsyaPronina force-pushed the asyadev/extract_y branch 2 times, most recently from b44774c to d222419 Compare March 19, 2021 14:53
};

G_API_OP(GY, <GMat(GFrame)>, "org.opencv.streaming.Y") {
static GMatDesc outMeta(const GFrameDesc frameDesc) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

&

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

};

G_API_OP(GUV, <GMat(GFrame)>, "org.opencv.streaming.UV") {
static GMatDesc outMeta(const GFrameDesc frameDesc) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

&

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed


/** @brief Extracts Y plane from media frame.

Output image shall be 8-bit 1-channel image of @ref CV_8UC1.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is. "shall be" assumes some requirement or expectation set, but it is not the case.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed


/** @brief Extracts UV plane from media frame.

Output image shall be 8-bit 2-channels image of @ref CV_8UC2.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2-channel

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

{
explicit RMatMediaAdapterBGR(const cv::MediaFrame& frame) : m_frame(frame) { };
explicit RMatMediaFrameAdapter(const cv::MediaFrame& frame,
std::function<cv::Mat(const GFrameDesc&, const cv::MediaFrame::View&)> frameViewToMat) :
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks weird, why do we need a callback like this here?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got the idea after reviewing the rest of this code. I'd recommend to give this std::function a name (right within this class). See how our kernels are implemented in e.g. Fluid backend.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

m_frameViewToMat(frameViewToMat)
{
const auto& d = m_frame.desc();
const auto& fv = m_frame.access(cv::MediaFrame::Access::R);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd delay this to the actual access - why do we map MediaFrame's data immediately?

Is there a performance benefit in our case?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah you only do it to obtain meta early -- then I'd move it to that point.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, if you'll do this, please take care of concurrency.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed this part.
Implemented retrieving of meta as discussed internally.

auto ptr = reinterpret_cast<uchar*>(view.ptr[0]);
auto stride = view.stride[0];
auto fv = m_frame.access(a == cv::RMat::Access::R ? cv::MediaFrame::Access::R
: cv::MediaFrame::Access::W);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no guarantee in only R and W being used exclusively, there may be RW introduced one day.

This code will break then.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added mapping lamda, but it throws exception if cv::RMat::Access is not R or W for now.

auto view = frame.access(cv::MediaFrame::Access::R);
cv::Mat tmp_bgr(desc.size, CV_8UC3, view.ptr[0], view.stride[0]);
cv::Mat yuv;
cvtColor(tmp_bgr, yuv, cv::COLOR_BGR2YUV_I420);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In case of BGR() accessor called on an NV12 MediaFrame, we simply throw an exception (except some target platform where that conversion is implemented in firmware).

Since in case of Y() accessor we actually do the conversion (on CPU - what is debatable for high resolutions we target to), I'd align the behavior between the accessors.

Also, since the on-the-fly conversion is costly, I'd put a warning but only once per actor - not for every frame we process. You might want to look at std::call_once for that.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't throw exception in the OCV BGR kernel also..

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added warning for every accessor in case of non-consistent input format.
Warning is thrown only once per frame.

@AsyaPronina AsyaPronina force-pushed the asyadev/extract_y branch 3 times, most recently from 0ab881f to 71fab18 Compare March 23, 2021 21:08
using MapDescF = std::function<cv::GMatDesc(const GFrameDesc&)>;
using MapDataF = std::function<cv::Mat(const GFrameDesc&, const cv::MediaFrame::View&)>;

explicit RMatMediaFrameAdapter(const cv::MediaFrame& frame,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no need in explicit anymore as the constructor takes >1 parameter

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

{
std::call_once(m_warnFlag,
[](){
GAPI_LOG_WARNING(NULL, "On-fly conversion from NV12 to BGR will be happened.");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"On-the-fly", "will happen". I'd also put a recommendation here so user could figure out how to change his code to avoid that (and briefly explain why it is a problem)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

Copy link
Copy Markdown
Contributor

@dmatveev dmatveev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please merge this now and fix the text later.

Comment on lines +84 to +85
cv::util::throw_error(std::logic_error("cv::RMat::Access::R or "
"cv::RMat::Access::W can only be mapped to cv::MediaFrame::Access!"));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this text is misleading and it'd be enough to only put an assert here, saying that only R/W are accepted.

Please do it later (not in this PR).

std::call_once(m_warnFlag,
[](){
GAPI_LOG_WARNING(NULL, "\nOn-the-fly conversion from NV12 to BGR will happen.\n"
"Conversion may cost a lot for images with high resolution.\n"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cost a lot -> may be costly.

Again, please fix it later.

GAPI_LOG_WARNING(NULL, "\nOn-the-fly conversion from NV12 to BGR will happen.\n"
"Conversion may cost a lot for images with high resolution.\n"
"To retrieve cv::Mat-s from NV12 cv::MediaFrame for free, you may use "
"cv::gapi::streaming::Y and cv::gapi::streaming::UV accessors.\n");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may be misleading too since Y and UV are working at cv::GMat level (I mean, for user), there's no Mats etc.

Comment on lines +321 to +323
"Conversion may cost a lot for images with high resolution.\n"
"To retrieve cv::Mat from BGR cv::MediaFrame for free, you may use "
"cv::gapi::streaming::BGR accessor.\n");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment here

Comment on lines +376 to +379
GAPI_LOG_WARNING(NULL, "\nOn-the-fly conversion from BGR to NV12 UV plane will "
"happen.\n"
"Conversion may cost a lot for images with high resolution.\n"
"To retrieve cv::Mat from BGR cv::MediaFrame for free, you may use "
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and here.

@AsyaPronina
Copy link
Copy Markdown
Contributor Author

Please merge this now and fix the text later.

Thanks a lot!
@alalek, could you please merge this?

@alalek alalek merged commit 7949983 into opencv:master Mar 24, 2021
@alalek alalek mentioned this pull request Apr 9, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants