From b0aed02ce906dcf9232ba428f829c8a3d4a74a2b Mon Sep 17 00:00:00 2001 From: Norman Barker Date: Mon, 16 Apr 2018 02:40:25 -0500 Subject: [PATCH] added support for YDbDr (#3018) * added support for YDbDr * added ydbdr to colorspace tests --- skimage/color/__init__.py | 4 ++ skimage/color/colorconv.py | 85 +++++++++++++++++++++++++-- skimage/color/tests/test_colorconv.py | 16 ++++- 3 files changed, 98 insertions(+), 7 deletions(-) diff --git a/skimage/color/__init__.py b/skimage/color/__init__.py index 66e8bb32425..6f69b06f288 100644 --- a/skimage/color/__init__.py +++ b/skimage/color/__init__.py @@ -31,6 +31,8 @@ ypbpr2rgb, rgb2ycbcr, ycbcr2rgb, + rgb2ydbdr, + ydbdr2rgb, separate_stains, combine_stains, rgb_from_hed, @@ -93,6 +95,8 @@ 'ypbpr2rgb', 'rgb2ycbcr', 'ycbcr2rgb', + 'rgb2ydbdr', + 'ydbdr2rgb', 'separate_stains', 'combine_stains', 'rgb_from_hed', diff --git a/skimage/color/colorconv.py b/skimage/color/colorconv.py index 00b0995305c..52bdf634588 100644 --- a/skimage/color/colorconv.py +++ b/skimage/color/colorconv.py @@ -98,9 +98,11 @@ def convert_colorspace(arr, fromspace, tospace): ---------- arr : array_like The image to convert. - fromspace : {'RGB', 'HSV', 'RGB CIE', 'XYZ', 'YUV', 'YIQ', 'YPbPr', 'YCbCr'} + fromspace : {'RGB', 'HSV', 'RGB CIE', 'XYZ', 'YUV', + 'YIQ', 'YPbPr', 'YCbCr', 'YDbDr'} The color space to convert from. Can be specified in lower case. - tospace : {'RGB', 'HSV', 'RGB CIE', 'XYZ', 'YUV', 'YIQ', 'YPbPr', 'YCbCr'} + tospace : {'RGB', 'HSV', 'RGB CIE', 'XYZ', 'YUV', + 'YIQ', 'YPbPr', 'YCbCr', 'YDbDr'} The color space to convert to. Can be specified in lower case. Returns @@ -122,10 +124,10 @@ def convert_colorspace(arr, fromspace, tospace): """ fromdict = {'rgb': lambda im: im, 'hsv': hsv2rgb, 'rgb cie': rgbcie2rgb, 'xyz': xyz2rgb, 'yuv': yuv2rgb, 'yiq': yiq2rgb, - 'ypbpr': ypbpr2rgb, 'ycbcr': ycbcr2rgb} + 'ypbpr': ypbpr2rgb, 'ycbcr': ycbcr2rgb, 'ydbdr': ydbdr2rgb} todict = {'rgb': lambda im: im, 'hsv': rgb2hsv, 'rgb cie': rgb2rgbcie, 'xyz': rgb2xyz, 'yuv': rgb2yuv, 'yiq': rgb2yiq, - 'ypbpr': rgb2ypbpr, 'ycbcr': rgb2ycbcr} + 'ypbpr': rgb2ypbpr, 'ycbcr': rgb2ycbcr, 'ydbdr': rgb2ydbdr} fromspace = fromspace.lower() tospace = tospace.lower() @@ -405,6 +407,13 @@ def hsv2rgb(hsv): rgb_from_ycbcr = linalg.inv(ycbcr_from_rgb) +ydbdr_from_rgb = np.array([[ 0.299, 0.587, 0.114], + [ -0.45 , -0.883, 1.333], + [ -1.333, 1.116, 0.217]]) + +rgb_from_ydbdr = linalg.inv(ydbdr_from_rgb) + + # CIE LAB constants for Observer=2A, Illuminant=D65 # NOTE: this is actually the XYZ values for the illuminant above. lab_ref_white = np.array([0.95047, 1., 1.08883]) @@ -1692,6 +1701,40 @@ def rgb2ycbcr(rgb): return arr +def rgb2ydbdr(rgb): + """RGB to YDbDr color space conversion. + + Parameters + ---------- + rgb : array_like + The image in RGB format, in a 3- or 4-D array of shape + ``(M, N, [P,] 3)``. + + Returns + ------- + out : ndarray + The image in YDbDr format, in a 3- or 4-D array of shape + ``(M, N, [P,] 3)``. + + Raises + ------ + ValueError + If `rgb` is not a 3- or 4-D array of shape ``(M, N, [P,] 3)``. + + Notes + ----- + This is the color space which is commonly used + by video codecs, it is also the reversible color transform in JPEG2000. + + References + ---------- + .. [1] https://en.wikipedia.org/wiki/YDbDr + + """ + arr = _convert(ydbdr_from_rgb, rgb) + return arr + + def yuv2rgb(yuv): """YUV to RGB color space conversion. @@ -1806,3 +1849,37 @@ def ycbcr2rgb(ycbcr): arr[..., 1] -= 128 arr[..., 2] -= 128 return _convert(rgb_from_ycbcr, arr) + + +def ydbdr2rgb(ydbdr): + """YDbDr to RGB color space conversion. + + Parameters + ---------- + ydbdr : array_like + The image in YDbDr format, in a 3- or 4-D array of shape + ``(M, N, [P,] 3)``. + + Returns + ------- + out : ndarray + The image in RGB format, in a 3- or 4-D array of shape + ``(M, N, [P,] 3)``. + + Raises + ------ + ValueError + If `ydbdr` is not a 3- or 4-D array of shape ``(M, N, [P,] 3)``. + + Notes + ----- + This is the color space which is commonly used + by video codecs, it is also the reversible color transform in JPEG2000. + + References + ---------- + .. [1] https://en.wikipedia.org/wiki/YDbDr + + """ + arr = ydbdr.copy() + return _convert(rgb_from_ydbdr, arr) diff --git a/skimage/color/tests/test_colorconv.py b/skimage/color/tests/test_colorconv.py index 7c4ebaa9c82..23d43dc6a99 100644 --- a/skimage/color/tests/test_colorconv.py +++ b/skimage/color/tests/test_colorconv.py @@ -38,6 +38,7 @@ rgb2yiq, yiq2rgb, rgb2ypbpr, ypbpr2rgb, rgb2ycbcr, ycbcr2rgb, + rgb2ydbdr, ydbdr2rgb, rgba2rgb, guess_spatial_dimensions) @@ -221,9 +222,15 @@ def test_rgbcie2rgb_conversion(self): self.colbars_array) def test_convert_colorspace(self): - colspaces = ['HSV', 'RGB CIE', 'XYZ', 'YCbCr', 'YPbPr'] - colfuncs_from = [hsv2rgb, rgbcie2rgb, xyz2rgb, ycbcr2rgb, ypbpr2rgb] - colfuncs_to = [rgb2hsv, rgb2rgbcie, rgb2xyz, rgb2ycbcr, rgb2ypbpr] + colspaces = ['HSV', 'RGB CIE', 'XYZ', 'YCbCr', 'YPbPr', 'YDbDr'] + colfuncs_from = [ + hsv2rgb, rgbcie2rgb, xyz2rgb, + ycbcr2rgb, ypbpr2rgb, ydbdr2rgb + ] + colfuncs_to = [ + rgb2hsv, rgb2rgbcie, rgb2xyz, + rgb2ycbcr, rgb2ypbpr, rgb2ydbdr + ] assert_almost_equal( convert_colorspace(self.colbars_array, 'RGB', 'RGB'), @@ -467,11 +474,13 @@ def test_yuv(self): assert_array_almost_equal(rgb2yiq(rgb), np.array([[[1, 0, 0]]])) assert_array_almost_equal(rgb2ypbpr(rgb), np.array([[[1, 0, 0]]])) assert_array_almost_equal(rgb2ycbcr(rgb), np.array([[[235, 128, 128]]])) + assert_array_almost_equal(rgb2ydbdr(rgb), np.array([[[1, 0, 0]]])) rgb = np.array([[[0.0, 1.0, 0.0]]]) assert_array_almost_equal(rgb2yuv(rgb), np.array([[[0.587, -0.28886916, -0.51496512]]])) assert_array_almost_equal(rgb2yiq(rgb), np.array([[[0.587, -0.27455667, -0.52273617]]])) assert_array_almost_equal(rgb2ypbpr(rgb), np.array([[[0.587, -0.331264, -0.418688]]])) assert_array_almost_equal(rgb2ycbcr(rgb), np.array([[[144.553, 53.797, 34.214]]])) + assert_array_almost_equal(rgb2ydbdr(rgb), np.array([[[0.587, -0.883, 1.116]]])) def test_yuv_roundtrip(self): img_rgb = img_as_float(self.img_rgb)[::16, ::16] @@ -479,6 +488,7 @@ def test_yuv_roundtrip(self): assert_array_almost_equal(yiq2rgb(rgb2yiq(img_rgb)), img_rgb) assert_array_almost_equal(ypbpr2rgb(rgb2ypbpr(img_rgb)), img_rgb) assert_array_almost_equal(ycbcr2rgb(rgb2ycbcr(img_rgb)), img_rgb) + assert_array_almost_equal(ydbdr2rgb(rgb2ydbdr(img_rgb)), img_rgb) def test_rgb2yiq_conversion(self): rgb = img_as_float(self.img_rgb)[::16, ::16]