From 1657a4d1b83bd61af4093357c224da07f8f5549f Mon Sep 17 00:00:00 2001 From: Ralf Gommers Date: Mon, 19 Oct 2009 14:34:00 +0200 Subject: [PATCH] Implement hsv2rgb. --- scikits/image/color/colorconv.py | 60 ++++++++++++++++++++- scikits/image/color/tests/test_colorconv.py | 24 +++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) diff --git a/scikits/image/color/colorconv.py b/scikits/image/color/colorconv.py index c12791cf..9130738a 100644 --- a/scikits/image/color/colorconv.py +++ b/scikits/image/color/colorconv.py @@ -8,7 +8,7 @@ from __future__ import division -__all__ = ["rgb2hsv"] +__all__ = ['rgb2hsv', 'hsv2rgb'] __docformat__ = "restructuredtext en" import numpy as np @@ -83,3 +83,61 @@ def rgb2hsv(rgb): return out + +def hsv2rgb(hsv): + """HSV to RGB color space conversion. + + Parameters + ---------- + hsv : ndarray + The image in HSV format, in a 3-D array of shape (.., .., 3). + + Returns + ------- + out : ndarray + The image in RGB format, in a 3-D array of shape (.., .., 3). + + Raises + ------ + ValueError + If `hsv` is not a 3-D array of shape (.., .., 3). + + Examples + -------- + >>> import os + >>> from scikits.image import data_dir + >>> from scikits.image.io import imread + + >>> lena = imread(os.path.join(data_dir, 'lena.png')) + >>> lena_hsv = rgb2hsv(lena) + >>> lena_rgb = hsv2rgb(lena_hsv) + """ + + if type(hsv) != np.ndarray: + raise TypeError, "the input array 'hsv' must be a numpy.ndarray" + + if hsv.ndim != 3 or hsv.shape[2] != 3: + msg = "the input array 'hsv' must be have a shape == (.,.,3))" + raise ValueError, msg + + arr = hsv.astype("float32") + + hi = np.floor(arr[:,:,0] * 6) + f = arr[:,:,0] * 6 - hi + p = arr[:,:,2] * (1 - arr[:,:,1]) + q = arr[:,:,2] * (1 - f * arr[:,:,1]) + t = arr[:,:,2] * (1 - (1 - f) * arr[:,:,1]) + v = arr[:,:,2] + + hi = np.dstack([hi, hi, hi]).astype("uint8") % 6 + out = np.choose(hi, [np.dstack((v, t, p)), + np.dstack((q, v, p)), + np.dstack((p, v, t)), + np.dstack((p, q, v)), + np.dstack((t, p, v)), + np.dstack((v, p, q))]) + + # remove NaN + out[np.isnan(out)] = 0 + + return out diff --git a/scikits/image/color/tests/test_colorconv.py b/scikits/image/color/tests/test_colorconv.py index 3dbc027d..f40dcec5 100644 --- a/scikits/image/color/tests/test_colorconv.py +++ b/scikits/image/color/tests/test_colorconv.py @@ -14,17 +14,20 @@ from numpy.testing import * from scikits.image.io import imread from scikits.image.color import ( rgb2hsv, + hsv2rgb, ) from scikits.image import data_dir import colorsys + class TestColorconv(TestCase): img_rgb = imread(os.path.join(data_dir, 'color.png')) img_grayscale = imread(os.path.join(data_dir, 'camera.png')) + # RGB to HSV def test_rgb2hsv_conversion(self): rgb = self.img_rgb.astype("float32")[::16, ::16] hsv = rgb2hsv(rgb).reshape(-1, 3) @@ -43,6 +46,27 @@ class TestColorconv(TestCase): def test_rgb2hsv_error_list(self): self.assertRaises(TypeError, rgb2hsv, [self.img_rgb[0,0]]) + + # HSV to RGB + def test_hsv2rgb_conversion(self): + rgb = self.img_rgb.astype("float32")[::16, ::16] + # create HSV image with colorsys + hsv = np.array([colorsys.rgb_to_hsv(pt[0], pt[1], pt[2]) + for pt in rgb.reshape(-1, 3)]).reshape(rgb.shape) + # convert back to RGB and compare with original. + # float32 -> relative precision about 1e-6 + assert_almost_equal(rgb, hsv2rgb(hsv), decimal=4) + + def test_hsv2rgb_error_grayscale(self): + self.assertRaises(ValueError, hsv2rgb, self.img_grayscale) + + def test_hsv2rgb_error_one_element(self): + self.assertRaises(ValueError, hsv2rgb, self.img_rgb[0,0]) + + def test_hsv2rgb_error_list(self): + self.assertRaises(TypeError, hsv2rgb, [self.img_rgb[0,0]]) + + if __name__ == "__main__": run_module_suite()