【问题标题】:divide two matrices in opencv在opencv中划分两个矩阵
【发布时间】:2014-01-07 15:24:56
【问题描述】:

我想对两个 opencv CV_32S 矩阵(A 和 B)进行元素除法。

当 B 不为 0 时,我希望 C = A/B,否则为 0。

但我不确定是否理解 opencv 文档:

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

上面写着:

当 src2(I) 为零时,dst(I) 也将为零。多通道数组的不同通道独立处理。

注意当输出数组的深度为 CV_32S 时,不应用饱和度。在溢出的情况下,您甚至可能得到错误符号的结果。

saturate() 函数是什么?我可以在 CV_32S 矩阵中安全地使用 divide(A,B,C) 吗? divide() 与 / 操作符有何不同?

===== 测试后编辑 =====

我的测试表明 / 运算符完全符合我的要求:当 B != 0 时 C = A/B,否则为 0。

【问题讨论】:

    标签: c++ opencv matrix


    【解决方案1】:

    saturate_cast 防止某些数据类型溢出,例如像素值200+200 减少到255 for CV_8U(否则会出现溢出并可能出现意外值)。

    如果您想了解有关 saturate_cast 的更多信息,请查看该链接。 http://docs.opencv.org/modules/core/doc/intro.html#saturation-arithmetics

    由于整数除法总是减少绝对值,所以整数除法应该不会发生溢出(或者我错过了什么?),所以我猜你应该是安全的。

    【讨论】:

    • 谢谢! divide() 与 / 运算符有何不同?
    • 维基百科:“数字 2,147,483,647 是计算中 32 位有符号整数的最大值”。因此,如果您将两个 32F 元素相除,如果结果是目标 32S 的溢出,则会发生意外行为。但是,对于输入 32S 矩阵,您是安全的。你需要重载 cv::Mat 的操作符/方法来实现额外的行为。
    • 我不知道除法与标准 / 运算符有何不同。也许他们转换为浮点数并使用 SSE 指令,或者他们在内部使用 / 运算符,也许您可​​以在 openCV 源代码中找到这些部分;)
    • 我查看了源代码(在matop.cpp第463行),但它充满了MatOp_Bin::makeExpr(),我不太明白......
    【解决方案2】:

    所以,operator/cv::divide 实际上应该是相同的,只是运算符将返回一个矩阵表达式,其评估被延迟。最后,operator/ 也将调用cv::divide,可以看出 e。 G。对于一个简单的案例here。特别是结果应该相等。

    不过,结果可能令人惊讶。使用两个整数矩阵进行除法,结果就像在浮点运算中完成,然后是round to nearest integer 更喜欢偶数(另请参阅nearbyint())。例如,使用两个 6x6 整数矩阵,您将得到

    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
    

    注意(如您在文档中所述),但还要注意(四舍五入)和 而(平局)。


    注意: 两个浮点类型矩阵没有定义任何特殊行为,而是在被零除的情况下计算为 -inf、nan 或 inf。当您将两个浮点矩阵相除但请求整数结果时,这甚至成立。在这种情况下,-inf、nan 和 inf 将转换为最小值,这可能是一个错误(或者只是 OpenCV 没有定义)。


    整数除法代码div.cpp(用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;
    }
    

    【讨论】:

      猜你喜欢
      • 2020-02-04
      • 1970-01-01
      • 1970-01-01
      • 2018-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-29
      • 2011-12-29
      相关资源
      最近更新 更多