Merge pull request #378 from sergeyk/master

Fixed RGB<->XYZ conversion (was incorrect before).
This commit is contained in:
Tony S Yu
2012-12-18 07:57:06 -08:00
3 changed files with 44 additions and 11 deletions
+16 -5
View File
@@ -79,7 +79,6 @@ def is_gray(image):
return image.ndim == 2
def convert_colorspace(arr, fromspace, tospace):
"""Convert an image array to a new color space.
@@ -288,8 +287,8 @@ sb_primaries = np.array([1. / 155, 1. / 190, 1. / 225]) * 1e5
# From sRGB specification
xyz_from_rgb = np.array([[0.412453, 0.357580, 0.180423],
[0.212671, 0.715160, 0.072169],
[0.019334, 0.119193, 0.950227]])
[0.212671, 0.715160, 0.072169],
[0.019334, 0.119193, 0.950227]])
rgb_from_xyz = linalg.inv(xyz_from_rgb)
@@ -379,7 +378,13 @@ def xyz2rgb(xyz):
>>> lena_xyz = rgb2xyz(lena)
>>> lena_rgb = xyz2rgb(lena_xyz)
"""
return _convert(rgb_from_xyz, xyz)
# Follow the algorithm from http://www.easyrgb.com/index.php
# except we don't multiply/divide by 100 in the conversion
arr = _convert(rgb_from_xyz, xyz)
mask = arr > 0.0031308
arr[mask] = 1.055 * np.power(arr[mask], 1 / 2.4) - 0.055
arr[~mask] *= 12.92
return arr
def rgb2xyz(rgb):
@@ -415,7 +420,13 @@ def rgb2xyz(rgb):
>>> lena = data.lena()
>>> lena_xyz = rgb2xyz(lena)
"""
return _convert(xyz_from_rgb, rgb)
# Follow the algorithm from http://www.easyrgb.com/index.php
# except we don't multiply/divide by 100 in the conversion
arr = _prepare_colorarray(rgb).copy()
mask = arr > 0.04045
arr[mask] = np.power((arr[mask] + 0.055) / 1.055, 2.4)
arr[~mask] /= 12.92
return _convert(xyz_from_rgb, arr)
def rgb2rgbcie(rgb):
+24 -2
View File
@@ -113,10 +113,14 @@ class TestColorconv(TestCase):
# XYZ to RGB
def test_xyz2rgb_conversion(self):
# only roundtrip test, we checked rgb2xyz above already
assert_almost_equal(xyz2rgb(rgb2xyz(self.colbars_array)),
self.colbars_array)
# RGB<->XYZ roundtrip on another image
def test_xyz_rgb_roundtrip(self):
img_rgb = img_as_float(self.img_rgb)
assert_array_almost_equal(xyz2rgb(rgb2xyz(img_rgb)), img_rgb)
# RGB to RGB CIE
def test_rgb2rgbcie_conversion(self):
gt = np.array([[[ 0.1488856 , 0.18288098, 0.19277574],
@@ -175,11 +179,29 @@ class TestColorconv(TestCase):
assert_array_almost_equal(lab2xyz(self.lab_array),
self.xyz_array, decimal=3)
def test_rgb2lab_brucelindbloom(self):
"""
Test the RGB->Lab conversion by comparing to the calculator on the
authoritative Bruce Lindbloom
[website](http://brucelindbloom.com/index.html?ColorCalculator.html).
"""
# Obtained with D65 white point, sRGB model and gamma
gt_for_colbars = np.array([
[100,0,0],
[97.1393, -21.5537, 94.4780],
[91.1132, -48.0875, -14.1312],
[87.7347, -86.1827, 83.1793],
[60.3242, 98.2343, -60.8249],
[53.2408, 80.0925, 67.2032],
[32.2970, 79.1875, -107.8602],
[0,0,0]]).T
gt_array = np.swapaxes(gt_for_colbars.reshape(3, 4, 2), 0, 2)
assert_array_almost_equal(rgb2lab(self.colbars_array), gt_array, decimal=2)
def test_lab_rgb_roundtrip(self):
img_rgb = img_as_float(self.img_rgb)
assert_array_almost_equal(lab2rgb(rgb2lab(img_rgb)), img_rgb)
def test_gray2rgb():
x = np.array([0, 0.5, 1])
assert_raises(ValueError, gray2rgb, x)
@@ -34,10 +34,10 @@ def test_color():
seg = quickshift(img, random_seed=0, max_dist=30, kernel_size=10, sigma=0)
# we expect 4 segments:
assert_equal(len(np.unique(seg)), 4)
assert_array_equal(seg[:10, :10], 0)
assert_array_equal(seg[10:, :10], 3)
assert_array_equal(seg[:10, 10:], 1)
assert_array_equal(seg[10:, 10:], 2)
assert_array_equal(seg[:10, :10], 1)
assert_array_equal(seg[10:, :10], 2)
assert_array_equal(seg[:10, 10:], 0)
assert_array_equal(seg[10:, 10:], 3)
seg2 = quickshift(img, kernel_size=1, max_dist=2, random_seed=0,
convert2lab=False, sigma=0)