提升数组子集赋值的性能
12027 评分:
4.0
提升数组子集赋值的性能
匿名作者 2015年6月11日,星期四
在处理多维数据(例如图像)时,有时需要用另一块相同尺寸的数据块替换原有数据块。对于图像而言,这可能是需要替换的云层覆盖区域,或是需要替换的光谱波段。
以空间替换为例,假设我们要用尺寸相同的数据块替换一部分数据。本例中,子集为50行50列,而更大的数据尺寸为250行250列。
IDL> array = bytarr(250, 250) + 127B
IDL> sub = indgen(50, 50)
在IDL中替换部分数据,可能会采用这种方式:
IDL> array[50:99, 100:149] = sub
这种方法可行,但并非最快的方式。通过上述替换方法,IDL会逐个替换每个元素。若要一次性替换整个子集,IDL只需要指定子集需要插入的起始索引位置:
IDL> array[50, 100] = sub
IDL将一次性填充数据,直至整个子集都插入到更大的数组中。但需注意,如果空间不足,IDL可能会产生意外结果或抛出越界错误。以下是我们刚刚操作的数组图像:
IDL> i = image(array)

数组中的数组
其优势在于,这种方式比显式调用要替换的数组元素或使用通配符(*)要快得多。让我们看下一个使用通配符的例子——替换波段。
如果我们想降低图像中的红色分量,可以通过将红色波段乘以小于1的数值来实现。首先,获取一些图像数据:
IDL> file = file_which('rose.jpg')
IDL> read_jpeg, file, data
IDL> help, data
DATA BYTE = Array[3, 227, 149]
为了获取红色波段,我们需要使用通配符。但这不会造成性能问题,因为我们只是将数据块赋值给变量,并未进行替换操作。一个良好的经验法则是,尽量避免在赋值语句的左侧使用通配符,而在右侧使用通配符是可以接受的。
IDL> red = data[0,*,*]
现在将原始红色波段替换为其乘以0.6的结果。我们可以再次使用通配符来实现:
IDL> data[0,*,*]= byte(red * 0.6)
但现在我们知道,这不是在IDL中赋值该波段最高效的方式。我们只需要指定要替换数据的起始索引:
IDL> data[0,0,0] = byte(red* 0.6)
由于红色波段的尺寸未变,整个波段将一次性被替换,而不是逐个元素替换。对于这些小数组,速度提升并不明显,但对于更大的数据集,采用这种实践对于实现高性能至关重要。
IDL> i = image(data)
