Ask Your Question

Best practices for writing image processing functions?

asked 2015-11-25 09:06:22 -0500

kbarni gravatar image

updated 2020-11-30 02:54:38 -0500

I've been thinking for some time, which is the best method to declare an image processing function?

The function should take an input image and return an output image.

I can think of the following possibilities:

  1. using InputArray & OutputArray:

    void foo(InputArray in,OutputArray out)
        Mat inMat=in.getMat();
        Mat outMat=out.getMat();
        // processing code...
  2. Using two Mat variables as parameters:

    void foo(Mat in,Mat out)
        // processing code...

    BTW, in this case which parameters should be declared with &? (i.e. Mat &in)

  3. One Mat as parameter and return a new Mat:

    Mat foo(Mat in)
        Mat out(in.size(),CV_8U);
        // processing code...
        return out;

In classical C++ code, the third method should be normally preferred, but I think the other two can be more optimal in certain cases (i.e. using foo(img,img) vs. img=foo(img) or when the out matrix was already created)?

Concerning the first two solutions, I think they are mostly equivalent, however OpenCV uses systematically InputArray and OutputArray as parameters. Is there a good reason for this, or is it's for better readability? I am also aware that InputArray and OutputArray are more general, they can accept other parameters then Mat variables, too.

edit retag flag offensive close merge delete


I have some remarks about the Mat parameters functions:

  1. It is nasty to use the Mat in as input parameter. You shall adopt the const TypeAddress param form, so use const cv::Mat& in. Like this you are sure that you are not modifying the values in the input parameter
  2. The first version should be used if there is a more generic approach, like it may run on vectors of some other arrays, not just on Mat; so use one of the last 2.
  3. With the last versions of C++ compilers, I think, returning the Mat is not anymore a problem (I do not know for CUDA, GPU, CL, etc.). More, you may do some improvements like returning an address of an object in some cases (more details)
thdrksdfthmn gravatar imagethdrksdfthmn ( 2015-11-25 10:22:21 -0500 )edit

2 answers

Sort by ยป oldest newest most voted

answered 2015-11-25 13:09:19 -0500

pklab gravatar image

I prefer

void foo(const cv::Mat &src, cv::Mat &dst) // for cv::Mat only


void foo(InputArray src,OutputArray dst)  //for cv::Mat, cv::Mat_, cv::Matx,std:vector

Both are fastest and clear.

In general, cv::Mat has a powerful Automatic Memory Management that allocate/deallocates the memory automatically. This help developers to forget about memory management and many call statements are similar (for opencv mats only!!)

cv::Mat consists of header that hold informations about the Mat and a pointer to a memory block that holds the Mat data (matrix,images,...).

2 (or more cv::Mat) can share same memory for data but each cv::Mat has its own header. Using mat1 = mat2 you will achieve this result. This operation is O(1) and is fast because only header (small) information will be copied.

Function headers:

void foo(cv::Mat src,cv::Mat dst) // create 2 additional headers each call

With above declaration you will create 2 new temporary headers each time you call foo. Again memory data will be shared with calling function. Again is fast O(1) operation.

void foo(cv::Mat &src,cv::Mat &dst) // by ref, use same objects from calling function

With this 2nd declaration you are using param by reference as standard C++. This means that you are using same object instance from calling function. This is fastest method because you won't create new headers.

What's happens to when you write mat1 = mat2 ? will be deallocated automatically when is used nowhere else .This is achieved by OpenCV using internal counter.

Below some showcases:

void foo(const cv::Mat &src, cv::Mat &dst)
    cvtColor(src,dst,BGR2GRAY); // will be allocated here IF NEEDED
    cvtColor(src,src,BGR2GRAY); // NOT ALLOWED because src is const
void bar(cv::Mat &dst)
    cv::circle(dst,... // draw a circle on dst

    cv::Mat mat1,mat2,mat3,mat4,mat5,mat6;
    cv::imread("some.jpg"); //allocate mem for
    foo(mat1,mat2);         //new memory for has been allocated

    mat3 = cv::Mat(mat1.size(),mat1.type()); // allocate mem for
    foo(mat1,mat3);                          // existing has been used (size fits)

    mat4 = cv::Mat(10,10,mat1.type()); // allocate mem (SMALL SIZE) for
    foo(mat1,mat4);                    // no one using than it has been deallocated.
                                       // New memory has been allocated for

    mat5 = cv::Mat(10,10,mat1.type()); // allocate mem (SMALL SIZE) for
    mat6 = mat5;                       // mat5 and mat6 share same data
    bar(mat5);                         // draw a circle
                                       // mat6 contains circle too
    foo(mat1,mat5); // existing data is still valid for mat6.
                    // New memory has been allocated for mat5
    // now mat6 is different from mat5. It contains circle same as before.
} //deallocate memory for all mats

this works also if you are using some local var

void foo(const cv::Mat &src, cv::Mat &dst) // for cv::Mat only
    cv::Mat local;
    cv::cvtColor(src, local, cv::COLOR_BGR2GRAY);//new memory for ...
edit flag offensive delete link more



Nice explanation!!

thdrksdfthmn gravatar imagethdrksdfthmn ( 2015-11-26 02:29:50 -0500 )edit

Thanks pklab! Good explanation on the internal mechanisms of handling Mat objects!

kbarni gravatar imagekbarni ( 2015-11-26 03:32:15 -0500 )edit

thank you !!! ... it should be correct but correction and criticisms are welcome. In special case integration for GPU,CUDA,CL etc.. will be usefull for all ;)

pklab gravatar imagepklab ( 2015-11-26 04:04:51 -0500 )edit

answered 2016-02-18 21:50:13 -0500

not an answer but to take an attention i post an answer instead of a comment

i found the link below very useful to whom wants to improve his skill writing c++ code

The C++ Core Guidelines are a set of tried-and-true guidelines, rules, and best practices about coding in C++

edit flag offensive delete link more

Question Tools

1 follower


Asked: 2015-11-25 09:06:22 -0500

Seen: 2,491 times

Last updated: Feb 18 '16