在opencv中按权重图像划分图像的每个通道

时间:2015-10-13 09:19:57

标签: c++ opencv image-processing

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

awk '{if(length($0) == 485) { print $0 }}' in.txt > 485.txt
awk '{if(length($0) == 501) { print $0 }}' in.txt > 501.txt

是否有更高效的解决办法将图像的所有3个通道分割为相同的1通道图像?

1 个答案:

答案 0 :(得分:2)

我测试了你的方法:

  1. split - divide - merge,@ panmari
  2. 线性化矩阵,并应用元素分割@Miki
  3. 线性化矩阵,并应用元素分割(使用指针)@Miki和乘法而不是除法@Micka
  4. weights设为3通道矩阵,并在整个矩阵@Micka上应用divide
  5. 结果(以毫秒为单位):

    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;
    }