Ask Your Question
7

Best practices for writing image processing functions?

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

kbarni gravatar image

updated 2015-11-26 09:52:00 -0500

pklab gravatar image

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();
        out.createSameSize(in,CV_8U);
        Mat outMat=out.getMat();
        // processing code...
    }
    
  2. Using two Mat variables as parameters:

    void foo(Mat in,Mat out)
    {
        out.create(in.size(),CV_8U);
        // 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

Comments

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
12

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

or

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 mat1.data when you write mat1 = mat2 ?

mat1.data 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); // dst.data 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
}

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

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

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

    mat5 = cv::Mat(10,10,mat1.type()); // allocate mem (SMALL SIZE) for mat5.data
    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 ...
(more)
edit flag offensive delete link more

Comments

1

Nice explanation!!

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

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

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

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
1

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

sturkmen gravatar image

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
Login/Signup to Answer

Question Tools

1 follower

Stats

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

Seen: 369 times

Last updated: Feb 18 '16