Fix bug at blobFromImagesWithParams#24128
Conversation
|
Furthermore, we think there is also a bug in the current implementation that is fixed by our changes. If the user passes multiple three-channel images in combination with |
I don't undestand. Image2BlobParams is const in blobFromImageWithParams I tried VS2022 + windows11 and result is |
|
Correct, but the actually applied weights are those defined by which is a non-const local variable inside which recreates mean (i.e. no issue here) but reuses scalefactor and keeps swapping. |
|
Ok only scaleFactor variables is outside the loop. yes there is a problem : result is |
zihaomu
left a comment
There was a problem hiding this comment.
LGTM! 👍 Thanks for your contribution.
|
Thanks for confirming - but this bug will be fixed by the PR as well 👍 |
|
Hi @CSBVision, can you add a test at https://github.com/opencv/opencv/blob/4.x/modules/dnn/test/test_misc.cpp#L66 so that we will not miss this case again in the future? |
|
This is our proposal for a test: Is this test fine for you? |
|
Hi @CSBVision, how about adding a new test case for this issue? |
|
Then we a arrive at the following additional function: Should we add this to the PR? |
|
Hi @CSBVision, thanks for update. We can use the following code the check if the two Mat are the same. Other part looks good for me. |
426a303 to
cce0634
Compare
|
Alright, just updated the PR. |
| { | ||
| std::swap(mean[0], mean[2]); | ||
| std::swap(scalefactor[0], scalefactor[2]); | ||
| } |
There was a problem hiding this comment.
I propose to add CV_LOG_WARNING for the else case to highlight the issue.
There was a problem hiding this comment.
What do you think about that?
if (param.swapRB)
{
if (nch > 2)
{
std::swap(mean[0], mean[2]);
std::swap(scalefactor[0], scalefactor[2]);
}
else
{
CV_LOG_WARNING(NULL, "Red/blue color swapping requires at least three image channels.");
}
}
modules/dnn/src/dnn_utils.cpp
Outdated
| { | ||
| CV_Assert(scalefactor == Scalar::all(1.0) && "Scaling is not supported for CV_8U blob depth"); | ||
| CV_Assert(param.mean == Scalar() && "Mean subtraction is not supported for CV_8U blob depth"); | ||
| CV_Assert(mean == Scalar() && "Mean subtraction is not supported for CV_8U blob depth"); |
There was a problem hiding this comment.
I propose to revert param.mean here. In case if assert user should see function parameter name, but not some internal variable,
There was a problem hiding this comment.
We used this for consistency with the scalefactor check. If param.mean should be used, we should also use param.scalefactor, making both checks more explicit. Or what do you think?
There was a problem hiding this comment.
you are right, both checks.
|
May it can be usefull to define in doc if mean and scalefactor are applied before channel are swap |
In the
|
7c91620 to
2b0ebfa
Compare
|
Hi @CSBVision, Please add the header file |
2b0ebfa to
01a7e0a
Compare
|
Thanks for pointing out. We just added the lines from the comments without recompiling. Should be fine now 👍 |
01a7e0a to
674c618
Compare
asmorkalov
left a comment
There was a problem hiding this comment.
👍
I changed test a bit to have slightly different images in batch.
|
Alright, looks good👍 |
blobFromImagesWithParams(image-s) apply swap scalefactor for every images when swapRB is true. This patch moves the swap scalefactor code out of the loop, that fix the above issue.We would like to improve the recently introduced function
blobFromImagesWithParamswith respect to three minor issues that we noticed:meanandscalefactorare recreated for every image, even though they should be reused. Maybe the compiler is smart enough to optimize this, still we think the variable should be created / swapped before the main loop.swapRBis true, as explained below.if - else if - elseinstead of nested else).Function wise, there are two improvements from this:
meanandscalefactorvalues, but unintentionally setsswapRBto true, the whole result can be silently zeroed. Themeanandscalefactorarrays will only contain a single value (whereas the other indices' values remain 0), butswapRBwill swap out the true mean / scalefactor values and swap in zeros for these instead. There is no warning or assertion, only the whole image will be zeroed by the following multiplication. Therefore, we suggest to only swap these values if the image is not a single-channel image, i.e.meanandscalefactorcontain correct values for all channels, therefore addif (nch > 2).DNN_LAYOUT_NHWC. If the user passes this in combination with a single-channel image andswapRBis true, the function produces the following error:This results from first converting the image to RGB (even though it is grayscale instead of the expected BGR layout) and, thereafter, copying the resulting three-channel image into the single-channel blob. This is avoided by checking
nch > 2here, too, which is also consistent to the function's implementation of theDNN_LAYOUT_NCHWcase.Both changes can be summarized such that
swapRBonly has an effect if the image has at least three channels. Most importantly, nothing changes at all if the arguments are consistent.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.