2017-08-06 151 views
0

首先,我对Python和它的库相对陌生。如何用numpy快速迭代并修改像素数组?

以下代码的目的是将HDR图像转换为RGBM,详见WebGL Insights Chapter 16

import argparse 
import numpy 
import imageio 
import math 

# Parse arguments 
parser = argparse.ArgumentParser(description = 'Convert a HDR image to a 32bit RGBM image.') 
parser.add_argument('file', metavar = 'FILE', type = str, help ='Image file to convert') 
args = parser.parse_args() 

# Load image 
image = imageio.imread(args.file) 
height = image.shape[0] 
width = image.shape[1] 

output = numpy.zeros((height, width, 4)) 

# Convert image 
for i in numpy.ndindex(image.shape[:2]): 
    rgb = image[i] 
    rgba = numpy.zeros(4) 
    rgba[0:3] = (1.0/7.0) * numpy.sqrt(rgb) 
    rgba[3] = max(max(rgba[0], rgba[1]), rgba[2]) 
    rgba[3] = numpy.clip(rgba[3], 1.0/255.0, 1.0) 
    rgba[3] = math.ceil(rgba[3] * 255.0)/255.0 
    output[i] = rgba 

# Save image to png 
imageio.imsave(args.file.split('.')[0] + '_rgbm.png', output) 

该代码工作并产生正确的结果,但它做得非常慢。这当然是通过在python中单独遍历每个像素引起的,对于较大的图像可能需要很长时间(对于大小为3200x1600的图像,大约需要4:30分钟)。

我的问题是:有没有更有效的方法来实现我所追求的?我简单地研究了矢量化和numpy广播,但还没有找到一种方法将这些应用到我的问题。

编辑:

感谢MATEEN Ulhaq,我找到了解决办法:

# Convert image 
rgb = (1.0/7.0) * numpy.sqrt(image) 
alpha = numpy.amax(rgb, axis=2) 
alpha = numpy.clip(alpha, 1.0/255.0, 1.0) 
alpha = numpy.ceil(alpha * 255.0)/255.0 
alpha = numpy.reshape(alpha, (height, width, 1)) 
output = numpy.concatenate((rgb, alpha), axis=2) 

这就完成了只有几秒钟。

回答

1

线

for i in numpy.ndindex(image.shape[:2]): 

只是遍历每个像素。摆脱循环并处理每行代码中的每个像素(“矢量化”)可能会更快。

rgb = (1.0/7.0) * np.sqrt(image) 
alpha = np.amax(rgb, axis=2) 
alpha = np.clip(alpha, 1.0/255.0, 1.0) 
alpha = np.ceil(alpha * 255.0)/255.0 
alpha = numpy.reshape(alpha, (height, width, 1)) 
output = np.concatenate((rgb, alpha), axis=2) 

我认为它也更清晰一些。

+0

这会产生错误“ValueError:连接时所有输入数组必须具有相同的维度数”。 **编辑:**修复它(见OP)。 – tomfulghum