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

Skip to content

Conversation

@mshabunin
Copy link
Contributor

@mshabunin mshabunin commented Jun 4, 2024

Resolves #25694
Replaces #25695

  • Moved OutputArray down the call stack
  • Allow output images with smaller or larger size - will be recreated if necessary
  • Added check for recreated image in calls to backend, if this happens, original image will not be updated - backend should be fixed in this case
  • Fixed gray output handling in HDR (RGBE) backend - use cvtColor to convert
  • Extended and moved corresponding test

Note: we rely on decoders to not recreate the input Mat in their readData(Mat & img) method. Otherwise destination image will not be updated just like in the issue.

@cocoa-xu
Copy link

cocoa-xu commented Jun 4, 2024

Hi @mshabunin, thanks for the fix! This looks perfect. ;)

@sturkmen72
Copy link
Contributor

is it too late to change API.

void imread( const String& filename, OutputArray dst, int flags )
{
    CV_TRACE_FUNCTION();

    /// load the data
    imread_(filename, flags, dst);
}

int imread( const String& filename, OutputArray dst, int flags ) will be good in that it is open to development in the future.

@mshabunin
Copy link
Contributor Author

is it too late to change API.

@sturkmen72 , this PR doesn't change public API (imread). Only internal functions are affected, e.g. imread_.

@sturkmen72
Copy link
Contributor

is it too late to change API.

@sturkmen72 , this PR doesn't change public API (imread). Only internal functions are affected, e.g. imread_.

i mean if it is still possible ( it is newly added function and maybe ABI change policy allow )
int imread( const String& filename, OutputArray dst, int flags ) will be open further development in the future.
At least i propose doing such change in OpenCV5

// grab the decoded type
const int type = calcType(decoder->type(), flags);

if (mat.empty())
Copy link
Contributor

@sturkmen72 sturkmen72 Jun 4, 2024

Choose a reason for hiding this comment

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

this change seems wrong to me.

we should keep

if (mat.empty())
    {
        mat.create( size.height, size.width, type );
    }
    else
    {
        CV_CheckEQ(size, mat.size(), "");
        CV_CheckTypeEQ(type, mat.type(), "");
        CV_Assert(mat.isContinuous());
    }

Copy link
Contributor Author

Choose a reason for hiding this comment

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

create should not reallocate data if requested image size fits into existing Mat.

Mat img(1000, 1000, CV_8UC3);
imread(f, img); // should not reallocate data if image size is less than (1000, 1000)

Without this change it will not be possible to read multiple images of different sizes efficiently, because user would need to pass either empty Mat or a Mat with exact image dimensions on each iteration.

I.e. with proposed change, following code should work and should perform reallocations only when necessary:

Mat img;
for (auto f : filenames)
{
    imread(f, img); // will fail if images have different sizes
}

Copy link
Contributor

Choose a reason for hiding this comment

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

sorry you are right. mat.create( size.height, size.width, type ); does the job.

Copy link
Contributor

Choose a reason for hiding this comment

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

    TickMeter tm;

    Mat im;

    for (int i = 0; i < 5; i++)
    {
        tm.reset();
        tm.start();
        imread("read.png", im);
        tm.stop();
        printf("read time %f\n", tm.getTimeSec());
    }
    imshow("read.png", im);
    waitKey();
read time 0.692092
read time 0.615938
read time 0.615163
read time 0.615883
read time 0.617650

good job!

}


static void ExifTransform(int orientation, Mat& img)
Copy link
Contributor

Choose a reason for hiding this comment

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

InputOutputArray is better. I know, that they are synonyms, but it's simpler for reader.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It seems that it won't work without changing public imread to accept InputOutputArray (https://docs.opencv.org/4.x/d0/d46/classcv_1_1__InputOutputArray.html). There is no obvious way to construct InputOutputArray from OutputArray (https://docs.opencv.org/4.x/d2/d9e/classcv_1_1__OutputArray.html).

Copy link
Contributor

@asmorkalov asmorkalov left a comment

Choose a reason for hiding this comment

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

👍

@asmorkalov asmorkalov added this to the 4.11.0 milestone Jun 5, 2024
@asmorkalov asmorkalov merged commit 0d1ed49 into opencv:4.x Jun 6, 2024
@mshabunin mshabunin deleted the fix-imread-arg branch June 6, 2024 10:05
@mshabunin mshabunin mentioned this pull request Jun 14, 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.

cv::imread with OutputArray dst returns with empty output

5 participants