2016-09-30 32 views
2

在我的圖像編輯應用程序中,我有一個將sRGB的32位浮點圖像轉換爲線性色彩空間的功能。其計算公式爲:在numpy中向量化sRGB到線性轉換

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

我的圖像是三維numpy.ndarray命名img32

我實施至今:

boolarray = img32 <= 0.04045 
lower = (img32/12.92) * boolarray.astype(np.int) 
upper = np.power(((img32 + 0.055)/1.055), 2.4) * np.invert(boolarray).astype(np.int) 
img32 = lower + upper 

所以,我創建一個新的數組boolarray,用真值< = 0.04045,並通過繁殖。

什麼是更好的解決方案?

我想是這樣的:

img32[img32 < 0.04045] = img32/12.92 

其工作的第一步,但未能在第二:

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

可能是因爲包裹在np.power當它不工作功能

任何幫助表示讚賞。

+0

'更好solution' - 如何更好?內存明智還是性能明智? – Divakar

+0

更清潔的東西,因爲這在我看來有點像黑客。我非常想找到這樣做的標準方法。還沒有測試過速度(這是相當快),但我想這絕對是浪費內存?抱歉不清楚。 – tde

回答

1

一個乾淨的方式將與np.where,讓我們可以根據掩碼選擇兩個值。在我們的情況下,面具可能是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) 

,你可以把它的三個步驟 -

所以,我們必須像這樣的實施通過創建並選擇性地設定對應於這些兩個條件,像這樣elems的 -

mask = img32 >= 0.04045 
img32[mask] = ((img32[mask] + 0.055)/1.055)**2.4 
img32[~mask] = img32[~mask]/12.92 

樣品情況下 -

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%。請注意,這可能會導致性能略有下降。

+0

非常感謝! – tde

0
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 
1

您還可以使用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') 
+0

謝謝!現在我正在使用np.where,但稍後我會對執行速度進行比較,以查看最快和最有效的運行速度。 – tde