gpt4 book ai didi

c++ - 在opencv中按权重图像划分图像的每个 channel

转载 作者:搜寻专家 更新时间:2023-10-31 02:20:05 24 4
gpt4 key购买 nike

我有一个 3 channel 图像,基本上是加权补丁的组合。将所有贡献添加到我的总和图像后,我想将其除以权重。现在,我使用以下代码:

Mat weighted_sum, weights;
// for (Patch p: patches)
// weighted_sum[loc_p] += w * p
// weights[loc_p] += w;

vector<Mat> channels(3);
split(weighted_sum, channels);
for (Mat chan: channels) {
divide(chan, weights, chan);
}
merge(channels, reconstructed);

是否有更有效的解决方案来将图像的所有 3 个 channel 除以相同的 1 个 channel 图像?

最佳答案

我测试了你的方法:

  1. 拆分 - 划分 - 合并,@panmari
  2. 线性化矩阵,并应用元素智能除法@Miki
  3. 线性化矩阵,并应用元素明智的除法(使用指针)@Miki 和乘法而不是除法@Micka
  4. weights 设为 3 channel 矩阵,并对整个矩阵应用 divide @Micka。

结果(以毫秒为单位):

Size            Method1         Metdhod2        Method3         Method4
[2 x 2] 0.0359212 0.00183271 0.000733086 1.77333
[10 x 10] 0.0117294 0.00293234 0.00109963 0.0051316
[100 x 100] 0.422624 0.241918 0.0751413 0.319625
[1000 x 1000] 20.757 20.3673 7.28284 18.4389
[2000 x 2000] 83.6238 82.942 28.4353 74.2132

注意事项

  • 我的方法运行速度更快,但速度提升与矩阵的大小有关。
  • 方法 3(带指针)最快
  • 方法 2 和方法 3 修改原始矩阵。如果您不需要更改原始矩阵,则需要进行深拷贝(clone(),请参见下面代码中的注释行)。对于原始矩阵的深拷贝,两种方法都较慢,但方法 3 仍然是最快的。
  • 方法 4 不适用于 double 矩阵,因为 cvtColor 不接受 double)。
  • 方法 4 的预分配矩阵只是一个小改进。
  • 使用编译器 msvc12 (Visual Studio 2013) 进行测试。对于 gcc 4.8,方法 4 似乎更快。

这是我使用的代码。我正在测试浮点矩阵,但很容易移植到其他类型。

    #include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>
using namespace std;
using namespace cv;


int main()
{
vector<Size> sizes{Size(2,2), Size(10,10), Size(100,100), Size(1000,1000), Size(2000,2000)};

cout << "Size \t\tMethod1 \tMetdhod2 \tMethod3 \tMethod4" << endl;

for (int is = 0; is < sizes.size(); ++is)
{

Size sz = sizes[is];
Mat3f weighted_sum(sz);
randu(weighted_sum, 0, 200);

Mat1f weights(sz);
randu(weights, 0, 10);

Mat3f ws1 = weighted_sum.clone();
Mat3f ws2 = weighted_sum.clone();
Mat3f ws3 = weighted_sum.clone();
Mat3f ws4 = weighted_sum.clone();



// Method 1 @parmari
double tic1 = double(getTickCount());
Mat3f rec1;

vector<Mat> channels(3);
split(ws1, channels);
for (Mat chan : channels) {
divide(chan, weights, chan);
}
merge(channels, rec1);

double toc1 = (double(getTickCount() - tic1)) * 1000. / getTickFrequency();

// Method 2 @Miki
double tic2 = double(getTickCount());
Mat3f rec2 = ws2.reshape(3, 1);
//Mat3f rec2 = ws2.reshape(3, 1).clone(); // To not override original image
Mat1f ww2 = weights.reshape(1, 1);
for (int i = 0; i < rec2.cols; ++i)
{
double w = ww2(0, i);
Vec3f& v = rec2(0, i);
v[0] /= w;
v[1] /= w;
v[2] /= w;
}
rec2 = rec2.reshape(3, ws2.rows);

double toc2 = (double(getTickCount() - tic2)) * 1000. / getTickFrequency();


// Method 3 @Miki (+ @Micka)
double tic3 = double(getTickCount());
Mat3f rec3 = ws3.reshape(3, 1);
//Mat3f rec3 = ws3.reshape(3, 1).clone(); // To not override original image
Mat1f ww3 = weights.reshape(1, 1);

Vec3f* prec3 = rec3.ptr<Vec3f>(0);
float* pww = ww3.ptr<float>(0);

for (int i = 0; i < rec3.cols; ++i)
{
float scale = 1. / (*pww);
(*prec3)[0] *= scale;
(*prec3)[1] *= scale;
(*prec3)[2] *= scale;

++prec3; ++pww;
}
rec3 = rec3.reshape(3, ws3.rows);

double toc3 = (double(getTickCount() - tic3)) * 1000. / getTickFrequency();


// Method 4 @Micka
double tic4 = double(getTickCount());
Mat3f rec4;
Mat3f w3ch4;
cvtColor(weights, w3ch4, COLOR_GRAY2BGR);
divide(ws4, w3ch4, rec4);

double toc4 = (double(getTickCount() - tic4)) * 1000. / getTickFrequency();

cout << sz << " \t" << toc1 << " \t" << toc2 << " \t" << toc3 << " \t" << toc4 << endl;

}

getchar();

return 0;
}

关于c++ - 在opencv中按权重图像划分图像的每个 channel ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33098797/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com