[libcamera-devel,2/3] utils: raspberrypi: ctt: Add alsc_only method
diff mbox series

Message ID 20220706101836.20153-3-david.plowman@raspberrypi.com
State Superseded
Headers show
Series
  • Raspberry Pi tuning tool improvements
Related show

Commit Message

David Plowman July 6, 2022, 10:18 a.m. UTC
From: William Vinnicombe <william.vinnicombe@raspberrypi.com>

The ctt would not work if only passed alsc images.

Added alsc_only.py to run alsc calibration only, and modified check_imgs
to allow for no macbeth chart images.

Example usage would be ./alsc_only.py -i tuning-images/ -o sensor.json
with the same optional arguments as the original ctt.

Signed-off-by: William Vinnicombe <william.vinnicombe@raspberrypi.com>
---
 utils/raspberrypi/ctt/alsc_only.py | 118 +++++++++++++++++++++++++++++
 utils/raspberrypi/ctt/ctt.py       |   8 +-
 2 files changed, 124 insertions(+), 2 deletions(-)
 create mode 100755 utils/raspberrypi/ctt/alsc_only.py

Comments

David Plowman July 6, 2022, 11:52 a.m. UTC | #1
Hi William

Thanks for the patch.

On Wed, 6 Jul 2022 at 11:18, David Plowman
<david.plowman@raspberrypi.com> wrote:
>
> From: William Vinnicombe <william.vinnicombe@raspberrypi.com>
>
> The ctt would not work if only passed alsc images.
>
> Added alsc_only.py to run alsc calibration only, and modified check_imgs
> to allow for no macbeth chart images.
>
> Example usage would be ./alsc_only.py -i tuning-images/ -o sensor.json
> with the same optional arguments as the original ctt.
>
> Signed-off-by: William Vinnicombe <william.vinnicombe@raspberrypi.com>

Reviewed-by: David Plowman <david.plowman@raspberrypi.com>

Thanks!
David

> ---
>  utils/raspberrypi/ctt/alsc_only.py | 118 +++++++++++++++++++++++++++++
>  utils/raspberrypi/ctt/ctt.py       |   8 +-
>  2 files changed, 124 insertions(+), 2 deletions(-)
>  create mode 100755 utils/raspberrypi/ctt/alsc_only.py
>
> diff --git a/utils/raspberrypi/ctt/alsc_only.py b/utils/raspberrypi/ctt/alsc_only.py
> new file mode 100755
> index 00000000..318adc8c
> --- /dev/null
> +++ b/utils/raspberrypi/ctt/alsc_only.py
> @@ -0,0 +1,118 @@
> +#!/usr/bin/env python3
> +#
> +# SPDX-License-Identifier: BSD-2-Clause
> +#
> +# Copyright (C) 2022, Raspberry Pi (Trading) Limited
> +#
> +# alsc_only.py - alsc tuning tool
> +
> +from ctt import *
> +
> +
> +def run_alsc(json_output, directory, config, log_output):
> +    """
> +    check input files are jsons
> +    """
> +    if json_output[-5:] != '.json':
> +        raise ArgError('\n\nError: Output must be a json file!')
> +    if config is not None:
> +        """
> +        check if config file is actually a json
> +        """
> +        if config[-5:] != '.json':
> +            raise ArgError('\n\nError: Config file must be a json file!')
> +        """
> +        read configurations
> +        """
> +        try:
> +            with open(config, 'r') as config_json:
> +                configs = json.load(config_json)
> +        except FileNotFoundError:
> +            configs = {}
> +            config = False
> +        except json.decoder.JSONDecodeError:
> +            configs = {}
> +            config = True
> +
> +    else:
> +        configs = {}
> +    """
> +    load configurations from config file, if not given then set default
> +    only load configurations needed for alsc, and directly define others
> +    """
> +    plot = get_config(configs, "plot", [], 'list')
> +    alsc_d = get_config(configs, "alsc", {}, 'dict')
> +    do_alsc_colour = get_config(alsc_d, "do_alsc_colour", 1, 'bool')
> +    luminance_strength = get_config(alsc_d, "luminance_strength", 0.5, 'num')
> +    blacklevel = get_config(configs, "blacklevel", -1, 'num')
> +    mac_config = (0, 0)
> +
> +    if blacklevel < -1 or blacklevel >= 2**16:
> +        print('\nInvalid blacklevel, defaulted to 64')
> +        blacklevel = -1
> +
> +    if luminance_strength < 0 or luminance_strength > 1:
> +        print('\nInvalid luminance_strength strength, defaulted to 0.5')
> +        luminance_strength = 0.5
> +
> +    """
> +    sanitise directory path
> +    """
> +    if directory[-1] != '/':
> +        directory += '/'
> +    """
> +    initialise tuning tool and load images
> +    """
> +    try:
> +        Cam = Camera(json_output)
> +        Cam.log_user_input(json_output, directory, config, log_output)
> +        disable = set(Cam.json.keys()).symmetric_difference({"rpi.alsc"})
> +        Cam.disable = disable
> +        Cam.plot = plot
> +        Cam.add_imgs(directory, mac_config, blacklevel)
> +    except FileNotFoundError:
> +        raise ArgError('\n\nError: Input image directory not found!')
> +
> +    """
> +    preform calibrations as long as check_imgs returns True
> +    Only performs the alsc calibration
> +    """
> +    if Cam.check_imgs(macbeth=False):
> +        Cam.json_remove(disable)
> +        print('\nSTARTING CALIBRATIONS')
> +        Cam.alsc_cal(luminance_strength, do_alsc_colour)
> +        print('\nFINISHED CALIBRATIONS')
> +        Cam.write_json()
> +        Cam.write_log(log_output)
> +        print('\nCalibrations written to: '+json_output)
> +        if log_output is None:
> +            log_output = 'ctt_log.txt'
> +        print('Log file written to: '+log_output)
> +        pass
> +    else:
> +        Cam.write_log(log_output)
> +
> +
> +if __name__ == '__main__':
> +    """
> +    initialise calibration
> +    """
> +    if len(sys.argv) == 1:
> +        print("""
> +    Pisp Camera Tuning Tool version 1.0
> +
> +    Required Arguments:
> +    '-i' : Calibration image directory.
> +    '-o' : Name of output json file.
> +
> +    Optional Arguments:
> +    '-c' : Config file for the CTT. If not passed, default parameters used.
> +    '-l' : Name of output log file. If not passed, 'ctt_log.txt' used.
> +              """)
> +        quit(0)
> +    else:
> +        """
> +        parse input arguments
> +        """
> +        json_output, directory, config, log_output = parse_input()
> +        run_alsc(json_output, directory, config, log_output)
> diff --git a/utils/raspberrypi/ctt/ctt.py b/utils/raspberrypi/ctt/ctt.py
> index 15064634..0ea4854d 100755
> --- a/utils/raspberrypi/ctt/ctt.py
> +++ b/utils/raspberrypi/ctt/ctt.py
> @@ -664,7 +664,7 @@ class Camera:
>          - incorrect filename/extension
>          - images from different cameras
>      """
> -    def check_imgs(self):
> +    def check_imgs(self, macbeth=True):
>          self.log += '\n\nImages found:'
>          self.log += '\nMacbeth : {}'.format(len(self.imgs))
>          self.log += '\nALSC : {} '.format(len(self.imgs_alsc))
> @@ -672,10 +672,14 @@ class Camera:
>          """
>          check usable images found
>          """
> -        if len(self.imgs) == 0:
> +        if len(self.imgs) == 0 and macbeth:
>              print('\nERROR: No usable macbeth chart images found')
>              self.log += '\nERROR: No usable macbeth chart images found'
>              return 0
> +        elif len(self.imgs) == 0 and len(self.imgs_alsc) == 0:
> +            print('\nERROR: No usable images found')
> +            self.log += '\nERROR: No usable images found'
> +            return 0
>          """
>          Double check that every image has come from the same camera...
>          """
> --
> 2.30.2
>
Laurent Pinchart July 6, 2022, 5:43 p.m. UTC | #2
Hi David and William,

Thank you for the patch.

On Wed, Jul 06, 2022 at 11:18:35AM +0100, David Plowman via libcamera-devel wrote:
> From: William Vinnicombe <william.vinnicombe@raspberrypi.com>
> 
> The ctt would not work if only passed alsc images.
> 
> Added alsc_only.py to run alsc calibration only, and modified check_imgs
> to allow for no macbeth chart images.

The commit message should use the present tense, as it describes what is
being done. s/Added/Add/ and s/modified/modify/.

> Example usage would be ./alsc_only.py -i tuning-images/ -o sensor.json
> with the same optional arguments as the original ctt.
> 
> Signed-off-by: William Vinnicombe <william.vinnicombe@raspberrypi.com>
> ---
>  utils/raspberrypi/ctt/alsc_only.py | 118 +++++++++++++++++++++++++++++
>  utils/raspberrypi/ctt/ctt.py       |   8 +-
>  2 files changed, 124 insertions(+), 2 deletions(-)
>  create mode 100755 utils/raspberrypi/ctt/alsc_only.py
> 
> diff --git a/utils/raspberrypi/ctt/alsc_only.py b/utils/raspberrypi/ctt/alsc_only.py
> new file mode 100755
> index 00000000..318adc8c
> --- /dev/null
> +++ b/utils/raspberrypi/ctt/alsc_only.py
> @@ -0,0 +1,118 @@
> +#!/usr/bin/env python3
> +#
> +# SPDX-License-Identifier: BSD-2-Clause
> +#
> +# Copyright (C) 2022, Raspberry Pi (Trading) Limited
> +#
> +# alsc_only.py - alsc tuning tool
> +
> +from ctt import *
> +
> +
> +def run_alsc(json_output, directory, config, log_output):
> +    """
> +    check input files are jsons
> +    """
> +    if json_output[-5:] != '.json':
> +        raise ArgError('\n\nError: Output must be a json file!')
> +    if config is not None:
> +        """
> +        check if config file is actually a json
> +        """
> +        if config[-5:] != '.json':
> +            raise ArgError('\n\nError: Config file must be a json file!')
> +        """
> +        read configurations
> +        """
> +        try:
> +            with open(config, 'r') as config_json:
> +                configs = json.load(config_json)
> +        except FileNotFoundError:
> +            configs = {}
> +            config = False
> +        except json.decoder.JSONDecodeError:
> +            configs = {}
> +            config = True
> +
> +    else:
> +        configs = {}
> +    """
> +    load configurations from config file, if not given then set default
> +    only load configurations needed for alsc, and directly define others
> +    """
> +    plot = get_config(configs, "plot", [], 'list')
> +    alsc_d = get_config(configs, "alsc", {}, 'dict')
> +    do_alsc_colour = get_config(alsc_d, "do_alsc_colour", 1, 'bool')
> +    luminance_strength = get_config(alsc_d, "luminance_strength", 0.5, 'num')
> +    blacklevel = get_config(configs, "blacklevel", -1, 'num')
> +    mac_config = (0, 0)
> +
> +    if blacklevel < -1 or blacklevel >= 2**16:
> +        print('\nInvalid blacklevel, defaulted to 64')
> +        blacklevel = -1
> +
> +    if luminance_strength < 0 or luminance_strength > 1:
> +        print('\nInvalid luminance_strength strength, defaulted to 0.5')
> +        luminance_strength = 0.5
> +
> +    """
> +    sanitise directory path
> +    """
> +    if directory[-1] != '/':
> +        directory += '/'
> +    """
> +    initialise tuning tool and load images
> +    """
> +    try:
> +        Cam = Camera(json_output)
> +        Cam.log_user_input(json_output, directory, config, log_output)
> +        disable = set(Cam.json.keys()).symmetric_difference({"rpi.alsc"})
> +        Cam.disable = disable
> +        Cam.plot = plot
> +        Cam.add_imgs(directory, mac_config, blacklevel)
> +    except FileNotFoundError:
> +        raise ArgError('\n\nError: Input image directory not found!')
> +
> +    """
> +    preform calibrations as long as check_imgs returns True
> +    Only performs the alsc calibration
> +    """
> +    if Cam.check_imgs(macbeth=False):
> +        Cam.json_remove(disable)
> +        print('\nSTARTING CALIBRATIONS')
> +        Cam.alsc_cal(luminance_strength, do_alsc_colour)
> +        print('\nFINISHED CALIBRATIONS')
> +        Cam.write_json()
> +        Cam.write_log(log_output)
> +        print('\nCalibrations written to: '+json_output)
> +        if log_output is None:
> +            log_output = 'ctt_log.txt'
> +        print('Log file written to: '+log_output)
> +        pass
> +    else:
> +        Cam.write_log(log_output)

This duplicates quite a bit of code from run_ctt(). Could we make
run_ctt() more modular instead ?

> +
> +
> +if __name__ == '__main__':
> +    """
> +    initialise calibration
> +    """
> +    if len(sys.argv) == 1:
> +        print("""
> +    Pisp Camera Tuning Tool version 1.0
> +
> +    Required Arguments:
> +    '-i' : Calibration image directory.
> +    '-o' : Name of output json file.
> +
> +    Optional Arguments:
> +    '-c' : Config file for the CTT. If not passed, default parameters used.
> +    '-l' : Name of output log file. If not passed, 'ctt_log.txt' used.
> +              """)
> +        quit(0)
> +    else:
> +        """
> +        parse input arguments
> +        """
> +        json_output, directory, config, log_output = parse_input()
> +        run_alsc(json_output, directory, config, log_output)
> diff --git a/utils/raspberrypi/ctt/ctt.py b/utils/raspberrypi/ctt/ctt.py
> index 15064634..0ea4854d 100755
> --- a/utils/raspberrypi/ctt/ctt.py
> +++ b/utils/raspberrypi/ctt/ctt.py
> @@ -664,7 +664,7 @@ class Camera:
>          - incorrect filename/extension
>          - images from different cameras
>      """
> -    def check_imgs(self):
> +    def check_imgs(self, macbeth=True):
>          self.log += '\n\nImages found:'
>          self.log += '\nMacbeth : {}'.format(len(self.imgs))
>          self.log += '\nALSC : {} '.format(len(self.imgs_alsc))
> @@ -672,10 +672,14 @@ class Camera:
>          """
>          check usable images found
>          """
> -        if len(self.imgs) == 0:
> +        if len(self.imgs) == 0 and macbeth:
>              print('\nERROR: No usable macbeth chart images found')
>              self.log += '\nERROR: No usable macbeth chart images found'
>              return 0
> +        elif len(self.imgs) == 0 and len(self.imgs_alsc) == 0:
> +            print('\nERROR: No usable images found')
> +            self.log += '\nERROR: No usable images found'
> +            return 0
>          """
>          Double check that every image has come from the same camera...
>          """
Naushir Patuck July 11, 2022, 9:40 a.m. UTC | #3
Hi William,

Thank you for your work.

On Wed, 6 Jul 2022 at 11:18, David Plowman via libcamera-devel <
libcamera-devel@lists.libcamera.org> wrote:

> From: William Vinnicombe <william.vinnicombe@raspberrypi.com>
>
> The ctt would not work if only passed alsc images.
>
> Added alsc_only.py to run alsc calibration only, and modified check_imgs
> to allow for no macbeth chart images.
>
> Example usage would be ./alsc_only.py -i tuning-images/ -o sensor.json
> with the same optional arguments as the original ctt.
>
> Signed-off-by: William Vinnicombe <william.vinnicombe@raspberrypi.com>
>

Reviewed-by: Naushir Patuck <naush@raspberrypi.com>



> ---
>  utils/raspberrypi/ctt/alsc_only.py | 118 +++++++++++++++++++++++++++++
>  utils/raspberrypi/ctt/ctt.py       |   8 +-
>  2 files changed, 124 insertions(+), 2 deletions(-)
>  create mode 100755 utils/raspberrypi/ctt/alsc_only.py
>
> diff --git a/utils/raspberrypi/ctt/alsc_only.py
> b/utils/raspberrypi/ctt/alsc_only.py
> new file mode 100755
> index 00000000..318adc8c
> --- /dev/null
> +++ b/utils/raspberrypi/ctt/alsc_only.py
> @@ -0,0 +1,118 @@
> +#!/usr/bin/env python3
> +#
> +# SPDX-License-Identifier: BSD-2-Clause
> +#
> +# Copyright (C) 2022, Raspberry Pi (Trading) Limited
> +#
> +# alsc_only.py - alsc tuning tool
> +
> +from ctt import *
> +
> +
> +def run_alsc(json_output, directory, config, log_output):
> +    """
> +    check input files are jsons
> +    """
> +    if json_output[-5:] != '.json':
> +        raise ArgError('\n\nError: Output must be a json file!')
> +    if config is not None:
> +        """
> +        check if config file is actually a json
> +        """
> +        if config[-5:] != '.json':
> +            raise ArgError('\n\nError: Config file must be a json file!')
> +        """
> +        read configurations
> +        """
> +        try:
> +            with open(config, 'r') as config_json:
> +                configs = json.load(config_json)
> +        except FileNotFoundError:
> +            configs = {}
> +            config = False
> +        except json.decoder.JSONDecodeError:
> +            configs = {}
> +            config = True
> +
> +    else:
> +        configs = {}
> +    """
> +    load configurations from config file, if not given then set default
> +    only load configurations needed for alsc, and directly define others
> +    """
> +    plot = get_config(configs, "plot", [], 'list')
> +    alsc_d = get_config(configs, "alsc", {}, 'dict')
> +    do_alsc_colour = get_config(alsc_d, "do_alsc_colour", 1, 'bool')
> +    luminance_strength = get_config(alsc_d, "luminance_strength", 0.5,
> 'num')
> +    blacklevel = get_config(configs, "blacklevel", -1, 'num')
> +    mac_config = (0, 0)
> +
> +    if blacklevel < -1 or blacklevel >= 2**16:
> +        print('\nInvalid blacklevel, defaulted to 64')
> +        blacklevel = -1
> +
> +    if luminance_strength < 0 or luminance_strength > 1:
> +        print('\nInvalid luminance_strength strength, defaulted to 0.5')
> +        luminance_strength = 0.5
> +
> +    """
> +    sanitise directory path
> +    """
> +    if directory[-1] != '/':
> +        directory += '/'
> +    """
> +    initialise tuning tool and load images
> +    """
> +    try:
> +        Cam = Camera(json_output)
> +        Cam.log_user_input(json_output, directory, config, log_output)
> +        disable = set(Cam.json.keys()).symmetric_difference({"rpi.alsc"})
> +        Cam.disable = disable
> +        Cam.plot = plot
> +        Cam.add_imgs(directory, mac_config, blacklevel)
> +    except FileNotFoundError:
> +        raise ArgError('\n\nError: Input image directory not found!')
> +
> +    """
> +    preform calibrations as long as check_imgs returns True
> +    Only performs the alsc calibration
> +    """
> +    if Cam.check_imgs(macbeth=False):
> +        Cam.json_remove(disable)
> +        print('\nSTARTING CALIBRATIONS')
> +        Cam.alsc_cal(luminance_strength, do_alsc_colour)
> +        print('\nFINISHED CALIBRATIONS')
> +        Cam.write_json()
> +        Cam.write_log(log_output)
> +        print('\nCalibrations written to: '+json_output)
> +        if log_output is None:
> +            log_output = 'ctt_log.txt'
> +        print('Log file written to: '+log_output)
> +        pass
> +    else:
> +        Cam.write_log(log_output)
> +
> +
> +if __name__ == '__main__':
> +    """
> +    initialise calibration
> +    """
> +    if len(sys.argv) == 1:
> +        print("""
> +    Pisp Camera Tuning Tool version 1.0
> +
> +    Required Arguments:
> +    '-i' : Calibration image directory.
> +    '-o' : Name of output json file.
> +
> +    Optional Arguments:
> +    '-c' : Config file for the CTT. If not passed, default parameters
> used.
> +    '-l' : Name of output log file. If not passed, 'ctt_log.txt' used.
> +              """)
> +        quit(0)
> +    else:
> +        """
> +        parse input arguments
> +        """
> +        json_output, directory, config, log_output = parse_input()
> +        run_alsc(json_output, directory, config, log_output)
> diff --git a/utils/raspberrypi/ctt/ctt.py b/utils/raspberrypi/ctt/ctt.py
> index 15064634..0ea4854d 100755
> --- a/utils/raspberrypi/ctt/ctt.py
> +++ b/utils/raspberrypi/ctt/ctt.py
> @@ -664,7 +664,7 @@ class Camera:
>          - incorrect filename/extension
>          - images from different cameras
>      """
> -    def check_imgs(self):
> +    def check_imgs(self, macbeth=True):
>          self.log += '\n\nImages found:'
>          self.log += '\nMacbeth : {}'.format(len(self.imgs))
>          self.log += '\nALSC : {} '.format(len(self.imgs_alsc))
> @@ -672,10 +672,14 @@ class Camera:
>          """
>          check usable images found
>          """
> -        if len(self.imgs) == 0:
> +        if len(self.imgs) == 0 and macbeth:
>              print('\nERROR: No usable macbeth chart images found')
>              self.log += '\nERROR: No usable macbeth chart images found'
>              return 0
> +        elif len(self.imgs) == 0 and len(self.imgs_alsc) == 0:
> +            print('\nERROR: No usable images found')
> +            self.log += '\nERROR: No usable images found'
> +            return 0
>          """
>          Double check that every image has come from the same camera...
>          """
> --
> 2.30.2
>
>

Patch
diff mbox series

diff --git a/utils/raspberrypi/ctt/alsc_only.py b/utils/raspberrypi/ctt/alsc_only.py
new file mode 100755
index 00000000..318adc8c
--- /dev/null
+++ b/utils/raspberrypi/ctt/alsc_only.py
@@ -0,0 +1,118 @@ 
+#!/usr/bin/env python3
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (C) 2022, Raspberry Pi (Trading) Limited
+#
+# alsc_only.py - alsc tuning tool
+
+from ctt import *
+
+
+def run_alsc(json_output, directory, config, log_output):
+    """
+    check input files are jsons
+    """
+    if json_output[-5:] != '.json':
+        raise ArgError('\n\nError: Output must be a json file!')
+    if config is not None:
+        """
+        check if config file is actually a json
+        """
+        if config[-5:] != '.json':
+            raise ArgError('\n\nError: Config file must be a json file!')
+        """
+        read configurations
+        """
+        try:
+            with open(config, 'r') as config_json:
+                configs = json.load(config_json)
+        except FileNotFoundError:
+            configs = {}
+            config = False
+        except json.decoder.JSONDecodeError:
+            configs = {}
+            config = True
+
+    else:
+        configs = {}
+    """
+    load configurations from config file, if not given then set default
+    only load configurations needed for alsc, and directly define others
+    """
+    plot = get_config(configs, "plot", [], 'list')
+    alsc_d = get_config(configs, "alsc", {}, 'dict')
+    do_alsc_colour = get_config(alsc_d, "do_alsc_colour", 1, 'bool')
+    luminance_strength = get_config(alsc_d, "luminance_strength", 0.5, 'num')
+    blacklevel = get_config(configs, "blacklevel", -1, 'num')
+    mac_config = (0, 0)
+
+    if blacklevel < -1 or blacklevel >= 2**16:
+        print('\nInvalid blacklevel, defaulted to 64')
+        blacklevel = -1
+
+    if luminance_strength < 0 or luminance_strength > 1:
+        print('\nInvalid luminance_strength strength, defaulted to 0.5')
+        luminance_strength = 0.5
+
+    """
+    sanitise directory path
+    """
+    if directory[-1] != '/':
+        directory += '/'
+    """
+    initialise tuning tool and load images
+    """
+    try:
+        Cam = Camera(json_output)
+        Cam.log_user_input(json_output, directory, config, log_output)
+        disable = set(Cam.json.keys()).symmetric_difference({"rpi.alsc"})
+        Cam.disable = disable
+        Cam.plot = plot
+        Cam.add_imgs(directory, mac_config, blacklevel)
+    except FileNotFoundError:
+        raise ArgError('\n\nError: Input image directory not found!')
+
+    """
+    preform calibrations as long as check_imgs returns True
+    Only performs the alsc calibration
+    """
+    if Cam.check_imgs(macbeth=False):
+        Cam.json_remove(disable)
+        print('\nSTARTING CALIBRATIONS')
+        Cam.alsc_cal(luminance_strength, do_alsc_colour)
+        print('\nFINISHED CALIBRATIONS')
+        Cam.write_json()
+        Cam.write_log(log_output)
+        print('\nCalibrations written to: '+json_output)
+        if log_output is None:
+            log_output = 'ctt_log.txt'
+        print('Log file written to: '+log_output)
+        pass
+    else:
+        Cam.write_log(log_output)
+
+
+if __name__ == '__main__':
+    """
+    initialise calibration
+    """
+    if len(sys.argv) == 1:
+        print("""
+    Pisp Camera Tuning Tool version 1.0
+
+    Required Arguments:
+    '-i' : Calibration image directory.
+    '-o' : Name of output json file.
+
+    Optional Arguments:
+    '-c' : Config file for the CTT. If not passed, default parameters used.
+    '-l' : Name of output log file. If not passed, 'ctt_log.txt' used.
+              """)
+        quit(0)
+    else:
+        """
+        parse input arguments
+        """
+        json_output, directory, config, log_output = parse_input()
+        run_alsc(json_output, directory, config, log_output)
diff --git a/utils/raspberrypi/ctt/ctt.py b/utils/raspberrypi/ctt/ctt.py
index 15064634..0ea4854d 100755
--- a/utils/raspberrypi/ctt/ctt.py
+++ b/utils/raspberrypi/ctt/ctt.py
@@ -664,7 +664,7 @@  class Camera:
         - incorrect filename/extension
         - images from different cameras
     """
-    def check_imgs(self):
+    def check_imgs(self, macbeth=True):
         self.log += '\n\nImages found:'
         self.log += '\nMacbeth : {}'.format(len(self.imgs))
         self.log += '\nALSC : {} '.format(len(self.imgs_alsc))
@@ -672,10 +672,14 @@  class Camera:
         """
         check usable images found
         """
-        if len(self.imgs) == 0:
+        if len(self.imgs) == 0 and macbeth:
             print('\nERROR: No usable macbeth chart images found')
             self.log += '\nERROR: No usable macbeth chart images found'
             return 0
+        elif len(self.imgs) == 0 and len(self.imgs_alsc) == 0:
+            print('\nERROR: No usable images found')
+            self.log += '\nERROR: No usable images found'
+            return 0
         """
         Double check that every image has come from the same camera...
         """