I have an RGB image loaded into a numpy array via PIL. I get a rows x cols x 3 array. After tinkering, I arrived at the following code. I'd like to learn how to do such an array/matrix manipulation without the loop.
# Note using matrix not array.
rgb_to_ycc = np.matrix(
(0.2990, 0.5870, 0.1140,
-0.1687, -0.3313, 0.5000,
0.5000, -0.4187, -0.0813,)
).reshape( 3,3 )
ycc_to_rgb = np.matrix(
( 1.0, 0.0, 1.4022,
1.0, -0.3456, -0.7145,
1.0, 1.7710, 0, )
).reshape( 3, 3 )
def convert_ycc_to_rgb( ycc ) :
# convert back to RGB
rgb = np.zeros_like( ycc )
for row in range(ycc.shape[0]) :
rgb[row] = ycc[row] * ycc_to_rgb.T
return rgb
def convert_rgb_to_ycc( rgb ) :
ycc = np.zeros_like( rgb )
for row in range(rgb.shape[0]):
ycc[row] = rgb[row] * rgb_to_ycc.T
return ycc
I could use http://pypi.python.org/pypi/colormath (via Using Python to convert color formats?) but I'm using this as an exercise to learn numpy.
The aforementioned Colormath library uses a dot product.
# Perform the adaptation via matrix multiplication.
result_matrix = numpy.dot(var_matrix, rgb_matrix)
My math isn't where it should be. Is np.dot() my best bet?
EDIT. After deeper reading colormath's apply_RGB_matrix()-color_conversions.py, I found the np.dot() works if my conversion 3x3s are not matrices. Weird.
def convert_rgb_to_ycc( rgb ) :
return np.dot( rgb, np.asarray( rgb_to_ycc ).T )
I'm not sure about the formula you are using to convert RGB to YCC, so I don't want to claim this is the complete calculation, but to simplify the function you posted, yes, use np.dot with numpy arrays instead of numpy matrices.
np.dot is more general than * with numpy matrices. When using * with numpy matrices, the two matrices have to be 2 dimensional.
But np.dot can produce a result with arrays of different shape. This is important for your application since rgb is 3-dimensional (e.g. when it has shape (1470, 2105, 3)).
The docs for np.dot say:
For N dimensions it is a sum product over the last axis of `a` and
the second-to-last of `b`::
dot(a, b)[i,j,k,m] = sum(a[i,j,:] * b[k,:,m])
This is a generalization of regular matrix multiplication.
I suggest calling your ultimate function rgb_to_ycc, instead of giving that designation to the constant matrix. (It's shorter and says exactly what you want the function to do.)
So below, rgb_to_ycc is my suggested function, and I made some minor modifications to make convert_rgb_to_ycc not raise exceptions and do the computation I think you are intending.
The final line, np.allclose(...) shows the two functions return the same result.
import numpy as np
def rgb_to_ycc(rgb):
M = np.array(
(0.2990, 0.5870, 0.1140,
-0.1687, -0.3313, 0.5000,
0.5000, -0.4187, -0.0813,)
).reshape( 3,3 )
return np.dot(rgb, M.T)
def convert_rgb_to_ycc( rgb ) :
M = np.matrix(
(0.2990, 0.5870, 0.1140,
-0.1687, -0.3313, 0.5000,
0.5000, -0.4187, -0.0813,)
).reshape( 3,3 )
shape=rgb.shape
rgb=rgb.reshape((-1,3))
ycc = np.zeros_like( rgb )
for i in range(len(rgb)):
ycc[i] = rgb[i] * M.T
return ycc.reshape(shape)
rgb=np.random.random((100,100,3))
assert np.allclose(rgb_to_ycc(rgb),convert_rgb_to_ycc(rgb))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With