CARVIEW |
Navigation Menu
-
-
Notifications
You must be signed in to change notification settings - Fork 56.2k
G-API: Add standalone fix for graph empty input #20184
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
modules/gapi/src/api/gproto.cpp
Outdated
@@ -218,7 +219,9 @@ void cv::validate_input_arg(const GRunArg& arg) | |||
case GRunArg::index_of<cv::Mat>(): | |||
{ | |||
const auto desc = cv::descr_of(util::get<cv::Mat>(arg)); | |||
GAPI_Assert(desc.size.height != 0 && desc.size.width != 0 && "incorrect dimensions of Mat!"); break; | |||
GAPI_Assert(desc.size.height != 0 && desc.size.width != 0 && "incorrect dimensions of Mat!"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe the problem was in using !=
intead of >
, and at some point we get -1
there which passed through the test, isnt it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, it is.
But, i've decided that empty_gmat_descr
comparison is more clearest here, isnt it ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know, does it actually works for the case?
if(cv::empty_gmat_desc() == cv::util::get<cv::GMatDesc>(meta)) | ||
{ | ||
is_valid = false; | ||
tracer << "empty cv::Mat is not allowed as compile argument"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Empty cv::Mat (as the cv::Mat in general) is not a compile argument, so this message may be misleading
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also - does this check handle the case when an empty cv::Mat
is passed to .apply()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've checked the code and found:
- this parts is called from compile()
- compile() can be called as standalone method
or - be part of apply(), when arguments set was changed (recompile)
So, message looks like really misleading in direct apply()
case.
And empty cv::Mat
cannot be passed to .apply()
because recompile would be triggered in first and invoke this compile()
@dmatveev What do you thinks about the message?
empty cv::Mat is not allowed as graph input argument
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is more correct but again, we don't deal with cv::Mat
at all when compiling a graph, so referring to a structure which may not exist at the time can be misleading.
bool validate_input_meta_arg(const GMetaArg& meta, std::ostream* tracer = nullptr); | ||
bool validate_input_meta(const GMatDesc& meta, std::ostream* tracer = nullptr); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need this here? It is a public header - it is exposed in the installed library package. Is it supposed to be used somehow by end users? I believe it is not
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's actually the common part between gproto.cpp & gcompiled.cpp -which uses the same validation fucntionality
I've added it similarly in the same way with validate_input_args
because i got the impression after file inspection that entire file exposes a set of auxiliary functions - additionally, i didn't face with usage other function in this file as public interface. This overall assumption score told me that file is utility file
But maybe I wrong and this utility-like function should be implemented in other place
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
moved to src/ai/gmeta_chec.hpp/cpp
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gproto.cpp
and gproto_priv.hpp
are the right ones.
modules/gapi/src/api/gproto.cpp
Outdated
"incorrect description of cv::UMat! " | ||
"Dimensions, channel and depth must be positive"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe the check itself and the error message here mix levels of abstractions.
Looking at this code, you don't know what is actually checked by this function, but the assert text complains about some specific fields.
I am not sure if it needs to be an assert at all. If you want provide details, provide it in the exception text you throw from the validate_input_meta()
function (so it becomes void
not bool
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It make sense, and "incorrect description of cv::*Mat" is enough
about exception i think it is a bad idea:
- void function with the only reason in throwing exception looks ugly and unsafe and inconvenient in usage and considered as bad practice
- GAPI_Assert here means that this place is performance critical in Release build, so exception is not good here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is not performance critical, in the performance-critical code we use DbgAssert
.
modules/gapi/src/api/gproto.cpp
Outdated
bool cv::validate_input_meta(const cv::GMatDesc& meta, std::ostream* tracer) | ||
{ | ||
if (meta.dims.empty()) | ||
{ | ||
if (!(meta.size.height > 0 && meta.size.width > 0)) | ||
{ | ||
if (tracer) | ||
{ | ||
*tracer << "Image format is invalid. Size must contain positive values, got width: " | ||
<< meta.size.width << ", height: " << meta.size.height; | ||
} | ||
return false; | ||
} | ||
|
||
if (!(meta.chan > 0)) | ||
{ | ||
if (tracer) | ||
{ | ||
*tracer << "Image format is invalid. Channel mustn't be negative value, got channel: " | ||
<< meta.chan; | ||
} | ||
return false; | ||
} | ||
} | ||
|
||
if (!(meta.depth >= 0)) | ||
{ | ||
if (tracer) | ||
{ | ||
*tracer << "Image format is invalid. Depth must be positive value, got depth: " | ||
<< meta.depth; | ||
} | ||
return false; | ||
} | ||
return true; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why bool here again? I believe the code simplifies a lot if we drop this tracer thing at all and simply throw.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, it simplifed here, but after it become more complicated in caller context. It is a bad idea, as for me, to wrap function around try-catch every time
if you dislike optional tracer, then it is possible in the following approach
std::tuple<bool, std::string> validate_();
...
auto res = validate_(...)
if(!res.first)
{
printf(res.second)
}
what do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mainly we don't need try/catch
in/with our own code.
modules/gapi/CMakeLists.txt
Outdated
@@ -83,6 +83,7 @@ set(gapi_srcs | |||
src/api/ginfer.cpp | |||
src/api/media.cpp | |||
src/api/rmat.cpp | |||
src/api/gmeta_check.cpp |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a separate file may be too much for this simple function, consider gproto.cpp
& its _priv.hpp
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, i thought about _priv.hpp
, but I was confused with comment // FIXME: why it is here?
And i realized that this include should be removed is in future
@dmatveev What do you think about that - do you still suggest to move it in _priv.hpp
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe in 2021 nobody remembers the answer to
// FIXME: why it is here?
:)
modules/gapi/src/api/gproto.cpp
Outdated
{ | ||
if (!(meta.size.height > 0 && meta.size.width > 0)) | ||
{ | ||
cv::util::throw_error(std::logic_error(std::string("Image format is invalid. Size must contain positive values, got width: ") + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line is 139 characters long; I believe the OpenCV's coding style allows something up to 110 but we're trying to follow ~80. I believe the std::string()
thing is not needed here as operator+(const char*, std::string)
should work things out. throw_error
itself is terrible (was done wrong initially and nobody has fixed it then), so we usually write this stuff like
cv::util::throw_error
(std::logic_error
(...);
Also, I believe a simple assert could work fine here (except the failed value won't be printed).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
try | ||
{ | ||
gimpl::proto::validate_input_meta_arg(meta); //may throw | ||
} | ||
catch(const std::exception& ex) | ||
{ | ||
const auto index = ade::util::index(meta_arg_idx); | ||
util::throw_error(std::logic_error | ||
("GComputation metadata incorrect value " | ||
"(argument " + std::to_string(index) + "), error: " + | ||
ex.what())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this try/catch
is redundant - the code throws anyway, the only thing it adds is the error message - you can use the LOG()
trick instead to provide the context.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
for (const auto meta_arg_idx : ade::util::indexed(ade::util::zip(m_metas, c_expr.m_ins))) | ||
{ | ||
const auto &meta = std::get<0>(ade::util::value(meta_arg_idx)); | ||
const auto &proto = std::get<1>(ade::util::value(meta_arg_idx)); | ||
|
||
const auto index = ade::util::index(meta_arg_idx); | ||
GAPI_LOG_DEBUG(nullptr, "Process index: " << index); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[DEBUG:0] global C:\Users\sivanov\github\opencv\modules\gapi\src\compiler\gcompiler.cpp (346) cv::gimpl::GCompiler::validateInputMeta Total count: 1
[DEBUG:0] global C:\Users\sivanov\github\opencv\modules\gapi\src\compiler\gcompiler.cpp (353) cv::gimpl::GCompiler::validateInputMeta Process index: 0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fantastic, thanks!
G-API: Add standalone fix for graph empty input * Add sandalone fix for graph empty input * Apply some review comments * Fix whitespace * Apply review comment: make Mat check more deeper * Apply some comments * Remove tracer apply exception throwing * Apply comments: move validatio into gproto_priv.hpp * Apply minor text correction * Fix alignment, remove try-catch
STANDALONE version of the fix
G-API graph invocation may fail in case of user passed empty cv::Mat object and this issue detected in core part of G-API on compute step.
The main idea is move pretty-check into compile phase and separate if from actual invocation (note: compile doesn't mean C++ compile but rather means phase of graph pipeline execution )
Added UTs:
Pull Request Readiness Checklist
See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request
Patch to opencv_extra has the same branch name.