From 63115957136c4c9164fe47908572cb83ae08da44 Mon Sep 17 00:00:00 2001 From: Wacton Date: Fri, 10 Nov 2023 18:19:19 +0000 Subject: [PATCH] Add Macbeth ColorChecker dataset --- Unicolour.Datasets/Macbeth.cs | 50 +++++++++++++++++++++++++ Unicolour.Tests/DatasetMacbethTests.cs | 51 ++++++++++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 Unicolour.Datasets/Macbeth.cs create mode 100644 Unicolour.Tests/DatasetMacbethTests.cs diff --git a/Unicolour.Datasets/Macbeth.cs b/Unicolour.Datasets/Macbeth.cs new file mode 100644 index 00000000..95086ea1 --- /dev/null +++ b/Unicolour.Datasets/Macbeth.cs @@ -0,0 +1,50 @@ +namespace Wacton.Unicolour.Datasets; + +public static class Macbeth +{ + /* + * table at https://xritephoto.com/documents/literature/en/ColorData-1p_EN.pdf references LAB using D50 + * but their LAB values appear to be a bit off, unclear why (perhaps an unusual chromatic adaptation method?) + * ---------- + * there is also https://poynton.ca/notes/color/GretagMacbeth-ColorChecker.html containing apparent Illuminant C xyY data + * which is even further removed from the manufacturer's sRGB values + */ + private static readonly XyzConfiguration XyzConfig = new(WhitePoint.From(Illuminant.D50)); + private static readonly Configuration Config = new(RgbConfiguration.StandardRgb, XyzConfig); + + public static readonly Unicolour DarkSkin = new(ColourSpace.Rgb255, Config, 115, 82, 68); + public static readonly Unicolour LightSkin = new(ColourSpace.Rgb255, Config, 194, 150, 130); + public static readonly Unicolour BlueSky = new(ColourSpace.Rgb255, Config, 98, 122, 157); + public static readonly Unicolour Foliage = new(ColourSpace.Rgb255, Config, 87, 108, 67); + public static readonly Unicolour BlueFlower = new(ColourSpace.Rgb255, Config, 133, 128, 177); + public static readonly Unicolour BluishGreen = new(ColourSpace.Rgb255, Config, 103, 189, 170); + public static readonly Unicolour Orange = new(ColourSpace.Rgb255, Config, 214, 126, 44); + public static readonly Unicolour PurplishBlue = new(ColourSpace.Rgb255, Config, 80, 91, 166); + public static readonly Unicolour ModerateRed = new(ColourSpace.Rgb255, Config, 193, 90, 99); + public static readonly Unicolour Purple = new(ColourSpace.Rgb255, Config, 94, 60, 108); + public static readonly Unicolour YellowGreen = new(ColourSpace.Rgb255, Config, 157, 188, 64); + public static readonly Unicolour OrangeYellow = new(ColourSpace.Rgb255, Config, 224, 163, 46); + public static readonly Unicolour Blue = new(ColourSpace.Rgb255, Config, 56, 61, 150); + public static readonly Unicolour Green = new(ColourSpace.Rgb255, Config, 70, 148, 73); + public static readonly Unicolour Red = new(ColourSpace.Rgb255, Config, 175, 54, 60); + public static readonly Unicolour Yellow = new(ColourSpace.Rgb255, Config, 231, 199, 31); + public static readonly Unicolour Magenta = new(ColourSpace.Rgb255, Config, 187, 86, 149); + public static readonly Unicolour Cyan = new(ColourSpace.Rgb255, Config, 8, 133, 161); + public static readonly Unicolour White = new(ColourSpace.Rgb255, Config, 243, 243, 242); + public static readonly Unicolour Neutral8 = new(ColourSpace.Rgb255, Config, 200, 200, 200); + public static readonly Unicolour Neutral65 = new(ColourSpace.Rgb255, Config, 160, 160, 160); + public static readonly Unicolour Neutral5 = new(ColourSpace.Rgb255, Config, 122, 122, 121); + public static readonly Unicolour Neutral35 = new(ColourSpace.Rgb255, Config, 85, 85, 85); + public static readonly Unicolour Black = new(ColourSpace.Rgb255, Config, 52, 52, 52); + + public static readonly List Natural = new() { DarkSkin, LightSkin, BlueSky, Foliage, BlueFlower, BluishGreen }; + public static readonly List Miscellaneous = new() { Orange, PurplishBlue, ModerateRed, Purple, YellowGreen, OrangeYellow }; + public static readonly List PrimaryAndSecondary = new() { Blue, Green, Red, Yellow, Magenta, Cyan }; + public static readonly List Greyscale = new() { White, Neutral8, Neutral65, Neutral5, Neutral35, Black }; + + public static IEnumerable All => new List() + .Concat(Natural) + .Concat(Miscellaneous) + .Concat(PrimaryAndSecondary) + .Concat(Greyscale); +} \ No newline at end of file diff --git a/Unicolour.Tests/DatasetMacbethTests.cs b/Unicolour.Tests/DatasetMacbethTests.cs new file mode 100644 index 00000000..d717e592 --- /dev/null +++ b/Unicolour.Tests/DatasetMacbethTests.cs @@ -0,0 +1,51 @@ +namespace Wacton.Unicolour.Tests; + +using System.Collections.Generic; +using System.Linq; +using NUnit.Framework; +using Wacton.Unicolour.Datasets; +using Wacton.Unicolour.Tests.Utils; +using static Datasets.Macbeth; + +public class DatasetMacbethTests +{ + private static readonly Configuration ConfigIlluminantC = new(xyzConfiguration: new XyzConfiguration(WhitePoint.From(Illuminant.C))); + + private static readonly List XyyIlluminantC = new() + { + new TestCaseData(DarkSkin, new Xyy(0.400, 0.350, 10.1 / 100.0)).SetName("Dark skin"), + new TestCaseData(LightSkin, new Xyy(0.377, 0.345, 35.8 / 100.0)).SetName("Light skin"), + new TestCaseData(BlueSky, new Xyy(0.247, 0.251, 19.3 / 100.0)).SetName("Blue sky"), + new TestCaseData(Foliage, new Xyy(0.337, 0.422, 13.3 / 100.0)).SetName("Foliage"), + new TestCaseData(BlueFlower, new Xyy(0.265, 0.240, 24.3 / 100.0)).SetName("Blue flower"), + new TestCaseData(BluishGreen, new Xyy(0.261, 0.343, 43.1 / 100.0)).SetName("Bluish green"), + new TestCaseData(Orange, new Xyy(0.506, 0.407, 30.1 / 100.0)).SetName("Orange"), + new TestCaseData(PurplishBlue, new Xyy(0.211, 0.175, 12 / 100.0)).SetName("Purplish blue"), + new TestCaseData(ModerateRed, new Xyy(0.453, 0.306, 19.8 / 100.0)).SetName("Moderate red"), + new TestCaseData(Purple, new Xyy(0.285, 0.202, 6.6 / 100.0)).SetName("Purple"), + new TestCaseData(YellowGreen, new Xyy(0.38, 0.489, 44.3 / 100.0)).SetName("Yellow green"), + new TestCaseData(OrangeYellow, new Xyy(0.473, 0.438, 43.1 / 100.0)).SetName("Orange yellow"), + new TestCaseData(Blue, new Xyy(0.187, 0.129, 6.1 / 100.0)).SetName("Blue"), + new TestCaseData(Green, new Xyy(0.305, 0.478, 23.4 / 100.0)).SetName("Green"), + new TestCaseData(Red, new Xyy(0.539, 0.313, 12 / 100.0)).SetName("Red"), + new TestCaseData(Yellow, new Xyy(0.448, 0.47, 59.1 / 100.0)).SetName("Yellow"), + new TestCaseData(Magenta, new Xyy(0.364, 0.233, 19.8 / 100.0)).SetName("Magenta"), + new TestCaseData(Cyan, new Xyy(0.196, 0.252, 19.8 / 100.0)).SetName("Cyan"), + new TestCaseData(White, new Xyy(0.31, 0.316, 90 / 100.0)).SetName("White"), + new TestCaseData(Neutral8, new Xyy(0.31, 0.316, 59.1 / 100.0)).SetName("Neutral 8"), + new TestCaseData(Neutral65, new Xyy(0.31, 0.316, 36.2 / 100.0)).SetName("Neutral 6.5"), + new TestCaseData(Neutral5, new Xyy(0.31, 0.316, 19.8 / 100.0)).SetName("Neutral 5"), + new TestCaseData(Neutral35, new Xyy(0.31, 0.316, 9 / 100.0)).SetName("Neutral 3.5"), + new TestCaseData(Black, new Xyy(0.31, 0.316, 3.1 / 100.0)).SetName("Black") + }; + + [TestCaseSource(nameof(XyyIlluminantC))] + public void Test(Unicolour unicolour, Xyy expectedXyy) + { + var unicolourIlluminantC = unicolour.ConvertToConfiguration(ConfigIlluminantC); + TestUtils.AssertTriplet(unicolourIlluminantC, expectedXyy.Triplet, 0.02); + } + + [Test] + public void All() => Assert.That(Macbeth.All.Distinct().Count(), Is.EqualTo(24)); +} \ No newline at end of file