使用 OpenCV 的逐元素幂

Element-wise power using OpenCV

我正在阅读 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 中的值。

我试图在 dst 中重新分配 ptrs[2][j] 但未能获得 dst 的正确索引。我的问题如下:

  1. 有没有像Matlab中的A .^ B那样方便的求矩阵元素幂的方法?
  2. 有没有办法利用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 放在函数内,因为它会修改图像表示,这可能会影响以后的操作。相反,在临时垫上使用 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^b等价于c = e^(b.ln(a))的关系。此处,矩阵的类型应为 32F64F。这会产生

[1, 4, 27.000002;
  4, 25.000002, 216.00002;
  6.9999995, 64, 729.00006]

对于上面的例子。