2012-02-08 75 views
2

我正在写一个解压缩器(其中包括)必须将增量滤镜应用于RGB图像。也就是说,读取其中只有第一个像素是绝对的(R1,G1,B1)并且所有其他图像都是(R [n] -R [n-1],G [n] -G [n-1 ],B [n] -B [n-1]),并将它们转换为标准RGB。在python/numpy中加速delta滤镜

现在我使用numpy的如下:

rgb = numpy.fromstring(data, 'uint8') 
components = rgb.reshape(3, -1, order='F') 
filtered = numpy.cumsum(components, dtype='uint8', axis=1) 
frame = numpy.reshape(filtered, -1, order='F') 

  • 线1创建的原始图像的一维阵列;
  • 线2重塑它在形式

    [[R1, R2, ..., Rn], [G1, G2, ..., Gn], [B1, B2, ..., Bn]] 
    
  • 线3执行实际defiltering

  • 线4再次转换回为一维数组

的问题是,它是我的需求太慢了。我对它进行了剖析,发现花费了大量的时间来重塑阵列。

所以我想知道:有没有避免重塑或加速的方法?

注:

  • 我不希望有写C扩展这一点。
  • 我已经使用多线程
+0

如果你的'rgb'数据范围从0到255,有一个很好的机会,'numpy.cumsum'会悄悄溢出。看看'x = np.arange(255,dtype ='uint8')'和'y = np.cumsum(x,dtype ='uint8')'会发生什么。 – unutbu 2012-02-08 20:05:47

+0

嗯,我认为它已经溢出了,或者换句话说,它的运行模式为255. – Alberto 2012-02-08 20:35:23

+0

糟糕,所以这是故意的。但是,不应该用'filtered = numpy.diff(components,axis = 1)'来计算'R [n] -R [n-1]'等等。 – unutbu 2012-02-08 20:43:50

回答

1

首先,当你读它,你可以告诉它多一点有关的类型,请尝试:

rgb = numpy.fromstring(data, '3uint8') 

没有重塑需要。

接下来,对于大型操作,您可以避开它(并且cumsum有资格),请使用out= param来防止移动数据......所有事情都会发生。用途:

rgb.cumsum(axis=0,out=rgb) 

如果你仍然想它夷为平地:

rgb = rgb.ravel() 
+0

总体速度提高了15%左右,谢谢!我非常接近3个内核就足够了(这是我的目标)。 – Alberto 2012-02-08 20:43:15

+0

经过一些其他的实验后,我发现使用这种布局不需要将它弄平。删除rgb.ravel()生成了另一个+ 5%! – Alberto 2012-02-08 21:03:39

2

出于某种原因,我还不明白,最终重塑你的代码拷贝数据。这可以通过使用替代的Fortran订单C为了避免:

rgb = numpy.fromstring(data, 'uint8') 
components = rgb.reshape(-1, 3) 
filtered = numpy.cumsum(components, dtype='uint8', axis=0) 
frame = filtered.reshape(-1) 
+0

您能否在最终重塑的情况下显示在什么情况下复制数据?我自己从'rgb = np.fromstring('\ x01 \ x02 \ x03'* 2,dtype = np.uint8)'开始并看到'frame.flags ['OWNDATA']' 。 – unutbu 2012-02-08 20:37:45

+0

感谢您的提示,它提高了约12%的速度。 – Alberto 2012-02-08 20:52:19

+0

@unutbu:我发现仅仅看着'owndata'标志并不是一个可靠的方法来确定一个副本是否在两者之间。我做了'frame [:] = 0'并检查'filtered'是否也被清零,但事实并非如此。 – 2012-02-08 21:09:23