简体   繁体   中英

divide two matrices in opencv

I would like to perform a element-wise division of two opencv CV_32S matrices (A & B).

I want C = A/B when B is not 0, 0 otherwise.

But I'm not sure to understand opencv documentation:

http://docs.opencv.org/modules/core/doc/operations_on_arrays.html#divide

It says:

When src2(I) is zero, dst(I) will also be zero. Different channels of multi-channel arrays are processed independently.

Note Saturation is not applied when the output array has the depth CV_32S. You may even get result of an incorrect sign in the case of overflow.

What does the saturate() function? Can I use divide(A,B,C) safely with CV_32S matrices? How is divide() different from the / operator?

===== EDIT AFTER TEST =====

My test showed that the / operator does exactly what I want: C = A/B when B != 0, 0 otherwise.

saturate_cast prevents overflows for some data types, so that pixel values 200+200 are reduced to 255 for CV_8U for example (otherwise there would be an overflow and maybe unexpected values occur).

Have a look at the link if you want to know more about saturate_cast. http://docs.opencv.org/modules/core/doc/intro.html#saturation-arithmetics

Since integer division always reduces the absolute values, there should no overflows occur in integer division (or am I missing something?), so you should be safe I guess.

So, operator/ and cv::divide should be actually the same, except that the operator will return a matrix expression, whose evaluation is delayed. Finally, also operator/ will call cv::divide , as can be seen eg for a simple case here . Especially the results should be equal.

Still, the results can be surprising. Using two integer matrices for division, the result will be like done in floating point arithmetic followed by a round to nearest integer preferring even numbers (see also nearbyint() ). As an example, using two 6x6 integer matrices, you will get

0/0 == 0    1/0 == 0    2/0 == 0    3/0 == 0    4/0 == 0    5/0 == 0
0/1 == 0    1/1 == 1    2/1 == 2    3/1 == 3    4/1 == 4    5/1 == 5
0/2 == 0    1/2 == 0    2/2 == 1    3/2 == 2    4/2 == 2    5/2 == 2
0/3 == 0    1/3 == 0    2/3 == 1    3/3 == 1    4/3 == 1    5/3 == 2
0/4 == 0    1/4 == 0    2/4 == 0    3/4 == 1    4/4 == 1    5/4 == 1
0/5 == 0    1/5 == 0    2/5 == 0    3/5 == 1    4/5 == 1    5/5 == 1

Note thediv-by-0-equals-0 (as you stated from the documentation), but also note 四舍五入 (rounding) and 抢七局-1-2 while抢七局-3-2 (tie break to even).


Beware: Two floating point type matrices do not define any special behavior, but rather evaluate to -inf, nan or inf in case of division by zero. This even holds, when you divide two floating point matrices, but requesting an integer result. In that case -inf, nan and inf will translate to the minimum value, which might be a bug (or just not defined by OpenCV).


Code for integer division div.cpp (compile with g++ -std=c++11 div.cpp -o div -lopencv_core ):

#include <opencv2/opencv.hpp>
#include <iostream>
#include <cstdint>

int main() {
    cv::Mat i1(6,6,CV_32S);
    cv::Mat i2(6,6,CV_32S);
    for (int y = 0; y < i1.rows; ++y) {
        for (int x = 0; x < i1.cols; ++x) {
            i1.at<int32_t>(y, x) = x;
            i2.at<int32_t>(y, x) = y;
        }
    }

    cv::Mat q;
    cv::divide(i1, i2, q);
//  q = i1 / i2;

    for (int y = 0; y < q.rows; ++y) {
        for (int x = 0; x < q.cols; ++x)
            std::cout << x << "/" << y << " == " << q.at<int32_t>(y, x) << "\t";
        std::cout << std::endl;
    }

    return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM