OpenCV compilation Question

Hello,

I’m new to OpenCV and C++. Currently, I’m learning OpenCV and there’s something about its compilation that confuses me. I came across a trace function, and when I looked at its definition in the source code, it was defined as cv::Scalar cv::trace( InputArray _m ) in the modules/core/src/matrix_operations.cpp file.

However, after compiling the library, when I use cv::trace in my own code, I find that its definition changes to double trace(const Matx<_Tp, m, n>& a) in the include/opencv2/core/matx.hpp file. Furthermore, when I debug using gdb, the debugger steps into the cv::Scalar cv::trace( InputArray _m ) function.

This has left me a bit puzzled. Which is the actual code that gets called when I use cv::trace? If I want to modify the implementation, should I edit the source code in the .cpp file and recompile, or should I make modifications in the .hpp file?

Any clarification would be greatly appreciated.

please show how you do that !

how did you get to that conclusion ?

Ok, First Here’s my code

///
#include <iostream>
#include <iomanip>
#include "/home/jx23014/opencv347/include/opencv2/core.hpp"
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <time.h>

using namespace cv;
using namespace std;

inline cv::Scalar trace_copyed( InputArray _m  )
{
    Mat m = _m.getMat();
    CV_Assert( m.dims <= 2 );
    int type = m.type();
    int nm = std::min(m.rows, m.cols);

    if( type == CV_32FC1 )
    {
        const float* ptr = m.ptr<float>();
        size_t step = m.step/sizeof(ptr[0]) + 1;
        double _s = 0;
        for( int i = 0; i < nm; i++ )
            _s += ptr[i*step];
        return _s;
    }

    if( type == CV_64FC1 )
    {
        const double* ptr = m.ptr<double>();
        size_t step = m.step/sizeof(ptr[0]) + 1;
        double _s = 0;
        for( int i = 0; i < nm; i++ )
            _s += ptr[i*step];
        return _s;
    }

    return cv::sum(m.diag());
}

int main (){
    int64 begin, end;
    int iter_n = 50000;
    std::string path = samples::findFile("/home/jx23014/Dev/images/lena.png");
    Mat img = cv::imread(path, IMREAD_COLOR);
    std::cout << "Width : " << img.cols << std::endl;
    std::cout << "Height: " << img.rows << std::endl;

    cv::Scalar output1;

    begin = getTickCount();
    for (int i=0;i<iter_n;i++)
        output1 = trace_copyed (img);
    end = getTickCount();
    std::cout << "out1: " << output1 << std::endl;
    std::cout << "Copied time cost:" << (end - begin)/ getTickFrequency() <<std::endl;

    begin = getTickCount();
    for (int i=0;i<iter_n;i++)
        output1 = cv::trace (img); // <--------------------I call cv::trace
    end = getTickCount();
    std::cout << "out2: " << output1 << std::endl;
    std::cout << "Original time cost:" << (end - begin)/ getTickFrequency() <<std::endl;
    return 0;
}
///

The cv::Scalar trace_copyed function is copied from opencv-3.4.7/modules/core/src/matrix_operations.cpp file.

Second,

  1. I use “Go To Definition” function of my IDE to find that hpp file
  2. I copied the original function to my code, and I found that these two functions cost different time. Copied function always takes longer.

“the” definition?

as far as I understand C++, the same function name can have multiple signatures.

I mean, what’s the actual code get executed? There a function named trace in source, but there’s a different function named trace in include location after compiling the source.

your code example does not show that

since you’re already debugging, IF you get to that point, show stack (back)trace (bt in gdb)

It looks like this, why I’m linked back to here after I have already compiled the code?

(gdb) s
cv::debug_build_guard::_InputArray::_InputArray (this=0xffffffffed90, m=...) at /home/jx23014/opencv347/include/opencv2/core/mat.inl.hpp:88
88      inline _InputArray::_InputArray(const Mat& m) { init(MAT+ACCESS_READ, &m); }
(gdb) s
cv::Size_<int>::Size_ (this=0xffffffffeda0) at /home/jx23014/opencv347/include/opencv2/core/types.hpp:1656
1656        : width(0), height(0) {}
(gdb) s
cv::debug_build_guard::_InputArray::init (this=0xffffffffed90, _flags=16842752, _obj=0xffffffffecd8) at /home/jx23014/opencv347/include/opencv2/core/mat.inl.hpp:77
77      { flags = _flags; obj = (void*)_obj; }
(gdb) s
cv::trace (_m=...) at /home/jx23014/opencv-3.4.7/modules/core/src/matrix_operations.cpp:229
229         CV_INSTRUMENT_REGION();
(gdb) backtrace
#0  0x0000ffffbca7896c in cv::trace(cv::debug_build_guard::_InputArray const&) (_m=...) at /home/jx23014/opencv-3.4.7/modules/core/src/matrix_operations.cpp:229
#1  0x0000000000402990 in main() () at /home/jx23014/Dev/src/opencvWatch.cpp:55
(gdb) bt
#0  0x0000ffffbca7896c in cv::trace(cv::debug_build_guard::_InputArray const&) (_m=...) at /home/jx23014/opencv-3.4.7/modules/core/src/matrix_operations.cpp:229
#1  0x0000000000402990 in main() () at /home/jx23014/Dev/src/opencvWatch.cpp:55
(gdb) n
231         Mat m = _m.getMat();

For example in

(gdb) s
cv::Size_<int>::Size_ (this=0xffffffffeda0) at /home/jx23014/opencv347/include/opencv2/core/types.hpp:1656
1656        : width(0), height(0) {}

I’m calling function in /home/jx23014/opencv347/include/opencv2/core/types.hpp, which is my after-compiled library. But keep stepping to

(gdb) s
cv::trace (_m=...) at /home/jx23014/opencv-3.4.7/modules/core/src/matrix_operations.cpp:229
229         CV_INSTRUMENT_REGION();

It’s now in (gdb) s cv::trace (_m=...) at /home/jx23014/opencv-3.4.7/modules/core/src/matrix_operations.cpp:229 229 CV_INSTRUMENT_REGION();

The double trace(const Matx<_Tp, m, n>& a function mentioned before is a function found in /home/jx23014/opencv347/include/opencv2/core/matx.hpp. This function seems to have a same name as “trace” while not called in gdb. It looks like this

template<typename _Tp, int m, int n> static inline
double trace(const Matx<_Tp, m, n>& a)
{
    _Tp s = 0;
    for( int i = 0; i < std::min(m, n); i++ )
        s += a(i,i);
    return s;
}

please, NO SCREENSHOTS OF CODE ANYWHERE ON THE INTRNETZ !

apart from that, if you want any other person to debug this–
please do NOT use outdated 3.4.7 (we’re at 4.7.0-dev now)

I’m sorry, I know it’s a outdated one. Our course project asked us to rewritten some opencv function in assembly for performance improvement. It specified the trace function in this version.

mate, that’s plain sadism !

rewritten some opencv function in assembly

like what ? neon ? nasm ?

aarch64, we’re provided with a server to run the experiment. If we manage to get it 2x faster than original opencv, we get a A.

1 Like

Do you think your teacher can get a A? :smiling_face:

related (same author):