Mat::convertTo (); question on scaling

I want to convert a CV_32FC2 matrix (output from dense flow) to an CV_8UC2 matrix.

The values in flow matrix are of a “typical” movie (small absolute values, both positve and negative).
For my purpose I need an additional arithmetic mapping: (flow + 10) * 15.

My first attempt was

Mat flowTmp,
    flowInt;

flowTmp = flow + 10;
flowTmp.convertTo (flowInt, CV_8UC2, 15);

OK.
As scaling and addition is done 32bit float, mapping can be simplified to:

flow.convertTo (flowInt, CV_8UC2, 15, 150);

But when comparing the number of unique entries in flowInt for both calculations above

std::set<int> unique;
// iterate over pixels (assumes: CV_8UC2 !)
for (Vec2b &p : cv::Mat_<Vec2b>(flowInt)) {
    // "hash" representation of the 2D-pixel
    int n = (p[0] << 8) | (p[1]);
    unique.insert(n);
}

The first calculation shows only about half as much unique entries as the second one.
(Last seems to be the right value).

There will be rounding errors, but being float they won’t have such large impact.

What am I doing wrong?

I don('t understand your problem :

       Mat flow1 = (Mat_<float>(3, 2) << 0, 1, 2, 3, 4, 5) / 10.0;
        Mat flow2 = (Mat_<float>(3, 2) << 6, 5, 4, 3, 2, 1) / 10.0;
        Mat flow;
        merge(vector<Mat>{ flow1, flow2 }, flow);
        cout << "FLOW :\n";
        cout << flow << "\n";
        Mat flowTmp = flow + 10;
        cout << "FLOW +10:\n";
        cout << flowTmp << "\n";
        Mat flowInt;
        flowTmp.convertTo(flowInt, CV_8UC2, 15, 150);
        cout << "(FLOW+10)*15+150 :\n";
        cout << flowInt << "\n";
        return 0;

results :
FLOW :
[0, 0.60000002, 0.1, 0.5;
0.2, 0.40000001, 0.30000001, 0.30000001;
0.40000001, 0.2, 0.5, 0.1]
FLOW +10:
[10, 0.60000002, 10.1, 0.5;
10.2, 0.40000001, 10.3, 0.30000001;
10.4, 0.2, 10.5, 0.1]
(FLOW+10)*15+150 :
[255, 159, 255, 158;
255, 156, 255, 154;
255, 153, 255, 152]

1 Like

Thanks to your example - I do now:

I meant:

flowTmp = flow + Scalar (10,10);

Still a beginner with OpenCV I’m not so familiar with quick test code.

I understand your problem. may be converto doc is ambiguous OpenCV: cv::Mat Class Reference

alpha and beta is apply to all src(Mat) channels

but src+10 is apply to only first Channel

Probably there will be good reasons for taking src+10 as appliance to the first channel only and not to all elements…
However… I will have to thorougly check all my so far code … :wink: