2014-11-01 77 views
0

我有一个具有不同拜耳图案的原始图像。 这是我为了分离频道而实施的。 速度在这里非常重要,因为这将会在成千上万的大型图像上运行。将拜耳图像分离为彩色通道C++

可以请您提出代码优化。 我知道%(模)不是很快,我怎么能取代这个例子?

感谢

void Utilities::SeparateChannels(int** _image, int*& gr, int*& r, int*& b, int*& gb,int _width, int _height, int _colorOrder) 
{ 
    //swith case the color Order 
    int counter_R = 0; 
    int counter_GR = 0; 
    int counter_GB = 0; 
    int counter_B = 0; 

    switch (_colorOrder) 
    { 
     //rggb 
    case 0: 

     for (int i = 0; i < _height; i++) 
     { 
      for (int j = 0; j < _width; j++) 
      { 
       if (i % 2 == 0 && j % 2 == 0) 
       { 
        r[counter_R] = _image[i][j]; 
        counter_R++; 
       } 
       else if (i % 2 == 0 && j % 2 == 1) 
       { 
        gr[counter_GR] = _image[i][j]; 
        counter_GR++; 
       } 
       else if (i % 2 == 1 && j % 2 == 0) 
       { 
        gb[counter_GB] = _image[i][j]; 
        counter_GB++; 
       } 
       else if (i % 2 == 1 && j % 2 == 1) 
       { 
        b[counter_B] = _image[i][j]; 
        counter_B++; 
       } 
      } 
     } 
     break; 
    default: 
     break; 
    }  
} 
+2

实际上,模通常是非常* *快当第二操作数是2的恒定功率,因为​​它总是似乎是在上面的代码。如果你愿意,你可以试试'&1'而不是'%2',但它可能没有任何区别。 – 2014-11-01 23:28:18

回答

1

一种可能性,即威力是值得考虑的。将设置为目的地的信道的数据阵列作为数组本身:

int *channels[] = {r, gr, gb, b}; 

同样地,设置了计数器作为阵列:

int counters[4] = {0}; 

...那么你的代码能够站出来这样的事情:

for (int i=0; i<_height; i++) 
    for (int j=0; j<_width; j++) { 
     channel = (i&1) << 1 + (j&1); 
     int &counter = counters[channel]; 

     channels[channel][counter++] = image[i][j]; 
    } 

的基本想法是,我们结合ij的低位进入,我们可以作为一个通道地址使用一个单一的数字。然后我们使用该数字来索引该频道的频道和计数器。

您的编译器可能已经优化了现有的代码,大致等同于此(或者甚至可能比此更好),但它也有可能不是。

虽然我通常不会期望有很多改进(至少在典型的台式计算机上)。我希望瓶颈是主存的带宽,几乎不管你写循环的细节如何。

1

您应该展开循环以处理2x2块。通过这种方式,您将始终知道这些奇偶校验,并且不需要对它们进行测试。

   r[counter_R] = _image[i][j]; 
       counter_R++; 

       gr[counter_GR] = _image[i][j+1]; 
       counter_GR++; 

       gb[counter_GB] = _image[i+1][j]; 
       counter_GB++; 

       b[counter_B] = _image[i+1][j+1]; 
       counter_B++; 

(也适应循环参数。)

+1

如果我是对的,你打算做一个最近的邻居重建。这会给你相当难看的结果。 (Bi)线性插值在视觉上会更好。如果你想要速度,那么就应该考虑SSE向量化(但是对于这种特殊的转换,这将是艰巨的;不要指望编译器能够帮助你)。 – 2014-11-02 10:49:18