Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@cocoa-xu
Copy link

@cocoa-xu cocoa-xu commented Jun 3, 2024

This PR is related to #25694.

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 another license that is incompatible with OpenCV
  • The PR is proposed to the proper branch
  • There is a reference to the 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

@sturkmen72
Copy link
Contributor

this i not a bug. documentation says

Note
The image passing through the img parameter can be pre-allocated. The memory is reused if the shape and the type match with the load image."

maybe this PR considered as an improvement but need rethinking and being well documented.

@cocoa-xu
Copy link
Author

cocoa-xu commented Jun 3, 2024

Hi @sturkmen72, thanks for the reply. I think this should be a bug (or has inconsistent semantic meaning compared to other functions) and should be fixed for the following reasons:

  1. Inconsistent semantic meaning

    OutputArray in other functions like cv::blur suppports empty cv::Mat without any pre-allocations.

    void cv::blur(InputArray src,
        OutputArray dst,
        Size ksize,
        Point anchor = Point(-1,-1),
        int borderType = BORDER_DEFAULT 
    )

    https://docs.opencv.org/4.x/d4/d86/group__imgproc__filter.html#ga8c45db9afe636703801b0b2e440fce37

    The proposed changes should make it align with other existing functions that accepts an OutputArray for storing the result.

  2. It should work with empty cv::Mat

    In the implementation of cv::imread, i.e., imread_, empty cv::Mat can be correctly handled and initialised there:

    if (mat.empty())
    {
    mat.create( size.height, size.width, type );
    }

    This makes the current version to silently load, decode an image and discard the results. It would not only waste CPU time but also cause confusions and inconsistencies.

  3. Unclear requirements

    In the inline docs, it mentions that the img parameter can be pre-allocated, which IMHO suggests that it can also work with empty cv::Mat.

  4. Fail with no indications

    Furthermore, even if we really don't want it to work with any empty cv::Mat, and say that the pre-allocation is a must, then I'm expected to see an exception or assertion in the code instead of silently failing.

    void imread( const String& filename, OutputArray dst, int flags )
    {
        CV_TRACE_FUNCTION();
    
        Mat img = dst.getMat();
        CV_Assert( !img.empty() );
    
        /// load the data
        imread_(filename, flags, img);
    }

@sturkmen72
Copy link
Contributor

@cocoa-xu i completely agree with you. in addition the function should return an int value ( zero for All is OK or a failure code ). this is a new addition maybe still it is not too late to change API. anyway #24415 is the original addition PR.

@cocoa-xu
Copy link
Author

cocoa-xu commented Jun 3, 2024

in addition the function should return an int value ( zero for All is OK or a failure code ). this is a new addition maybe still it is not too late to change API.

OK it's done now. It will now forward the result boolean value from imread_ to the caller. I chose bool because that's all the information we can get from imread_.

And as there's no other calls can potentially fail inside this function, I think it should be okay. But please don't hesitate to let me know if we should use int instead. :)

@sturkmen72
Copy link
Contributor

core developers decide. My suggestion is good in that it is open to development in the future.

@sturkmen72
Copy link
Contributor

i am just a contributor. take it in account.

@mshabunin
Copy link
Contributor

mshabunin commented Jun 4, 2024

The root cause of this problem is wrong handling of OutputArray.

void foo(OutputArray res)
{
    Mat m = res.getMat(); // either Mat object wrapped by "res" or temporary Mat object
    m.create(...); // does not affect "res" or original object
}

To resolve this issue we should call OutputArray::create and then getMat instead of getMat and Mat::create.

@mshabunin
Copy link
Contributor

@cocoa-xu , please check whether #25703 resolves your issue.

@cocoa-xu cocoa-xu closed this Jun 5, 2024
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.

4 participants