opencv - 使用OpenCV的逐元素电源

标签 opencv elementwise-operations

我目前正在阅读this book。作者在第83页上编写了一个代码段,以便(如果我正确理解的话)计算两个矩阵的逐元素幂。但是我认为代码没有实现其目的,因为执行后矩阵dst不包含逐元素的幂。

这是原始代码:

const Mat* arrays[] = { src1, src2, dst, 0 };
float* ptrs[3];

NAryMatIterator it(arrays, (uchar**)ptrs);
for( size_t i = 0; i < it.nplanes; i++, ++it )
{
    for( size_t j = 0; j < it.size; j++ )
    {
        ptrs[2][j] = std::pow(ptrs[0][j], ptrs[1][j]);
    }
}

由于构造函数或cv::NAryMatIterator的参数是const cv::Mat **,我认为不允许更改矩阵dst中的值。

我试图在ptrs[2][j]中重新分配dst,但是未能获得正确的dst索引。我的问题如下:
  • 是否有一种方便的方法来求矩阵元素的幂,如Matlab中的A .^ B
  • 是否可以使用cv::NAryMatIterator来实现此目标?如果否,那么最有效的实现方法是什么?
  • 最佳答案

    您可以通过将src1src2dst转换为float (CV_32F)类型矩阵来使其工作。这是因为代码在float* ptrs[3];中以这种方式对待它们。

    最后给出了使用opencv函数logmultiplyexp的替代实现。

    以第二个问题为例,

    Mat src1 = (Mat_<int>(3, 3) <<
        1, 2, 3,
        4, 5, 6,
        7, 8, 9);
    Mat src2 = (Mat_<uchar>(3, 3) <<
        1, 2, 3,
        1, 2, 3,
        1, 2, 3);
    Mat dst = (Mat_<float>(3, 3) <<
        1, 2, 3,
        4, 5, 6,
        7, 8, 9);
    
    src1.convertTo(src1, CV_32F);
    src2.convertTo(src2, CV_32F);
    
    cout << "before\n";
    cout << dst << endl;
    
    const Mat* arrays[] = { &src1, &src2, &dst, 0 };
    float* ptrs[3];
    NAryMatIterator it(arrays, (uchar**)ptrs);
    for( size_t i = 0; i < it.nplanes; i++, ++it )
    {
        for( size_t j = 0; j < it.size; j++ )
        {
            ptrs[2][j] = std::pow(ptrs[0][j], ptrs[1][j]);
        }
    }
    
    cout << "after\n";
    cout << dst << endl;
    

    输出
    before
    [1, 2, 3;
      4, 5, 6;
      7, 8, 9]
    after
    [1, 4, 27;
      4, 25, 216;
      7, 64, 729]
    

    如果删除src1.convertTo(src1, CV_32F);src2.convertTo(src2, CV_32F);,则不会获得所需的结果。尝试一下。

    如果这是一个单独的函数,请不要将convertTo放在该函数内,因为它会修改图像表示,这可能会影响以后的操作。而是在临时Mats上使用convertTo,例如
    Mat src132f, src232f, dst32f;
    src1.convertTo(src132f, CV_32F);
    src2.convertTo(src132f, CV_32F);
    dst.convertTo(dst32f, CV_32F);
    
    pow_mat(&src132f, &src232f, &dst32f); /* or whatever the name */
    

    关于您的第一个问题,我不知道这样的功能。但是你可以尝试像
    Mat tmp;
    cv::log(src1, tmp);
    cv::multiply(src2, tmp, dst);
    cv::exp(dst, dst);
    

    使用c = a^bc = e^(b.ln(a))等效的关系。在这里,矩阵的类型应为32F64F。这产生
    [1, 4, 27.000002;
      4, 25.000002, 216.00002;
      6.9999995, 64, 729.00006]
    

    对于上面的示例。

    关于opencv - 使用OpenCV的逐元素电源,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47103764/

    相关文章:

    python - 跨多个列表的逻辑 AND 运算

    python - 如何在 Numpy 中有效地将二维数组中的每个元素乘以一维数组?

    c++ - createButton OpenCV 新 Qt 功能

    c++ - 为 UWP 构建 OpenCV

    c++ - 在 OpenCV 中绘制多边形?

    Pandas 将 DataFrame 与索引和列的元素匹配相乘

    python-3.x - 需要帮助找到 2 个单独的轮廓而不是 MICR 代码中的组合轮廓

    c++ - OpenCV 3.0 : Calibration not fitting as expected

    matlab - matlab 中的 Elementwise ifs - 它们存在吗?