Is cv::Mat class flawed by design?

前端 未结 4 1011
感情败类
感情败类 2020-12-29 07:06

I work a lot with the OpenCV C++ interface and designed a number of classes which use Mat\'s as private resources.

Recently, I got concerned about the Mat class, as

4条回答
  •  清酒与你
    2020-12-29 07:58

    To answer the OPs question:

    Yes, most definitely! As a couple of people have pointed out: OpenCV gives you no possibility to describe a const reference to an image. This is indeed a flaw. "const cv::Mat&" is not what a c++ programmer would expect it to be and I have often found myself sprinkling clone() calls all over my code to the point where I lose the benefit of the data sharing to begin with.

    To answer Vadims question of how to do it efficiently:

    It is absolutely possible to do this efficiently, though not without an API change. Look how Qt abandoned the explicit sharing model it had before Qt 4(analogue to OpenCV's current model) to it's current implicit sharing (copy on write) with great success. Basically all function calls which mutate an object, or returns a reference which could later mutate the object have to "deref" it. That is make a copy if there are more than one references.

    The cost of this is miniscule compared to the average cost of an image operation. It only becomes prohibitive if it has to be performed per pixel. That's why the class need to be separated into two. Much like cv::Mat and cv::Mat_. One that is responsible for the implicit sharing and copying, and one which is just a templated wrapper of a IplImage. Here is an example of what the API could look like(I have chosen overly explicit names for clarity):

    // The following makes no unnecessary copies. Only a 
    // couple of atomic increments and decrements.
    const cv::Image img = cv::Image("lenna.bmp").toGray().brighter(0.3).inverted();
    
    cv::Image copy(img);// Still no deep copy.
    
    cv::ConstImageRef src = img.constRef();// Still no deep copy.
    
    // This is where the copy(detach) happens.
    // "img" is left untouched
    cv::MutableImageRef dst = copy.ref();
    
    // The following is as efficient as it has ever been.
    for(int y = 0; y

    I realize there is too much OpenCV code floating around to make any radical changes and the window to make an API change with OpenCV 3 is closed, but I don't see why it shouldn't be possible to add a new improved interface.

提交回复
热议问题