使用 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
的正确索引。我的问题如下:
- 有没有像Matlab中的
A .^ B
那样方便的求矩阵元素幂的方法?
- 有没有办法利用
cv::NAryMatIterator
达到这个目的?如果不是,那么最有效的实现方式是什么?
您可以通过将 src1
、src2
和 dst
转换为 float (CV_32F)
类型矩阵来实现此功能。这是因为代码在 float* ptrs[3];
.
中以这种方式对待它们
最后给出了使用 opencv
函数 log
、multiply
和 exp
的替代实现。
作为第二个问题的例子,
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))
的关系。此处,矩阵的类型应为 32F
或 64F
。这会产生
[1, 4, 27.000002;
4, 25.000002, 216.00002;
6.9999995, 64, 729.00006]
对于上面的例子。
我正在阅读 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
的正确索引。我的问题如下:
- 有没有像Matlab中的
A .^ B
那样方便的求矩阵元素幂的方法? - 有没有办法利用
cv::NAryMatIterator
达到这个目的?如果不是,那么最有效的实现方式是什么?
您可以通过将 src1
、src2
和 dst
转换为 float (CV_32F)
类型矩阵来实现此功能。这是因为代码在 float* ptrs[3];
.
最后给出了使用 opencv
函数 log
、multiply
和 exp
的替代实现。
作为第二个问题的例子,
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))
的关系。此处,矩阵的类型应为 32F
或 64F
。这会产生
[1, 4, 27.000002;
4, 25.000002, 216.00002;
6.9999995, 64, 729.00006]
对于上面的例子。