From bfee1a482f1c220a41f8a962bdede4f5cdcb4bb7 Mon Sep 17 00:00:00 2001 From: Thomas Mansencal Date: Mon, 30 Nov 2020 22:17:00 +1300 Subject: [PATCH] Implement support for "Zhao et al. (2009)" dataset. --- BIBLIOGRAPHY.bib | 23 +++ README.rst | 5 +- colour_datasets/loaders/__init__.py | 3 + .../loaders/tests/test_zhao2009.py | 84 ++++++++++ colour_datasets/loaders/zhao2009.py | 157 ++++++++++++++++++ docs/colour_datasets.loaders.rst | 14 ++ docs/index.rst | 5 +- 7 files changed, 287 insertions(+), 4 deletions(-) create mode 100644 colour_datasets/loaders/tests/test_zhao2009.py create mode 100644 colour_datasets/loaders/zhao2009.py diff --git a/BIBLIOGRAPHY.bib b/BIBLIOGRAPHY.bib index 95c7272..7a8754b 100644 --- a/BIBLIOGRAPHY.bib +++ b/BIBLIOGRAPHY.bib @@ -353,3 +353,26 @@ @misc{X-Rite2016 url = {http://xritephoto.com/ph_product_overview.aspx?ID=938\&Action=Support\&SupportID=5884\#}, urldate = {2018-10-29}, } +@article{Zhao2009, + title = {Estimating basis functions for spectral sensitivity + of digital cameras}, + author = {Zhao, Hongxun and Kawakami, Rei and Tan, Robby T and + Ikeuchi, Katsushi}, + year = 2009, + pages = 7, + abstract = {Spectral sensitivity of digital cameras plays an + important role for many computer vision applications. However, + less attention has been drawn on estimating the spectral + sensitivity of commercial cameras, and there is neither + comprehensive analysis of those spectral characteristics. This + paper investigates the characteristics by extracting the basis + functions of them by using SVD (Singular Value Decomposition); we + have collected data from the literature but also by measuring the + sensitivity of different cameras. This paper compares the + extracted basis functions with different mathematical basis + functions and obtains the optimum set of basis functions. The + extracted basis functions can be used to estimate the unknown + spectral sensitivity of an arbitrary camera.}, + keywords = {⛔ No DOI found}, + language = {en}, +} diff --git a/README.rst b/README.rst index 5200bfc..5dbab0b 100644 --- a/README.rst +++ b/README.rst @@ -126,14 +126,13 @@ definition: colour-science-datasets ======================= - Datasets : 18 + Datasets : 19 Synced : 1 URL : https://zenodo.org/communities/colour-science-datasets/ Datasets -------- - [ ] 4050598 : Spectral Upsampling Coefficient Tables - Jakob and Hanika (2019) [ ] 3269926 : Agfa IT8.7/2 Set - Marszalec (n.d.) [ ] 3245883 : Camera Spectral Sensitivity Database - Jiang et al. (2013) [ ] 3367463 : Constant Hue Loci Data - Hung and Berns (1995) @@ -151,6 +150,8 @@ definition: [ ] 3252742 : Observer Function Database - Asano (2015) [ ] 3269922 : Paper Spectra - Haanpalo (n.d.) [ ] 3372171 : RAW to ACES Utility Data - Dyer et al. (2017) + [ ] 4297288 : Spectral Sensitivity Database - Zhao et al. (2009) + [ ] 4050598 : Spectral Upsampling Coefficient Tables - Jakob and Hanika. (2019) A ticked checkbox means that the particular dataset has been synced locally. A dataset is loaded by using its unique number: *3245895*: diff --git a/colour_datasets/loaders/__init__.py b/colour_datasets/loaders/__init__.py index 9e0e6f0..c2d75d8 100644 --- a/colour_datasets/loaders/__init__.py +++ b/colour_datasets/loaders/__init__.py @@ -20,6 +20,7 @@ from .labsphere2019 import DatasetLoader_Labsphere2019, build_Labsphere2019 from .luo1999 import DatasetLoader_Luo1999, build_Luo1999 from .xrite2016 import DatasetLoader_XRite2016, build_XRite2016 +from .zhao2009 import DatasetLoader_Zhao2009, build_Zhao2009 __all__ = ['AbstractDatasetLoader'] __all__ += ['DatasetLoader_Asano2015', 'build_Asano2015'] @@ -32,6 +33,7 @@ __all__ += ['DatasetLoader_Labsphere2019', 'build_Labsphere2019'] __all__ += ['DatasetLoader_Luo1999', 'build_Luo1999'] __all__ += ['DatasetLoader_XRite2016', 'build_XRite2016'] +__all__ += ['DatasetLoader_Zhao2009', 'build_Zhao2009'] DATASET_LOADERS = CaseInsensitiveMapping({ DatasetLoader_Asano2015.ID: build_Asano2015, @@ -44,6 +46,7 @@ DatasetLoader_Labsphere2019.ID: build_Labsphere2019, DatasetLoader_Luo1999.ID: build_Luo1999, DatasetLoader_XRite2016.ID: build_XRite2016, + DatasetLoader_Zhao2009.ID: build_Zhao2009, }) DATASET_LOADERS.__doc__ = """ Dataset loaders ids and callables. diff --git a/colour_datasets/loaders/tests/test_zhao2009.py b/colour_datasets/loaders/tests/test_zhao2009.py new file mode 100644 index 0000000..70665c8 --- /dev/null +++ b/colour_datasets/loaders/tests/test_zhao2009.py @@ -0,0 +1,84 @@ +# -*- coding: utf-8 -*- +""" +Defines unit tests for :mod:`colour_datasets.loaders.zhao2009` module. +""" + +from __future__ import division, unicode_literals + +import unittest + +from colour import SpectralShape + +from colour_datasets.loaders import DatasetLoader_Zhao2009, build_Zhao2009 + +__author__ = 'Colour Developers' +__copyright__ = 'Copyright (C) 2019-2020 - Colour Developers' +__license__ = 'New BSD License - https://opensource.org/licenses/BSD-3-Clause' +__maintainer__ = 'Colour Developers' +__email__ = 'colour-developers@colour-science.org' +__status__ = 'Production' + +__all__ = ['TestDatasetLoader_Zhao2009', 'TestBuildZhao2009'] + + +class TestDatasetLoader_Zhao2009(unittest.TestCase): + """ + Defines :class:`colour_datasets.loaders.zhao2009.DatasetLoader_Zhao2009` + class unit tests methods. + """ + + def test_required_attributes(self): + """ + Tests presence of required attributes. + """ + + required_attributes = ('ID', ) + + for attribute in required_attributes: + self.assertIn(attribute, dir(DatasetLoader_Zhao2009)) + + def test_required_methods(self): + """ + Tests presence of required methods. + """ + + required_methods = ('__init__', 'load') + + for method in required_methods: + self.assertIn(method, dir(DatasetLoader_Zhao2009)) + + def test_load(self): + """ + Tests :func:`colour_datasets.loaders.zhao2009.\ +DatasetLoader_Zhao2009.load` method. + """ + + dataset = DatasetLoader_Zhao2009() + self.assertEqual( + sorted(dataset.load().keys()), + sorted([ + 'SONY DXC 930', 'KODAK DCS 420', 'NIKON D1X', 'SONY DXC 9000', + 'CANON 10D', 'NIKON D70', 'KODAK DCS 460', 'CANON 400D', + 'CANON 5D', 'CANON 5D Mark 2', 'Ladybug2', 'KODAK DCS 200' + ])) + self.assertEqual(dataset.content['SONY DXC 930'].shape, + SpectralShape(400, 700, 4)) + + +class TestBuildZhao2009(unittest.TestCase): + """ + Defines :func:`colour_datasets.loaders.zhao2009.build_Zhao2009` + definition unit tests methods. + """ + + def test_build_Zhao2009(self): + """ + Tests :func:`colour_datasets.loaders.zhao2009.build_Zhao2009` + definition. + """ + + self.assertIs(build_Zhao2009(), build_Zhao2009()) + + +if __name__ == '__main__': + unittest.main() diff --git a/colour_datasets/loaders/zhao2009.py b/colour_datasets/loaders/zhao2009.py new file mode 100644 index 0000000..78b5544 --- /dev/null +++ b/colour_datasets/loaders/zhao2009.py @@ -0,0 +1,157 @@ +# -*- coding: utf-8 -*- +""" +Spectral Sensitivity Database - Zhao et al. (2009) +================================================== + +Defines the objects implementing support for *Zhao, Kawakami, Tan and Ikeuchi +(2009)* *Spectral Sensitivity Database* dataset loading: + +- :class:`colour_datasets.loaders.DatasetLoader_Zhao2009` +- :func:`colour_datasets.loaders.build_Zhao2009` + +References +---------- +- :cite:`Zhao2009` : Zhao, H., Kawakami, R., Tan, R. T., & Ikeuchi, K. + (2009). Estimating basis functions for spectral sensitivity of digital + cameras. 7. +""" + +from __future__ import division, unicode_literals + +import numpy as np +import os +from collections import OrderedDict + +from colour.characterisation import RGB_CameraSensitivities + +from colour_datasets.records import datasets +from colour_datasets.loaders import AbstractDatasetLoader + +__author__ = 'Colour Developers' +__copyright__ = 'Copyright (C) 2019-2020 - Colour Developers' +__license__ = 'New BSD License - https://opensource.org/licenses/BSD-3-Clause' +__maintainer__ = 'Colour Developers' +__email__ = 'colour-developers@colour-science.org' +__status__ = 'Production' + +__all__ = ['DatasetLoader_Zhao2009', 'build_Zhao2009'] + + +class DatasetLoader_Zhao2009(AbstractDatasetLoader): + """ + Defines the *Zhao et al. (2009)* *Spectral Sensitivity Database* + dataset loader. + + Attributes + ---------- + - :attr:`colour_datasets.loaders.DatasetLoader_Zhao2009.ID` + + Methods + ------- + - :meth:`colour_datasets.loaders.DatasetLoader_Zhao2009.__init__` + - :meth:`colour_datasets.loaders.DatasetLoader_Zhao2009.load` + + References + ---------- + :cite:`Zhao2009` + """ + + ID = '4297288' + """ + Dataset record id, i.e. the *Zenodo* record number. + + ID : unicode + """ + + def __init__(self): + super(DatasetLoader_Zhao2009, + self).__init__(datasets()[DatasetLoader_Zhao2009.ID]) + + def load(self): + """ + Syncs, parses, converts and returns the *Zhao et al. (2009)* + *Spectral Sensitivity Database* dataset content. + + Returns + ------- + OrderedDict + *Zhao et al. (2009)* *Spectral Sensitivity Database* + dataset content. + + Examples + -------- + >>> from colour_datasets.utilities import suppress_stdout + >>> dataset = DatasetLoader_Zhao2009() + >>> with suppress_stdout(): + ... dataset.load() + >>> len(dataset.content.keys()) + 12 + """ + + super(DatasetLoader_Zhao2009, self).sync() + + cameras = [ + 'SONY DXC 930', + 'KODAK DCS 420', + 'NIKON D1X', + 'SONY DXC 9000', + 'CANON 10D', + 'NIKON D70', + 'KODAK DCS 460', + 'CANON 400D', + 'CANON 5D', + 'CANON 5D Mark 2', + 'Ladybug2', + 'KODAK DCS 200', + ] + + self._content = OrderedDict() + + for i, camera in enumerate(cameras): + data = np.loadtxt( + os.path.join(self.record.repository, 'dataset', + 'camera_{0}.spectra'.format(i))) + self._content[camera] = RGB_CameraSensitivities( + data[..., 1:], data[..., 0], name=camera) + + return self._content + + +_DATASET_LOADER_JIANG2009 = None +""" +Singleton instance of the *Zhao et al. (2009)* +*Spectral Sensitivity Database* dataset loader. + +_DATASET_LOADER_JIANG2009 : DatasetLoader_Zhao2009 +""" + + +def build_Zhao2009(load=True): + """ + Singleton factory that builds the *Zhao et al. (2009)* + *Spectral Sensitivity Database* dataset loader. + + Parameters + ---------- + load : bool, optional + Whether to load the dataset upon instantiation. + + Returns + ------- + DatasetLoader_Zhao2009 + Singleton instance of the *Zhao et al. (2009)* + *Spectral Sensitivity Database* dataset loader. + + References + ---------- + :cite:`Zhao2009` + """ + + global _DATASET_LOADER_JIANG2009 + + if _DATASET_LOADER_JIANG2009 is None: + _DATASET_LOADER_JIANG2009 = DatasetLoader_Zhao2009() + if load: + _DATASET_LOADER_JIANG2009.load() + + return _DATASET_LOADER_JIANG2009 diff --git a/docs/colour_datasets.loaders.rst b/docs/colour_datasets.loaders.rst index a33d2fd..f4dec49 100644 --- a/docs/colour_datasets.loaders.rst +++ b/docs/colour_datasets.loaders.rst @@ -290,3 +290,17 @@ RAW to ACES Utility Data - Dyer et al. (2017) :toctree: generated/ build_Dyer2017 + +Spectral Sensitivity Database - Zhao et al. (2009) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. autosummary:: + :toctree: generated/ + :template: class.rst + + DatasetLoader_Zhao2009 + +.. autosummary:: + :toctree: generated/ + + build_Zhao2009 diff --git a/docs/index.rst b/docs/index.rst index 49238e5..91dc9d4 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -121,14 +121,13 @@ definition: colour-science-datasets ======================= - Datasets : 18 + Datasets : 19 Synced : 1 URL : https://zenodo.org/communities/colour-science-datasets/ Datasets -------- - [ ] 4050598 : Spectral Upsampling Coefficient Tables - Jakob and Hanika (2019) [ ] 3269926 : Agfa IT8.7/2 Set - Marszalec (n.d.) [ ] 3245883 : Camera Spectral Sensitivity Database - Jiang et al. (2013) [ ] 3367463 : Constant Hue Loci Data - Hung and Berns (1995) @@ -146,6 +145,8 @@ definition: [ ] 3252742 : Observer Function Database - Asano (2015) [ ] 3269922 : Paper Spectra - Haanpalo (n.d.) [ ] 3372171 : RAW to ACES Utility Data - Dyer et al. (2017) + [ ] 4297288 : Spectral Sensitivity Database - Zhao et al. (2009) + [ ] 4050598 : Spectral Upsampling Coefficient Tables - Jakob and Hanika. (2019) A ticked checkbox means that the particular dataset has been synced locally. A dataset is loaded by using its unique number: *3245895*: