2016-09-30 1 views
2

내 이미지 편집 응용 프로그램에는 32 비트 부동 소수점 이미지를 sRGB에서 선형 색상 공간으로 변환하는 함수가 있습니다. 공식은 다음Numpy에서 sRGB를 선형 변환으로 올바르게 벡터화

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

내 화상 img32라는 입체 numpy.ndarray이다. 지금까지

내 구현 :

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 

그래서, 나는 = <에 대한 0.04045를 진리 값을 갖는 새 배열 boolarray를 생성하고 그 곱입니다.

더 나은 솔루션은 무엇입니까? np.power에 싸여 때 작동하지 않습니다 아마도 때문에

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

:

img32[img32 < 0.04045] = img32/12.92 

두 번째의 첫 번째 단계에서 작동하지만 실패 : 내가 좋아하는 뭔가를 시도

기능

도움을 주시면 감사하겠습니다.

+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) 

수 -

그래서 우리는 그렇게 같은 구현을 할 것이다

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

샘플 케이스 - -

,369,136 선택적으로 만들고과 같이, 이들 두 조건에 대응하여 설정 elems3210
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