Beispiel #1
0
    def test_n_dimensional_delta_E_CIE1976(self):
        """
        Tests :func:`colour.difference.delta_e.delta_E_CIE1976` definition
        n-dimensional arrays support.
        """

        Lab1 = np.array([100.00000000, 21.57210357, 272.22819350])
        Lab2 = np.array([100.00000000, 426.67945353, 72.39590835])
        delta_E = 451.71330197359117
        np.testing.assert_almost_equal(
            delta_E_CIE1976(Lab1, Lab2),
            delta_E,
            decimal=7)

        Lab1 = np.tile(Lab1, (6, 1))
        Lab2 = np.tile(Lab2, (6, 1))
        delta_E = np.tile(delta_E, 6)
        np.testing.assert_almost_equal(
            delta_E_CIE1976(Lab1, Lab2),
            delta_E,
            decimal=7)

        Lab1 = np.reshape(Lab1, (2, 3, 3))
        Lab2 = np.reshape(Lab2, (2, 3, 3))
        delta_E = np.reshape(delta_E, (2, 3))
        np.testing.assert_almost_equal(
            delta_E_CIE1976(Lab1, Lab2),
            delta_E,
            decimal=7)
Beispiel #2
0
    def test_n_dimensional_delta_E_CIE1976(self):
        """
        Tests :func:`colour.difference.delta_e.delta_E_CIE1976` definition
        n-dimensional arrays support.
        """

        Lab1 = np.array([100.00000000, 21.57210357, 272.22819350])
        Lab2 = np.array([100.00000000, 426.67945353, 72.39590835])
        delta_E = 451.71330197359117
        np.testing.assert_almost_equal(delta_E_CIE1976(Lab1, Lab2),
                                       delta_E,
                                       decimal=7)

        Lab1 = np.tile(Lab1, (6, 1))
        Lab2 = np.tile(Lab2, (6, 1))
        delta_E = np.tile(delta_E, 6)
        np.testing.assert_almost_equal(delta_E_CIE1976(Lab1, Lab2),
                                       delta_E,
                                       decimal=7)

        Lab1 = np.reshape(Lab1, (2, 3, 3))
        Lab2 = np.reshape(Lab2, (2, 3, 3))
        delta_E = np.reshape(delta_E, (2, 3))
        np.testing.assert_almost_equal(delta_E_CIE1976(Lab1, Lab2),
                                       delta_E,
                                       decimal=7)
Beispiel #3
0
    def test_delta_E_CIE1976(self):
        """
        Tests :func:`colour.difference.delta_e.delta_E_CIE1976` definition.
        """

        self.assertAlmostEqual(
            delta_E_CIE1976(
                np.array([100.00000000, 21.57210357, 272.22819350]),
                np.array([100.00000000, 426.67945353, 72.39590835])),
            451.713301974,
            places=7)

        self.assertAlmostEqual(
            delta_E_CIE1976(
                np.array([100.00000000, 21.57210357, 272.22819350]),
                np.array([100.00000000, 74.05216981, 276.45318193])),
            52.6498611564,
            places=7)

        self.assertAlmostEqual(
            delta_E_CIE1976(
                np.array([100.00000000, 21.57210357, 272.22819350]),
                np.array([100.00000000, 8.32281957, -73.58297716])),
            346.064891718,
            places=7)
Beispiel #4
0
    def test_nan_delta_E_CIE1976(self):
        """
        Tests :func:`colour.difference.delta_e.delta_E_CIE1976` definition nan
        support.
        """

        cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]
        cases = set(permutations(cases * 3, r=3))
        for case in cases:
            Lab1 = np.array(case)
            Lab2 = np.array(case)
            delta_E_CIE1976(Lab1, Lab2)
Beispiel #5
0
    def test_nan_delta_E_CIE1976(self):
        """
        Tests :func:`colour.difference.delta_e.delta_E_CIE1976` definition nan
        support.
        """

        cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]
        cases = set(permutations(cases * 3, r=3))
        for case in cases:
            Lab1 = np.array(case)
            Lab2 = np.array(case)
            delta_E_CIE1976(Lab1, Lab2)
Beispiel #6
0
    def test_optimise(self):
        """Test :class:`colour.recovery.otsu2018.Tree_Otsu2018.optimise` method."""

        node_tree = Tree_Otsu2018(self._reflectances, self._cmfs, self._sd_D65)
        node_tree.optimise(iterations=5)

        dataset = node_tree.to_dataset()
        dataset.write(self._path)

        dataset = Dataset_Otsu2018()
        dataset.read(self._path)

        for sd in SDS_COLOURCHECKERS["ColorChecker N Ohta"].values():
            XYZ = sd_to_XYZ(sd, self._cmfs, self._sd_D65) / 100
            Lab = XYZ_to_Lab(XYZ, self._xy_D65)

            recovered_sd = XYZ_to_sd_Otsu2018(
                XYZ, self._cmfs, self._sd_D65, dataset, False
            )
            recovered_XYZ = (
                sd_to_XYZ(recovered_sd, self._cmfs, self._sd_D65) / 100
            )
            recovered_Lab = XYZ_to_Lab(recovered_XYZ, self._xy_D65)

            error = metric_mse(
                reshape_sd(sd, SPECTRAL_SHAPE_OTSU2018).values,
                recovered_sd.values,
            )
            self.assertLess(error, 0.075)

            delta_E = delta_E_CIE1976(Lab, recovered_Lab)
            self.assertLess(delta_E, 1e-12)
Beispiel #7
0
    def test_intermediates(self):
        """
        Tests intermediate results of
        :func:`colour.recovery.jakob2019.error_function` with
        :func:`colour.sd_to_XYZ`, :func:`colour.XYZ_to_Lab` and checks if the
        error is computed correctly by comparing it with
        :func:`colour.difference.delta_E_CIE1976`.
        """

        # Quoted names refer to colours from ColorChecker N Ohta (using D65).
        coefficient_list = [
            np.array([0, 0, 0]),  # 50% gray
            np.array([0, 0, -1e+9]),  # Pure black
            np.array([0, 0, +1e+9]),  # Pure white
            np.array([1e+9, -1e+9, 2.1e+8]),  # A pathological example
            np.array([2.2667394, -7.6313081, 1.03185]),  # 'blue'
            np.array([-31.377077, 26.810094, -6.1139927]),  # 'green'
            np.array([25.064246, -16.072039, 0.10431365]),  # 'red'
            np.array([-19.325667, 22.242319, -5.8144924]),  # 'yellow'
            np.array([21.909902, -17.227963, 2.142351]),  # 'magenta'
            np.array([-15.864009, 8.6735071, -1.4012552]),  # 'cyan'
        ]

        for coefficients in coefficient_list:
            error, _derror, R, XYZ, Lab = error_function(coefficients,
                                                         self._Lab_e,
                                                         self._cmfs,
                                                         self._sd_D65,
                                                         additional_data=True)

            sd = sd_Jakob2019(
                dimensionalise_coefficients(coefficients, self._shape),
                self._shape)

            sd_XYZ = sd_to_XYZ(sd, self._cmfs, self._sd_D65) / 100
            sd_Lab = XYZ_to_Lab(XYZ, self._xy_D65)
            error_reference = delta_E_CIE1976(self._Lab_e, Lab)

            np.testing.assert_allclose(sd.values, R, atol=1e-14)
            np.testing.assert_allclose(XYZ, sd_XYZ, atol=1e-14)

            self.assertLess(abs(error_reference - error), JND_CIE1976 / 100)
            self.assertLess(delta_E_CIE1976(Lab, sd_Lab), JND_CIE1976 / 100)
Beispiel #8
0
    def test_delta_E_CIE1976(self):
        """
        Tests :func:`colour.difference.delta_e.delta_E_CIE1976` definition.
        """

        self.assertAlmostEqual(delta_E_CIE1976(
            np.array([100.00000000, 21.57210357, 272.22819350]),
            np.array([100.00000000, 426.67945353, 72.39590835])),
                               451.713301974,
                               places=7)

        self.assertAlmostEqual(delta_E_CIE1976(
            np.array([100.00000000, 21.57210357, 272.22819350]),
            np.array([100.00000000, 74.05216981, 276.45318193])),
                               52.6498611564,
                               places=7)

        self.assertAlmostEqual(delta_E_CIE1976(
            np.array([100.00000000, 21.57210357, 272.22819350]),
            np.array([100.00000000, 8.32281957, -73.58297716])),
                               346.064891718,
                               places=7)
Beispiel #9
0
    def test_delta_E_CIE1976(self):
        """
        Tests :func:`colour.difference.delta_e.delta_E_CIE1976` definition.
        """

        Lab_1 = np.array([100.00000000, 21.57210357, 272.22819350])
        Lab_2 = np.array([100.00000000, 426.67945353, 72.39590835])
        Lab_1 = np.tile(Lab_1, (6, 1)).reshape((2, 3, 3))
        Lab_2 = np.tile(Lab_2, (6, 1)).reshape((2, 3, 3))

        np.testing.assert_almost_equal(delta_E_CIE1976(Lab_1, Lab_2),
                                       euclidean_distance(Lab_1, Lab_2),
                                       decimal=7)
Beispiel #10
0
    def test_delta_E_CIE1976(self):
        """
        Tests :func:`colour.difference.delta_e.delta_E_CIE1976` definition.
        """

        Lab_1 = np.array([100.00000000, 21.57210357, 272.22819350])
        Lab_2 = np.array([100.00000000, 426.67945353, 72.39590835])
        Lab_1 = np.tile(Lab_1, (6, 1)).reshape([2, 3, 3])
        Lab_2 = np.tile(Lab_2, (6, 1)).reshape([2, 3, 3])

        np.testing.assert_almost_equal(
            delta_E_CIE1976(Lab_1, Lab_2),
            euclidean_distance(Lab_1, Lab_2),
            decimal=7)
Beispiel #11
0
    def test_domain_range_scale_delta_E_CIE1976(self):
        """
        Tests :func:`colour.difference.delta_e.delta_E_CIE1976` definition
        domain and range scale support.
        """

        Lab_1 = np.array([100.00000000, 21.57210357, 272.22819350])
        Lab_2 = np.array([100.00000000, 426.67945353, 72.39590835])

        d_r = (('reference', 1), (1, 0.01), (100, 1))
        for scale, factor in d_r:
            with domain_range_scale(scale):
                np.testing.assert_almost_equal(
                    delta_E_CIE1976(Lab_1 * factor, Lab_2 * factor),
                    euclidean_distance(Lab_1, Lab_2),
                    decimal=7)
Beispiel #12
0
    def test_domain_range_scale_delta_E_CIE1976(self):
        """
        Tests :func:`colour.difference.delta_e.delta_E_CIE1976` definition
        domain and range scale support.
        """

        Lab_1 = np.array([100.00000000, 21.57210357, 272.22819350])
        Lab_2 = np.array([100.00000000, 426.67945353, 72.39590835])

        d_r = (('reference', 1), (1, 0.01), (100, 1))
        for scale, factor in d_r:
            with domain_range_scale(scale):
                np.testing.assert_almost_equal(
                    delta_E_CIE1976(Lab_1 * factor, Lab_2 * factor),
                    euclidean_distance(Lab_1, Lab_2),
                    decimal=7)
    def check_basis_functions(self):
        """
        Test :func:`colour.recovery.RGB_to_sd_Mallett2019` definition or the
        more specialised :func:`colour.recovery.RGB_to_sd_Mallett2019`
        definition.
        """

        # Make sure the white point is reconstructed as a perfectly flat
        # spectrum.
        RGB = np.full(3, 1.0)
        sd = RGB_to_sd_Mallett2019(RGB, self._basis)
        self.assertLess(np.var(sd.values), 1e-5)

        # Check if the primaries or their combination exceeds the [0, 1] range.
        lower = np.zeros_like(sd.values) - 1e-12
        upper = np.ones_like(sd.values) + 1e12
        for RGB in [[1, 1, 1], [1, 0, 0], [0, 1, 0], [0, 0, 1]]:
            sd = RGB_to_sd_Mallett2019(RGB, self._basis)
            np.testing.assert_array_less(sd.values, upper)
            np.testing.assert_array_less(lower, sd.values)

        # Check Delta E's using a colour checker.
        for name, sd in SDS_COLOURCHECKERS["ColorChecker N Ohta"].items():
            XYZ = sd_to_XYZ(sd, self._cmfs, self._sd_D65) / 100
            Lab = XYZ_to_Lab(XYZ, self._xy_D65)
            RGB = XYZ_to_RGB(
                XYZ,
                self._RGB_colourspace.whitepoint,
                self._xy_D65,
                self._RGB_colourspace.matrix_XYZ_to_RGB,
            )

            recovered_sd = RGB_to_sd_Mallett2019(RGB, self._basis)
            recovered_XYZ = (
                sd_to_XYZ(recovered_sd, self._cmfs, self._sd_D65) / 100
            )
            recovered_Lab = XYZ_to_Lab(recovered_XYZ, self._xy_D65)

            error = delta_E_CIE1976(Lab, recovered_Lab)

            if error > 4 * JND_CIE1976 / 100:  # pragma: no cover
                self.fail(f'Delta E for "{name}" is {error}!')
Beispiel #14
0
    def test_NodeTree_Otsu2018_and_Dataset_Otsu2018(self):
        """
        Tests :class:`colour.recovery.otsu2018.NodeTree_Otsu2018` dataset
        generation and :class:`colour.recovery.otsu2018.Dataset_Otsu2018`
        input and output. The generated dataset is also tested for
        reconstruction errors.
        """

        reflectances = []
        for colourchecker in ['ColorChecker N Ohta', 'BabelColor Average']:
            for sd in SDS_COLOURCHECKERS[colourchecker].values():
                reflectances.append(sd.copy().align(self._shape).values)

        node_tree = NodeTree_Otsu2018(reflectances, self._cmfs, self._sd_D65)
        node_tree.optimise(iterations=2)

        path = os.path.join(self._temporary_directory, 'Test_Otsu2018.npz')
        dataset = node_tree.to_dataset()
        dataset.write(path)

        dataset = Dataset_Otsu2018()
        dataset.read(path)

        for sd in SDS_COLOURCHECKERS['ColorChecker N Ohta'].values():
            XYZ = sd_to_XYZ(sd, self._cmfs, self._sd_D65) / 100
            Lab = XYZ_to_Lab(XYZ, self._xy_D65)

            recovered_sd = XYZ_to_sd_Otsu2018(XYZ, self._cmfs, self._sd_D65,
                                              dataset, False)
            recovered_XYZ = sd_to_XYZ(recovered_sd, self._cmfs,
                                      self._sd_D65) / 100
            recovered_Lab = XYZ_to_Lab(recovered_XYZ, self._xy_D65)

            error = metric_mse(sd.copy().align(SPECTRAL_SHAPE_OTSU2018).values,
                               recovered_sd.values)
            self.assertLess(error, 0.075)

            delta_E = delta_E_CIE1976(Lab, recovered_Lab)
            self.assertLess(delta_E, 1e-12)
Beispiel #15
0
    def test_LUT3D_Jakob2019(self):
        """
        Tests the entirety of the
        :class:`colour.recovery.jakob2019.LUT3D_Jakob2019`class.
        """

        LUT = LUT3D_Jakob2019()
        LUT.generate(self._RGB_colourspace, self._cmfs, self._sd_D65, 5)

        path = os.path.join(self._temporary_directory, 'Test_Jakob2019.coeff')

        LUT.write(path)
        LUT.read(path)

        for RGB in [
                np.array([1, 0, 0]),
                np.array([0, 1, 0]),
                np.array([0, 0, 1]),
                zeros(3),
                full(3, 0.5),
                ones(3),
        ]:
            XYZ = RGB_to_XYZ(RGB, self._RGB_colourspace.whitepoint,
                             self._xy_D65,
                             self._RGB_colourspace.matrix_RGB_to_XYZ)
            Lab = XYZ_to_Lab(XYZ, self._xy_D65)

            recovered_sd = LUT.RGB_to_sd(RGB)
            recovered_XYZ = sd_to_XYZ(recovered_sd, self._cmfs,
                                      self._sd_D65) / 100
            recovered_Lab = XYZ_to_Lab(recovered_XYZ, self._xy_D65)

            error = delta_E_CIE1976(Lab, recovered_Lab)

            if error > 2 * JND_CIE1976 / 100:
                self.fail(
                    'Delta E for RGB={0} in colourspace {1} is {2}!'.format(
                        RGB, self._RGB_colourspace.name, error))
Beispiel #16
0
    def test_XYZ_to_sd_Otsu2018(self):
        """Test :func:`colour.recovery.otsu2018.XYZ_to_sd_Otsu2018` definition."""

        # Tests the round-trip with values of a colour checker.
        for _name, sd in SDS_COLOURCHECKERS["ColorChecker N Ohta"].items():
            XYZ = sd_to_XYZ(sd, self._cmfs, self._sd_D65) / 100
            Lab = XYZ_to_Lab(XYZ, self._xy_D65)

            recovered_sd = XYZ_to_sd_Otsu2018(
                XYZ, self._cmfs, self._sd_D65, clip=False
            )
            recovered_XYZ = (
                sd_to_XYZ(recovered_sd, self._cmfs, self._sd_D65) / 100
            )
            recovered_Lab = XYZ_to_Lab(recovered_XYZ, self._xy_D65)

            error = metric_mse(
                reshape_sd(sd, SPECTRAL_SHAPE_OTSU2018).values,
                recovered_sd.values,
            )
            self.assertLess(error, 0.02)

            delta_E = delta_E_CIE1976(Lab, recovered_Lab)
            self.assertLess(delta_E, 1e-12)
Beispiel #17
0
    x = []
    y = []
    errors = []
    above_JND = 0
    for i, sd in tqdm.tqdm(enumerate(sds), total=len(sds)):
        XYZ = sd_to_XYZ(sd, illuminant=D65) / 100
        xy = XYZ_to_xy(XYZ)
        x.append(xy[0])
        y.append(xy[1])
        Lab = XYZ_to_Lab(XYZ, xy_w)

        recovered_sd = XYZ_to_sd_Otsu2018(XYZ)
        recovered_XYZ = sd_to_XYZ(recovered_sd, illuminant=D65) / 100
        recovered_Lab = XYZ_to_Lab(recovered_XYZ, xy_w)

        error = delta_E_CIE1976(Lab, recovered_Lab)
        errors.append(error)
        if error > 2.4:
            above_JND += 1

    print('Min. error: %g' % min(errors))
    print('Max. error: %g' % max(errors))
    print('Avg. error: %g' % np.mean(errors))
    print('Errors above JND: %d (%.1f%%)' %
          (above_JND, 100 * above_JND / len(sds)))

    bins = [int((max(y) - min(y)) / 0.01), int((max(x) - min(x)) / 0.01)]
    histogram, _, _ = np.histogram2d(x, y, bins=bins, weights=errors)

    plot_chromaticity_diagram_CIE1931(standalone=False)
    plt.imshow(histogram,