我对上一个问题进行了搜索,但没有找到优化代码的必要条件。
有关信息,我在Python 2.7上运行,但如果需要可以更改为3
我正在转换图像的每个像素,由于某些条件,我必须逐像素进行转换。 因此,我在其中嵌套了if-elif-else语句的for循环,这需要很长时间才能运行。 对于1536 x 2640的图像,整个代码需要约20秒的时间,而90%的时间都在这个double for循环内
我相信应该有更好的方式编写以下代码
for pixel in range(width):
for row in range(height):
ADC = img_original[row, pixel]
if ADC < 84:
gain = gain1
offset = offset1
elif ADC > 153:
gain = gain3
offset = offset3
else:
gain = gain2
offset = offset2
Conv_ADC = int(min(max(ADC * gain + offset, 0),255))
img_conv[row, pixel] = Conv_ADC
感谢您的帮助
编辑以获取更多详细信息:
@Jean-FrançoisFabre是正确的,我将根据在0到255之间的哪个部分来应用三个不同的增益/偏移。但是该部分并不总是均匀分布,可以修改。 也许要提供一些附加的上下文,我只是在图像上应用自定义S曲线以向上/向下移动像素值。而且图像中的每一列都有自己的S形曲线
我的增益1,2,3 /偏移1,2,3的值是浮点数。增益将始终为正,偏移量可以为负或正。我在宽度方向上每个像素都有一个单独的值,但在行方向上是相同的。
例如,第1列的所有像素都可以使用下表第一行的增益/偏移1,2,3。图像中第2列的所有像素将使用下表中第2行的增益/偏移量
Pixel Gain1 Offset1 Gain2 Offset2 Gain3 Offset3
1 0.417722 24.911392 0.623188 7.652176 1.175676 -76.878357
2 0.43038 25.848103 0.623188 9.652176 1.148649 -70.743225
3 0.443038 23.784809 0.637681 7.434776 1.175676 -74.878357
4 0.443038 22.784809 0.652174 5.217384 1.175676 -74.878357
5 0.455696 23.721519 0.637681 8.434776 1.202703 -78.013519
6 0.455696 21.721519 0.637681 6.434776 1.243243 -86.216217
7 0.455696 22.721519 0.623188 8.652176 1.216216 -82.081085
8 0.443038 22.784809 0.623188 7.652176 1.22973 -85.148651
... until pixel 2640 in width direction
我将研究@Jean-FrançoisFabre解决方案,但与此同时,我也正在研究使用一些numpy方法。
一旦我获得了计算速度更快的东西,我会在这里发布我的发现
答案 0 :(得分:2)
由于您的值介于0到255之间,并且边界是均匀分布的,因此可以使用以下技巧:
您似乎想应用3种不同的增益,具体取决于您位于0-255范围的前三分之一,后三分之一还是后三分之一。
为什么不通过除以85(255/3)来计算索引?
简单的概念证明:
gainsoffsets = [(10,1),(20,2),(30,3),(30,3)] # [(gain1,offset1),(gain2,offset2),(gain3,offset3)] + extra corner case for value 255
for value in 84,140,250:
index = value // 85
gain,offset = gainsoffsets[index]
print(gain,offset)
结果:
10 1
20 2
30 3
在此循环中,只有一个除法,没有if
。应该更快(除了numpy
方法之外)
您可以使用更精确的查询表(也可以通过生成256个元组来避免除法):
gainsoffsets = [(10,1)]*85+[(20,2)]*85+[(30,3)*86] # add more intervals for more thresholds
答案 1 :(得分:1)
尝试使用查找表:您预先计算了[0,255]
范围内的所有转换ADC值,并且循环体将简化
for pixel in range(width):
for row in range(height):
img_conv[row, pixel]= LUT[img_original[row, pixel]]
答案 2 :(得分:0)
这是我用来删除2个for循环的最终实现。每张图像下降到大约1〜2秒
我正在创建3个数组,当它不在我想要的范围内时,我将内容替换为0。然后对每个增益进行乘法和偏移,然后再将其相加
height = img_original.shape[0]
width = img_original.shape[1]
print 'height = ', height, 'width = ', width
# create temp 3 2D-arrays
img1 = np.array(img_original,dtype=np.int)
img2 = np.array(img_original,dtype=np.int)
img3 = np.array(img_original,dtype=np.int)
#create the 2D array for gain/offset based on 1D array
# csv array acquire from .csv file, INDEX_xx for column to read
array_gain1 = np.tile(csv[1:, INDEX_G1],(height,1))
array_offset1 = np.tile(csv[1:, INDEX_O1],(height,1))
array_gain2 = np.tile(csv[1:, INDEX_G2],(height,1))
array_offset2 = np.tile(csv[1:, INDEX_O2],(height,1))
array_gain3 = np.tile(csv[1:, INDEX_G3],(height,1))
array_offset3 = np.tile(csv[1:, INDEX_O3],(height,1))
# replace the content by 0 when not in the desired zone
np.place(img1,img_original >= G2_TARGET, 0)
np.place(img2,img_original < G2_TARGET,0)
np.place(img2,img_original > G1_TARGET,0)
np.place(img3,img_original <= G1_TARGET, 0)
np.place(array_offset1,img_original >= G2_TARGET, 0)
np.place(array_offset2,(img_original < G2_TARGET), 0)
np.place(array_offset2,(img_original > G1_TARGET), 0)
np.place(array_offset3,img_original <= G1_TARGET, 0)
# apply the gain/offset for each zone
img1 = np.array(img1 * array_gain1 + array_offset1, dtype=np.uint8)
img2 = np.array(img2 * array_gain2 + array_offset2, dtype=np.uint8)
img3 = np.array(img3 * array_gain3 + array_offset3, dtype=np.uint8)
# recrete the whole image
img_conv = np.clip(img1 + img2 + img3, 0, 255)