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

Skip to content

Conversation

@vrabaud
Copy link
Contributor

@vrabaud vrabaud commented Nov 15, 2021

This ensures that the type is copied.
The doc also mentions that .create is called:
https://docs.opencv.org/4.5.4/d3/d63/classcv_1_1Mat.html#a33fd5d125b4c302b0c9aa86980791a77

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
  • The feature is well documented and sample code can be built with the project CMake

@alalek
Copy link
Member

alalek commented Nov 15, 2021

Currently, there is no proper support for handling of empty matrices or distinguish them from just declared cv::Mat m;.

AFAIK, meta information should not be used if Mat is .empty().

See also: #7710

@vrabaud
Copy link
Contributor Author

vrabaud commented Nov 16, 2021

I understand we cannot differentiate with a proper empty matrix created by cv::Mat m (which has a default type of CV_8UC1).
Still, behavior is inconsistent: resize(0) keeps the type (cf

void Mat::resize(size_t nelems)
) which makes sense: if you do resize(0) and then resize(1), the type has to be known.

My patch is actually to solve: cv::Mat(0,0,CV_16SC3).clone() returns cv::Mat(0,0,CV_8UC1) (and not an empty matrix of the right type CV_16SC3).

So please advise on how we should fix the following (maybe by just updating the doc in the right places):

I still think my patch would bring some consistency but I would also need to have release() keep the type (which I can add).

@alalek
Copy link
Member

alalek commented Nov 16, 2021

release()

Main point here that "Mat" is a kind of smart pointer over some buffer.
To behave similar to smart pointers, .release() should reset instance to the state of empty and undefined cv::Mat m;.

which contradicts the documentation

Currently it is a gray zone which is not documented.

@vrabaud
Copy link
Contributor Author

vrabaud commented Nov 17, 2021

I agree with .release(), the semantic needs to be clarified in the doc though.

There is actually a way to differentiate between cv::Mat() and cv::Mat(0,0,CV_8U) though their type is 0 for both: elemSize() is 0 in the first case, 1 in the other case.

@vpisarev
Copy link
Contributor

Probably, we should use the check, proposed by @vrabaud (e.g. m.total() == 0 && m.elemSize() == 0) to check for empty matrices and produce meaningful results in this case instead of crashing

@alalek
Copy link
Member

alalek commented Nov 17, 2021

instead of crashing

where is code crashing?


m.elemSize() == 0

Even cv::Mat m; returns 1 here (as its type is CV_8UC1 = 0), so this check doesn't make a lot of sense.

@vrabaud
Copy link
Contributor Author

vrabaud commented Nov 18, 2021

.elemSize() does return different results for me with 4.5.3.

#include "opencv2/core.hpp"
#include <iostream>


int main(int, char**argv){
  cv::Mat m1, m2(0, 0, CV_8U);
  std::cout << m1.elemSize() << " " << m2.elemSize() << std::endl;
}

And

clang++ -l opencv_core -I /usr/include/opencv4/ -o test main.cc
./test
0 1

Maybe we need a .empty() like we have right now that just checks if there are no elements, and a .uninitialized() / .released() / emptyFull() that checks whether we have a cv::Mat() (no element, no type).

@alalek
Copy link
Member

alalek commented Nov 18, 2021

.elemSize()

Right, it has dedicated handling for empty Mat:

size_t Mat::elemSize() const
{
size_t res = dims > 0 ? step.p[dims - 1] : 0;
CV_DbgAssert(res != 0);
return res;
}

I messed that with CV_ELEM_SIZE(flags).

Also please note CV_DbgAssert() check in the code above - using .elemSize() with empty Mat triggers error.

However original expression form m.total() == 0 && m.elemSize() == 0 doesn't make sense.

@vrabaud
Copy link
Contributor Author

vrabaud commented Apr 3, 2024

Hi, what do I do with that PR ? Port it to 4.x or give up until 5.x which has better handling of 0d ?

@asmorkalov
Copy link
Contributor

Replaced with #27972

@asmorkalov asmorkalov closed this Nov 6, 2025
asmorkalov added a commit that referenced this pull request Nov 10, 2025
Force empty output type where it's defined in API #27972

The PR replaces:
- #27936
- #21059

Empty matrix has undefined type, so user code should not relay on the output type, if it's empty. The PR introduces some exceptions:
- copyTo documentation defines, that the method re-create output buffer and set it's type.
- convertTo has output type as parameter and output type is defined and expected.
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