[{"id":29896,"web_url":"https://patchwork.libcamera.org/comment/29896/","msgid":"<171826706128.1550852.629646733026118654@ping.linuxembedded.co.uk>","date":"2024-06-13T08:24:21","subject":"Re: [PATCH 5/6] utils: raspberrypi: ctt: Add option to convert\n\tbetween vc4/pisp targets","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Quoting David Plowman (2024-06-06 11:15:11)\n> From: Naushir Patuck <naush@raspberrypi.com>\n> \n> This change adds functionality to the convert_tuning.py script to\n> convert between vc4 and pisp target tuning files. The conversion is\n> done on a best effort basis, and should provide functional tuning files.\n> However, a full tuning for the target platform is always preferred.\n> \n> Signed-off-by: Naushir Patuck <naush@raspberrypi.com>\n\nHi David,\n\nCan I assume you have supplied your SoB and RB tag to this one already?\n\n--\nKieran\n\n\n> ---\n>  utils/raspberrypi/ctt/convert_tuning.py | 98 ++++++++++++++++++++++---\n>  1 file changed, 86 insertions(+), 12 deletions(-)\n> \n> diff --git a/utils/raspberrypi/ctt/convert_tuning.py b/utils/raspberrypi/ctt/convert_tuning.py\n> index f4504d45..83cf69d4 100755\n> --- a/utils/raspberrypi/ctt/convert_tuning.py\n> +++ b/utils/raspberrypi/ctt/convert_tuning.py\n> @@ -8,30 +8,104 @@\n>  \n>  import argparse\n>  import json\n> +import numpy as np\n>  import sys\n>  \n>  from ctt_pretty_print_json import pretty_print\n> +from ctt_pisp import grid_size as grid_size_pisp\n> +from ctt_pisp import json_template as json_template_pisp\n> +from ctt_vc4 import grid_size as grid_size_vc4\n> +from ctt_vc4 import json_template as json_template_vc4\n>  \n>  \n> -def convert_v2(in_json: dict) -> str:\n> +def interp_2d(in_ls, src_w, src_h, dst_w, dst_h):\n>  \n> -    if 'version' in in_json.keys() and in_json['version'] != 1.0:\n> -        print(f'The JSON config reports version {in_json[\"version\"]} that is incompatible with this tool.')\n> -        sys.exit(-1)\n> +    out_ls = np.zeros((dst_h, dst_w))\n> +    for i in range(src_h):\n> +        out_ls[i] = np.interp(np.linspace(0, dst_w - 1, dst_w),\n> +                              np.linspace(0, dst_w - 1, src_w),\n> +                              in_ls[i])\n> +    for i in range(dst_w):\n> +        out_ls[:,i] = np.interp(np.linspace(0, dst_h - 1, dst_h),\n> +                                np.linspace(0, dst_h - 1, src_h),\n> +                                out_ls[:src_h, i])\n> +    return out_ls\n>  \n> -    converted = {\n> -        'version': 2.0,\n> -        'target': 'bcm2835',\n> -        'algorithms': [{algo: config} for algo, config in in_json.items()]\n> -    }\n>  \n> -    return pretty_print(converted)\n> +def convert_target(in_json: dict, target: str):\n> +\n> +    src_w, src_h = grid_size_pisp if target == 'vc4' else grid_size_vc4\n> +    dst_w, dst_h = grid_size_vc4 if target == 'vc4' else grid_size_pisp\n> +    json_template = json_template_vc4 if target == 'vc4' else json_template_pisp\n> +\n> +    # ALSC grid sizes\n> +    alsc = next(algo for algo in in_json['algorithms'] if 'rpi.alsc' in algo)['rpi.alsc']\n> +    for colour in ['calibrations_Cr', 'calibrations_Cb']:\n> +        if colour not in alsc:\n> +            continue\n> +        for temperature in alsc[colour]:\n> +            in_ls = np.reshape(temperature['table'], (src_h, src_w))\n> +            out_ls = interp_2d(in_ls, src_w, src_h, dst_w, dst_h)\n> +            temperature['table'] = np.round(out_ls.flatten(), 3).tolist()\n> +\n> +    if 'luminance_lut' in alsc:\n> +        in_ls = np.reshape(alsc['luminance_lut'], (src_h, src_w))\n> +        out_ls = interp_2d(in_ls, src_w, src_h, dst_w, dst_h)\n> +        alsc['luminance_lut'] = np.round(out_ls.flatten(), 3).tolist()\n> +\n> +    # Denoise blocks\n> +    for i, algo in enumerate(in_json['algorithms']):\n> +        if list(algo.keys())[0] == 'rpi.sdn':\n> +            in_json['algorithms'][i] = {'rpi.denoise': json_template['rpi.sdn'] if target == 'vc4' else json_template['rpi.denoise']}\n> +            break\n> +\n> +    # AGC mode weights\n> +    agc = next(algo for algo in in_json['algorithms'] if 'rpi.agc' in algo)['rpi.agc']\n> +    if 'channels' in agc:\n> +        for i, channel in enumerate(agc['channels']):\n> +            target_agc_metering = json_template['rpi.agc']['channels'][i]['metering_modes']\n> +            for mode, v in channel['metering_modes'].items():\n> +                v['weights'] = target_agc_metering[mode]['weights']\n> +    else:\n> +        for mode, v in agc[\"metering_modes\"].items():\n> +            target_agc_metering = json_template['rpi.agc']['channels'][0]['metering_modes']\n> +            v['weights'] = target_agc_metering[mode]['weights']\n> +\n> +    # HDR\n> +    if target == 'pisp':\n> +        for i, algo in enumerate(in_json['algorithms']):\n> +            if list(algo.keys())[0] == 'rpi.hdr':\n> +                in_json['algorithms'][i] = {'rpi.hdr': json_template['rpi.hdr']}\n> +\n> +    return in_json\n> +\n> +\n> +def convert_v2(in_json: dict, target: str) -> str:\n> +\n> +    if 'version' in in_json.keys() and in_json['version'] == 1.0:\n> +        converted = {\n> +            'version': 2.0,\n> +            'target': target,\n> +            'algorithms': [{algo: config} for algo, config in in_json.items()]\n> +        }\n> +    else:\n> +        converted = in_json\n> +\n> +    # Convert between vc4 <-> pisp targets. This is a best effort thing.\n> +    if converted['target'] != target:\n> +        converted = convert_target(converted, target)\n> +        converted['target'] = target\n> +\n> +    grid_size = grid_size_vc4[0] if target == 'vc4' else grid_size_pisp[0]\n> +    return pretty_print(converted, custom_elems={'table': grid_size, 'luminance_lut': grid_size})\n>  \n>  \n>  if __name__ == \"__main__\":\n>      parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter, description=\n> -                    'Convert the format of the Raspberry Pi camera tuning file from v1.0 to v2.0.\\n')\n> +        'Convert the format of the Raspberry Pi camera tuning file from v1.0 to v2.0 and/or the vc4 <-> pisp targets.\\n')\n>      parser.add_argument('input', type=str, help='Input tuning file.')\n> +    parser.add_argument('-t', '--target', type=str, help='Target platform.',\n> +                        choices=['pisp', 'vc4'], default='vc4')\n>      parser.add_argument('output', type=str, nargs='?',\n>                          help='Output converted tuning file. If not provided, the input file will be updated in-place.',\n>                          default=None)\n> @@ -40,7 +114,7 @@ if __name__ == \"__main__\":\n>      with open(args.input, 'r') as f:\n>          in_json = json.load(f)\n>  \n> -    out_json = convert_v2(in_json)\n> +    out_json = convert_v2(in_json, args.target)\n>  \n>      with open(args.output if args.output is not None else args.input, 'w') as f:\n>          f.write(out_json)\n> -- \n> 2.39.2\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 48F31C3237\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 13 Jun 2024 08:24:26 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 4BD026548E;\n\tThu, 13 Jun 2024 10:24:25 +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 1111865458\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 13 Jun 2024 10:24:24 +0200 (CEST)","from pendragon.ideasonboard.com\n\t(cpc89244-aztw30-2-0-cust6594.18-1.cable.virginm.net [86.31.185.195])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 152D3BEB;\n\tThu, 13 Jun 2024 10:24:10 +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=\"DwX5ECro\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1718267050;\n\tbh=Kma0RdU0ngVc47gVSquku1a6QFnqv4L1cGThodRY50E=;\n\th=In-Reply-To:References:Subject:From:Cc:To:Date:From;\n\tb=DwX5ECrodUAlIhzbIqwaOLN5vNoX1V4W33JiN3JKM1ihHRhYkmTbSnHxiBtU0pTNH\n\tKSDYZmYXu9WWQt8eZYKOSQU0s+GD0VpOGKCKQo2VaXawfHq1q3cm5MZkLrqZI4KIf3\n\t58sPlXHyyVLXPPi83i4x3AKvAOEhI647BWw+m8Z4=","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<20240606101512.375178-6-david.plowman@raspberrypi.com>","References":"<20240606101512.375178-1-david.plowman@raspberrypi.com>\n\t<20240606101512.375178-6-david.plowman@raspberrypi.com>","Subject":"Re: [PATCH 5/6] utils: raspberrypi: ctt: Add option to convert\n\tbetween vc4/pisp targets","From":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"Naushir Patuck <naush@raspberrypi.com>","To":"David Plowman <david.plowman@raspberrypi.com>,\n\tlibcamera-devel@lists.libcamera.org","Date":"Thu, 13 Jun 2024 09:24:21 +0100","Message-ID":"<171826706128.1550852.629646733026118654@ping.linuxembedded.co.uk>","User-Agent":"alot/0.10","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>"}}]