[{"id":30308,"web_url":"https://patchwork.libcamera.org/comment/30308/","msgid":"<ZoZzyLMh_ftbXtG6@pyrite.rasen.tech>","date":"2024-07-04T10:04:56","subject":"Re: [PATCH v3 16/23] libtuning: modules: Add initial CCM module","submitter":{"id":17,"url":"https://patchwork.libcamera.org/api/people/17/","name":"Paul Elder","email":"paul.elder@ideasonboard.com"},"content":"On Wed, Jul 03, 2024 at 04:17:05PM +0200, Stefan Klug wrote:\n> From: Paul Elder <paul.elder@ideasonboard.com>\n> \n> Implement a minimal ccm calibration module. For now it doesn't take the\n> results from lsc into account and supports rkisp1 only.\n> \n> Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>\n> Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>\n> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> ---\n>  .../tuning/libtuning/modules/ccm/__init__.py  |  6 +++\n>  utils/tuning/libtuning/modules/ccm/ccm.py     | 41 +++++++++++++++++++\n>  utils/tuning/libtuning/modules/ccm/rkisp1.py  | 27 ++++++++++++\n>  utils/tuning/rkisp1.py                        |  4 +-\n>  4 files changed, 77 insertions(+), 1 deletion(-)\n>  create mode 100644 utils/tuning/libtuning/modules/ccm/__init__.py\n>  create mode 100644 utils/tuning/libtuning/modules/ccm/ccm.py\n>  create mode 100644 utils/tuning/libtuning/modules/ccm/rkisp1.py\n> \n> diff --git a/utils/tuning/libtuning/modules/ccm/__init__.py b/utils/tuning/libtuning/modules/ccm/__init__.py\n> new file mode 100644\n> index 000000000000..322602afe63b\n> --- /dev/null\n> +++ b/utils/tuning/libtuning/modules/ccm/__init__.py\n> @@ -0,0 +1,6 @@\n> +# SPDX-License-Identifier: GPL-2.0-or-later\n> +#\n> +# Copyright (C) 2024, Paul Elder <paul.elder@ideasonboard.com>\n> +\n> +from libtuning.modules.ccm.ccm import CCM\n> +from libtuning.modules.ccm.rkisp1 import CCMRkISP1\n> diff --git a/utils/tuning/libtuning/modules/ccm/ccm.py b/utils/tuning/libtuning/modules/ccm/ccm.py\n> new file mode 100644\n> index 000000000000..ba433404f069\n> --- /dev/null\n> +++ b/utils/tuning/libtuning/modules/ccm/ccm.py\n> @@ -0,0 +1,41 @@\n> +# SPDX-License-Identifier: GPL-2.0-or-later\n> +#\n> +# Copyright (C) 2024, Paul Elder <paul.elder@ideasonboard.com>\n> +# Copyright (C) 2024, Ideas on Board\n> +#\n> +# Base Ccm tuning module\n> +\n> +from ..module import Module\n> +\n> +from libtuning.ctt_ccm import ccm\n> +import logging\n> +\n> +logger = logging.getLogger(__name__)\n> +\n> +\n> +class CCM(Module):\n> +    type = 'ccm'\n> +    hr_name = 'CCM (Base)'\n> +    out_name = 'GenericCCM'\n> +\n> +    def __init__(self, debug: list):\n> +        super().__init__()\n> +\n> +        self.debug = debug\n> +\n> +    def do_calibration(self, images):\n> +        logger.info('Starting CCM calibration')\n> +\n> +        imgs = [img for img in images if img.macbeth is not None]\n> +\n> +        # todo: Take LSC calibration results into account.\n> +        cal_cr_list = None\n> +        cal_cb_list = None\n> +\n> +        try:\n> +            ccms = ccm(imgs, cal_cr_list, cal_cb_list)\n\nOoh that's cool.\n\n> +        except ArithmeticError:\n> +            logger.error('CCM calibration failed')\n> +            return 1\n> +\n> +        return ccms\n> diff --git a/utils/tuning/libtuning/modules/ccm/rkisp1.py b/utils/tuning/libtuning/modules/ccm/rkisp1.py\n> new file mode 100644\n> index 000000000000..00381abe2893\n> --- /dev/null\n> +++ b/utils/tuning/libtuning/modules/ccm/rkisp1.py\n> @@ -0,0 +1,27 @@\n> +# SPDX-License-Identifier: GPL-2.0-or-later\n> +#\n> +# Copyright (C) 2024, Paul Elder <paul.elder@ideasonboard.com>\n> +# Copyright (C) 2024, Ideas on Board\n> +#\n> +# Ccm module for tuning rkisp1\n> +\n> +from .ccm import CCM\n> +\n> +class CCMRkISP1(CCM):\n> +    hr_name = 'Crosstalk Correction (RkISP1)'\n> +    out_name = 'Ccm'\n> +\n> +    def __init__(self, **kwargs):\n> +        super().__init__(**kwargs)\n> +\n> +    # We don't need anything from the config file.\n> +    def validate_config(self, config: dict) -> bool:\n> +        return True\n> +\n> +    def process(self, config: dict, images: list, outputs: dict) -> dict:\n> +        output = {}\n> +\n> +        ccms = self.do_calibration(images)\n\nDon't we need to error check this?\n\nOtherwise we'd get a single 1 for the ccm; not even a matrix.\n\n\nPaul\n\n> +        output['ccms'] = ccms\n> +\n> +        return output\n> diff --git a/utils/tuning/rkisp1.py b/utils/tuning/rkisp1.py\n> index 2606e07a93f7..fae35783c656 100755\n> --- a/utils/tuning/rkisp1.py\n> +++ b/utils/tuning/rkisp1.py\n> @@ -14,6 +14,7 @@ from libtuning.parsers import YamlParser\n>  from libtuning.generators import YamlOutput\n>  from libtuning.modules.lsc import LSCRkISP1\n>  from libtuning.modules.agc import AGCRkISP1\n> +from libtuning.modules.ccm import CCMRkISP1\n>  \n>  \n>  coloredlogs.install(level=logging.INFO, fmt='%(name)s %(levelname)s %(message)s')\n> @@ -39,9 +40,10 @@ tuner.add(LSCRkISP1(\n>            smoothing_function=lt.smoothing.MedianBlur(3),\n>            ))\n>  tuner.add(AGCRkISP1(debug=[lt.Debug.Plot]))\n> +tuner.add(CCMRkISP1(debug=[lt.Debug.Plot]))\n>  tuner.set_input_parser(YamlParser())\n>  tuner.set_output_formatter(YamlOutput())\n> -tuner.set_output_order([AGCRkISP1, LSCRkISP1])\n> +tuner.set_output_order([AGCRkISP1, CCMRkISP1, LSCRkISP1])\n>  \n>  if __name__ == '__main__':\n>      sys.exit(tuner.run(sys.argv))\n> -- \n> 2.43.0\n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id C5124BEFBE\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu,  4 Jul 2024 10:05:05 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id F018B62C99;\n\tThu,  4 Jul 2024 12:05:04 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id C89B1619C8\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu,  4 Jul 2024 12:05:02 +0200 (CEST)","from pyrite.rasen.tech (h175-177-049-156.catv02.itscom.jp\n\t[175.177.49.156])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id E56A3502;\n\tThu,  4 Jul 2024 12:04:32 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"o4nL41al\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1720087474;\n\tbh=z+FyOih0n0QNGsrxfT0SmRFOsxXTeN1h+M24QgDO7Wg=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=o4nL41alXaxitTujC0EKxs4oMMmtbwNE5GqNokPhUw4AxqGUTDm7qXDpLpS4LHeVl\n\tW6cQqazDpAjuS3Os92jzFyh8MJXtWakdMmbDc9XHt5aI1xjMLyBAQalOWbjncE6JmJ\n\t7mnkh+w5j3GFKkOayUHzzG1AEfS90yBiu65u0DkU=","Date":"Thu, 4 Jul 2024 19:04:56 +0900","From":"Paul Elder <paul.elder@ideasonboard.com>","To":"Stefan Klug <stefan.klug@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org,\n\tLaurent Pinchart <laurent.pinchart@ideasonboard.com>","Subject":"Re: [PATCH v3 16/23] libtuning: modules: Add initial CCM module","Message-ID":"<ZoZzyLMh_ftbXtG6@pyrite.rasen.tech>","References":"<20240703141726.252368-1-stefan.klug@ideasonboard.com>\n\t<20240703141726.252368-17-stefan.klug@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=us-ascii","Content-Disposition":"inline","In-Reply-To":"<20240703141726.252368-17-stefan.klug@ideasonboard.com>","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":30311,"web_url":"https://patchwork.libcamera.org/comment/30311/","msgid":"<20240704101658.GA6230@pendragon.ideasonboard.com>","date":"2024-07-04T10:16:58","subject":"Re: [PATCH v3 16/23] libtuning: modules: Add initial CCM module","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"On Thu, Jul 04, 2024 at 07:04:56PM +0900, Paul Elder wrote:\n> On Wed, Jul 03, 2024 at 04:17:05PM +0200, Stefan Klug wrote:\n> > From: Paul Elder <paul.elder@ideasonboard.com>\n> > \n> > Implement a minimal ccm calibration module. For now it doesn't take the\n> > results from lsc into account and supports rkisp1 only.\n> > \n> > Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>\n> > Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>\n> > Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> > ---\n> >  .../tuning/libtuning/modules/ccm/__init__.py  |  6 +++\n> >  utils/tuning/libtuning/modules/ccm/ccm.py     | 41 +++++++++++++++++++\n> >  utils/tuning/libtuning/modules/ccm/rkisp1.py  | 27 ++++++++++++\n> >  utils/tuning/rkisp1.py                        |  4 +-\n> >  4 files changed, 77 insertions(+), 1 deletion(-)\n> >  create mode 100644 utils/tuning/libtuning/modules/ccm/__init__.py\n> >  create mode 100644 utils/tuning/libtuning/modules/ccm/ccm.py\n> >  create mode 100644 utils/tuning/libtuning/modules/ccm/rkisp1.py\n> > \n> > diff --git a/utils/tuning/libtuning/modules/ccm/__init__.py b/utils/tuning/libtuning/modules/ccm/__init__.py\n> > new file mode 100644\n> > index 000000000000..322602afe63b\n> > --- /dev/null\n> > +++ b/utils/tuning/libtuning/modules/ccm/__init__.py\n> > @@ -0,0 +1,6 @@\n> > +# SPDX-License-Identifier: GPL-2.0-or-later\n> > +#\n> > +# Copyright (C) 2024, Paul Elder <paul.elder@ideasonboard.com>\n> > +\n> > +from libtuning.modules.ccm.ccm import CCM\n> > +from libtuning.modules.ccm.rkisp1 import CCMRkISP1\n> > diff --git a/utils/tuning/libtuning/modules/ccm/ccm.py b/utils/tuning/libtuning/modules/ccm/ccm.py\n> > new file mode 100644\n> > index 000000000000..ba433404f069\n> > --- /dev/null\n> > +++ b/utils/tuning/libtuning/modules/ccm/ccm.py\n> > @@ -0,0 +1,41 @@\n> > +# SPDX-License-Identifier: GPL-2.0-or-later\n> > +#\n> > +# Copyright (C) 2024, Paul Elder <paul.elder@ideasonboard.com>\n> > +# Copyright (C) 2024, Ideas on Board\n> > +#\n> > +# Base Ccm tuning module\n> > +\n> > +from ..module import Module\n> > +\n> > +from libtuning.ctt_ccm import ccm\n> > +import logging\n> > +\n> > +logger = logging.getLogger(__name__)\n> > +\n> > +\n> > +class CCM(Module):\n> > +    type = 'ccm'\n> > +    hr_name = 'CCM (Base)'\n> > +    out_name = 'GenericCCM'\n> > +\n> > +    def __init__(self, debug: list):\n> > +        super().__init__()\n> > +\n> > +        self.debug = debug\n> > +\n> > +    def do_calibration(self, images):\n> > +        logger.info('Starting CCM calibration')\n> > +\n> > +        imgs = [img for img in images if img.macbeth is not None]\n> > +\n> > +        # todo: Take LSC calibration results into account.\n> > +        cal_cr_list = None\n> > +        cal_cb_list = None\n> > +\n> > +        try:\n> > +            ccms = ccm(imgs, cal_cr_list, cal_cb_list)\n> \n> Ooh that's cool.\n> \n> > +        except ArithmeticError:\n> > +            logger.error('CCM calibration failed')\n> > +            return 1\n> > +\n> > +        return ccms\n> > diff --git a/utils/tuning/libtuning/modules/ccm/rkisp1.py b/utils/tuning/libtuning/modules/ccm/rkisp1.py\n> > new file mode 100644\n> > index 000000000000..00381abe2893\n> > --- /dev/null\n> > +++ b/utils/tuning/libtuning/modules/ccm/rkisp1.py\n> > @@ -0,0 +1,27 @@\n> > +# SPDX-License-Identifier: GPL-2.0-or-later\n> > +#\n> > +# Copyright (C) 2024, Paul Elder <paul.elder@ideasonboard.com>\n> > +# Copyright (C) 2024, Ideas on Board\n> > +#\n> > +# Ccm module for tuning rkisp1\n> > +\n> > +from .ccm import CCM\n> > +\n> > +class CCMRkISP1(CCM):\n> > +    hr_name = 'Crosstalk Correction (RkISP1)'\n> > +    out_name = 'Ccm'\n> > +\n> > +    def __init__(self, **kwargs):\n> > +        super().__init__(**kwargs)\n> > +\n> > +    # We don't need anything from the config file.\n> > +    def validate_config(self, config: dict) -> bool:\n> > +        return True\n> > +\n> > +    def process(self, config: dict, images: list, outputs: dict) -> dict:\n> > +        output = {}\n> > +\n> > +        ccms = self.do_calibration(images)\n> \n> Don't we need to error check this?\n> \n> Otherwise we'd get a single 1 for the ccm; not even a matrix.\n\nReturning None from do_calibration() when an error occurs seems better\nthan 1. Or we could use exceptions for error handling too, but that's a\nbigger rework.\n\n> > +        output['ccms'] = ccms\n> > +\n> > +        return output\n> > diff --git a/utils/tuning/rkisp1.py b/utils/tuning/rkisp1.py\n> > index 2606e07a93f7..fae35783c656 100755\n> > --- a/utils/tuning/rkisp1.py\n> > +++ b/utils/tuning/rkisp1.py\n> > @@ -14,6 +14,7 @@ from libtuning.parsers import YamlParser\n> >  from libtuning.generators import YamlOutput\n> >  from libtuning.modules.lsc import LSCRkISP1\n> >  from libtuning.modules.agc import AGCRkISP1\n> > +from libtuning.modules.ccm import CCMRkISP1\n> >  \n> >  \n> >  coloredlogs.install(level=logging.INFO, fmt='%(name)s %(levelname)s %(message)s')\n> > @@ -39,9 +40,10 @@ tuner.add(LSCRkISP1(\n> >            smoothing_function=lt.smoothing.MedianBlur(3),\n> >            ))\n> >  tuner.add(AGCRkISP1(debug=[lt.Debug.Plot]))\n> > +tuner.add(CCMRkISP1(debug=[lt.Debug.Plot]))\n> >  tuner.set_input_parser(YamlParser())\n> >  tuner.set_output_formatter(YamlOutput())\n> > -tuner.set_output_order([AGCRkISP1, LSCRkISP1])\n> > +tuner.set_output_order([AGCRkISP1, CCMRkISP1, LSCRkISP1])\n> >  \n> >  if __name__ == '__main__':\n> >      sys.exit(tuner.run(sys.argv))","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id C7AD7BEFBE\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu,  4 Jul 2024 10:17:24 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 1532A62C99;\n\tThu,  4 Jul 2024 12:17:23 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 6F9BD619C8\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu,  4 Jul 2024 12:17:20 +0200 (CEST)","from pendragon.ideasonboard.com\n\t(117.145-247-81.adsl-dyn.isp.belgacom.be [81.247.145.117])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 8BF3D502;\n\tThu,  4 Jul 2024 12:16:51 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"K3hfrXY3\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1720088211;\n\tbh=bR5kJafVnA2Pvv5VBItDk6AyqhgeXtLVVLYtwd0RFvs=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=K3hfrXY3MvKknU2Hn6qGDsBCCsjpTGcpj52nE6EQi/DuH0Gga8jUIMq8kMclCEIK7\n\tsHvgB3HUlkqP6N7IIRjtrK4YK4iNRENHSssV+wnwUo+tkJQX3hwnmvTL3pP8bZZEOx\n\t5QrhObseBnsGDp6LBWOv9CB7JJ2K7IeR4OxF8LBc=","Date":"Thu, 4 Jul 2024 13:16:58 +0300","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Paul Elder <paul.elder@ideasonboard.com>","Cc":"Stefan Klug <stefan.klug@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org","Subject":"Re: [PATCH v3 16/23] libtuning: modules: Add initial CCM module","Message-ID":"<20240704101658.GA6230@pendragon.ideasonboard.com>","References":"<20240703141726.252368-1-stefan.klug@ideasonboard.com>\n\t<20240703141726.252368-17-stefan.klug@ideasonboard.com>\n\t<ZoZzyLMh_ftbXtG6@pyrite.rasen.tech>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<ZoZzyLMh_ftbXtG6@pyrite.rasen.tech>","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":30316,"web_url":"https://patchwork.libcamera.org/comment/30316/","msgid":"<ZoZ6Mw-eVLBQD3lD@pyrite.rasen.tech>","date":"2024-07-04T10:32:19","subject":"Re: [PATCH v3 16/23] libtuning: modules: Add initial CCM module","submitter":{"id":17,"url":"https://patchwork.libcamera.org/api/people/17/","name":"Paul Elder","email":"paul.elder@ideasonboard.com"},"content":"On Thu, Jul 04, 2024 at 01:16:58PM +0300, Laurent Pinchart wrote:\n> On Thu, Jul 04, 2024 at 07:04:56PM +0900, Paul Elder wrote:\n> > On Wed, Jul 03, 2024 at 04:17:05PM +0200, Stefan Klug wrote:\n> > > From: Paul Elder <paul.elder@ideasonboard.com>\n> > > \n> > > Implement a minimal ccm calibration module. For now it doesn't take the\n> > > results from lsc into account and supports rkisp1 only.\n> > > \n> > > Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>\n> > > Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>\n> > > Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> > > ---\n> > >  .../tuning/libtuning/modules/ccm/__init__.py  |  6 +++\n> > >  utils/tuning/libtuning/modules/ccm/ccm.py     | 41 +++++++++++++++++++\n> > >  utils/tuning/libtuning/modules/ccm/rkisp1.py  | 27 ++++++++++++\n> > >  utils/tuning/rkisp1.py                        |  4 +-\n> > >  4 files changed, 77 insertions(+), 1 deletion(-)\n> > >  create mode 100644 utils/tuning/libtuning/modules/ccm/__init__.py\n> > >  create mode 100644 utils/tuning/libtuning/modules/ccm/ccm.py\n> > >  create mode 100644 utils/tuning/libtuning/modules/ccm/rkisp1.py\n> > > \n> > > diff --git a/utils/tuning/libtuning/modules/ccm/__init__.py b/utils/tuning/libtuning/modules/ccm/__init__.py\n> > > new file mode 100644\n> > > index 000000000000..322602afe63b\n> > > --- /dev/null\n> > > +++ b/utils/tuning/libtuning/modules/ccm/__init__.py\n> > > @@ -0,0 +1,6 @@\n> > > +# SPDX-License-Identifier: GPL-2.0-or-later\n> > > +#\n> > > +# Copyright (C) 2024, Paul Elder <paul.elder@ideasonboard.com>\n> > > +\n> > > +from libtuning.modules.ccm.ccm import CCM\n> > > +from libtuning.modules.ccm.rkisp1 import CCMRkISP1\n> > > diff --git a/utils/tuning/libtuning/modules/ccm/ccm.py b/utils/tuning/libtuning/modules/ccm/ccm.py\n> > > new file mode 100644\n> > > index 000000000000..ba433404f069\n> > > --- /dev/null\n> > > +++ b/utils/tuning/libtuning/modules/ccm/ccm.py\n> > > @@ -0,0 +1,41 @@\n> > > +# SPDX-License-Identifier: GPL-2.0-or-later\n> > > +#\n> > > +# Copyright (C) 2024, Paul Elder <paul.elder@ideasonboard.com>\n> > > +# Copyright (C) 2024, Ideas on Board\n> > > +#\n> > > +# Base Ccm tuning module\n> > > +\n> > > +from ..module import Module\n> > > +\n> > > +from libtuning.ctt_ccm import ccm\n> > > +import logging\n> > > +\n> > > +logger = logging.getLogger(__name__)\n> > > +\n> > > +\n> > > +class CCM(Module):\n> > > +    type = 'ccm'\n> > > +    hr_name = 'CCM (Base)'\n> > > +    out_name = 'GenericCCM'\n> > > +\n> > > +    def __init__(self, debug: list):\n> > > +        super().__init__()\n> > > +\n> > > +        self.debug = debug\n> > > +\n> > > +    def do_calibration(self, images):\n> > > +        logger.info('Starting CCM calibration')\n> > > +\n> > > +        imgs = [img for img in images if img.macbeth is not None]\n> > > +\n> > > +        # todo: Take LSC calibration results into account.\n> > > +        cal_cr_list = None\n> > > +        cal_cb_list = None\n> > > +\n> > > +        try:\n> > > +            ccms = ccm(imgs, cal_cr_list, cal_cb_list)\n> > \n> > Ooh that's cool.\n> > \n> > > +        except ArithmeticError:\n> > > +            logger.error('CCM calibration failed')\n> > > +            return 1\n> > > +\n> > > +        return ccms\n> > > diff --git a/utils/tuning/libtuning/modules/ccm/rkisp1.py b/utils/tuning/libtuning/modules/ccm/rkisp1.py\n> > > new file mode 100644\n> > > index 000000000000..00381abe2893\n> > > --- /dev/null\n> > > +++ b/utils/tuning/libtuning/modules/ccm/rkisp1.py\n> > > @@ -0,0 +1,27 @@\n> > > +# SPDX-License-Identifier: GPL-2.0-or-later\n> > > +#\n> > > +# Copyright (C) 2024, Paul Elder <paul.elder@ideasonboard.com>\n> > > +# Copyright (C) 2024, Ideas on Board\n> > > +#\n> > > +# Ccm module for tuning rkisp1\n> > > +\n> > > +from .ccm import CCM\n> > > +\n> > > +class CCMRkISP1(CCM):\n> > > +    hr_name = 'Crosstalk Correction (RkISP1)'\n> > > +    out_name = 'Ccm'\n> > > +\n> > > +    def __init__(self, **kwargs):\n> > > +        super().__init__(**kwargs)\n> > > +\n> > > +    # We don't need anything from the config file.\n> > > +    def validate_config(self, config: dict) -> bool:\n> > > +        return True\n> > > +\n> > > +    def process(self, config: dict, images: list, outputs: dict) -> dict:\n> > > +        output = {}\n> > > +\n> > > +        ccms = self.do_calibration(images)\n> > \n> > Don't we need to error check this?\n> > \n> > Otherwise we'd get a single 1 for the ccm; not even a matrix.\n> \n> Returning None from do_calibration() when an error occurs seems better\n\nYeah that would just disable ccm, which I suppose is more efficient than\nreturning identities.\n\nPaul\n\n> than 1. Or we could use exceptions for error handling too, but that's a\n> bigger rework.\n> \n> > > +        output['ccms'] = ccms\n> > > +\n> > > +        return output\n> > > diff --git a/utils/tuning/rkisp1.py b/utils/tuning/rkisp1.py\n> > > index 2606e07a93f7..fae35783c656 100755\n> > > --- a/utils/tuning/rkisp1.py\n> > > +++ b/utils/tuning/rkisp1.py\n> > > @@ -14,6 +14,7 @@ from libtuning.parsers import YamlParser\n> > >  from libtuning.generators import YamlOutput\n> > >  from libtuning.modules.lsc import LSCRkISP1\n> > >  from libtuning.modules.agc import AGCRkISP1\n> > > +from libtuning.modules.ccm import CCMRkISP1\n> > >  \n> > >  \n> > >  coloredlogs.install(level=logging.INFO, fmt='%(name)s %(levelname)s %(message)s')\n> > > @@ -39,9 +40,10 @@ tuner.add(LSCRkISP1(\n> > >            smoothing_function=lt.smoothing.MedianBlur(3),\n> > >            ))\n> > >  tuner.add(AGCRkISP1(debug=[lt.Debug.Plot]))\n> > > +tuner.add(CCMRkISP1(debug=[lt.Debug.Plot]))\n> > >  tuner.set_input_parser(YamlParser())\n> > >  tuner.set_output_formatter(YamlOutput())\n> > > -tuner.set_output_order([AGCRkISP1, LSCRkISP1])\n> > > +tuner.set_output_order([AGCRkISP1, CCMRkISP1, LSCRkISP1])\n> > >  \n> > >  if __name__ == '__main__':\n> > >      sys.exit(tuner.run(sys.argv))","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id CA8E0BD87C\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu,  4 Jul 2024 10:32:29 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id C067D62E27;\n\tThu,  4 Jul 2024 12:32:28 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id ECCDE619C8\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu,  4 Jul 2024 12:32:26 +0200 (CEST)","from pyrite.rasen.tech (h175-177-049-156.catv02.itscom.jp\n\t[175.177.49.156])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 02A46502;\n\tThu,  4 Jul 2024 12:31:56 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"NrGm+5jB\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1720089118;\n\tbh=wR7knkxZzUt3Khi8ekGxUgvRuFiRntcfm4JqGlnDV4c=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=NrGm+5jBgNQMO1JcyTolM9R4x0IdhzF53b3ZLFt4ax6tdeMWQpk/Z61TP/4JWiJjC\n\tXrTF5t2A/4D38d+ttjLkx00LPLBVFhsLZnYUyo7wBMSbQJgSKMxAfXThWmyVBGLbPG\n\tAhtFXG1aeIsrzMK4djD+Xm9cIG0LQsttKy5hX7u8=","Date":"Thu, 4 Jul 2024 19:32:19 +0900","From":"Paul Elder <paul.elder@ideasonboard.com>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"Stefan Klug <stefan.klug@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org","Subject":"Re: [PATCH v3 16/23] libtuning: modules: Add initial CCM module","Message-ID":"<ZoZ6Mw-eVLBQD3lD@pyrite.rasen.tech>","References":"<20240703141726.252368-1-stefan.klug@ideasonboard.com>\n\t<20240703141726.252368-17-stefan.klug@ideasonboard.com>\n\t<ZoZzyLMh_ftbXtG6@pyrite.rasen.tech>\n\t<20240704101658.GA6230@pendragon.ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=us-ascii","Content-Disposition":"inline","In-Reply-To":"<20240704101658.GA6230@pendragon.ideasonboard.com>","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]