在Numpy中实现sRGB到线性转换的矢量化

2024-03-28 12:52:55 发布

您现在位置:Python中文网/ 问答频道 /正文

在我的图像编辑应用程序中,我有一个将32位浮点图像从sRGB转换为线性颜色空间的函数。公式为:

if value <= 0.04045: (value / 12.92)
if value > 0.04045: ((value + 0.055) / 1.055)^2.4)

我的形象是三维的努比·恩达雷命名为img32。在

我目前的实施情况:

^{pr2}$

因此,我创建了一个新的数组boolarray,其真值为<;=0.04045并乘以该值。在

什么是更好的解决方案?在

我试过这样的方法:

img32[img32 < 0.04045] = img32 / 12.92

第一步有效,第二步失败:

img32[img32 >= 0.04045] = np.power(((img32 + 0.055) / 1.055), 2.4)

可能是因为它在np.功率功能

感谢任何帮助。在


Tags: 函数图像应用程序ifvalue颜色np空间
3条回答

一个干净的方法是使用^{},它允许我们根据掩码在两个值之间进行选择。在我们的例子中,掩码可以是img32 >= 0.04045,当True时,我们将选择((img32 + 0.055) / 1.055)**2.4,否则使用img32/12.92

所以,我们会有这样的实现-

np.where( img32 >= 0.04045,((img32 + 0.055) / 1.055)**2.4, img32/12.92 )

如果您非常关心内存,并且希望将结果写回输入数组中,您可以通过创建和有选择地设置与这两个条件相对应的元素,分三步完成,如-

^{pr2}$

示例案例-

In [143]: img32 = np.random.rand(4,5).astype(np.float32)

In [144]: img32.nbytes
Out[144]: 80

In [145]: mask.nbytes
Out[145]: 20

因此,我们避免创建一个输出数组,该数组将消耗我们80字节,而是在掩码上使用20字节。因此,在内存上保存输入数组大小的75%。请注意,这可能会导致性能略有下降。

b = (img32 < 0.04045)
img32[b] /= 12.92

not_b = numpy.logical_not(b)
img32[not_b] += 0.05
img32[not_b] /= 1.055
img32[not_b] **= 2.4

您还可以使用numpy.piecewise

In [11]: img32 = np.random.rand(800, 600).astype(np.float32)

In [12]: img_linear = np.piecewise(img32, 
           [img32  <= 0.04045, img32 > 0.04045], 
           [lambda v: v/12.92, lambda v: ((v + 0.055)/1.055)**2.4] )

In [13]: img_linear.shape
Out[13]: (800, 600)

In [14]: img_linear.dtype
Out[14]: dtype('float32')

相关问题 更多 >