Bayer Raw Image Generator (python version)

目的

写一个脚本能生成 bayer 格式的 mipi raw / raw

(能生成一个 color bar 就够了)

  1. 支持指定输出分辨率.
  2. 支持 bayer RGGB, BGGR. (这个是我工作常接触的sensor raw format)
  3. 支持 raw10, raw12

平时工作需要,要收集不同分辨率下 camera 平台的 DDR bandwidth , CPU usage, Power consumption 的相关数据,因为没有对应分辨率大小的sensor 硬件,只能从平台接收sensor数据的链路上做文章.

所以需要一个脚本,能生成一个特定大小的mipi raw 数据,送给我们硬件,之后硬件自己解码,接着送给后级模块处理,完成整个 camera pipeline 链路, 进而收集测试数据

代码

完整代码我放github上了

https://gist.github.com/Zack4396/fd7e956b650fc52d24927f2623bcc828

用法

# 生成 ispraw 格式 (可使用 ffplay 查看)
# 内容为 1920x1080 raw10
$ python3 bayer_raw_generator.py -W 1920 -H 1080 -D 10 -F bggr -P ispraw -o raw10.raw

# 生成 mipiraw 格式 (需要特定工具查看,或者手动转换成 ispraw 后,使用ffplay 查看)
# 内容为 1280x960 raw12
$ python3 bayer_raw_generator.py -W 1280 -H 960 -D 12 -F rggb -P mipiraw -o raw12.mipiraw

代码拆分

1. raw16 转 mipiraw10 

def ispraw_to_mipiraw10(data, order):
    combo_pixel_bytes, combo_pixel_count = get_combo_pixel_bytes(pixel_depth=10)

    # raw10: 5bytes store 4 pixels
    assert combo_pixel_bytes == 5
    assert combo_pixel_count == 4

    output_data = bytearray()

    for i in range(0, len(data), combo_pixel_count * 2):
        byte = data[i : i + combo_pixel_count * 2]

        pixel_1 = int.from_bytes(byte[0:2], order)
        pixel_2 = int.from_bytes(byte[2:4], order)
        pixel_3 = int.from_bytes(byte[4:6], order)
        pixel_4 = int.from_bytes(byte[6:8], order)

        output_data.extend((pixel_1 >> 2).to_bytes(1, order))
        output_data.extend((pixel_2 >> 2).to_bytes(1, order))
        output_data.extend((pixel_3 >> 2).to_bytes(1, order))
        output_data.extend((pixel_4 >> 2).to_bytes(1, order))
        output_data.extend(
            (
                (
                    ((pixel_1 & 0x03) << 0)
                    | ((pixel_2 & 0x03) << 2)
                    | ((pixel_3 & 0x03) << 4)
                    | ((pixel_4 & 0x03) << 6)
                )
            ).to_bytes(1, order)
        )

    return output_data

2. raw16 转 mipiraw12

def ispraw_to_mipiraw12(data, order):
    combo_pixel_bytes, combo_pixel_count = get_combo_pixel_bytes(pixel_depth=12)

    # raw12: 3bytes store 2 pixels
    assert combo_pixel_bytes == 3
    assert combo_pixel_count == 2

    output_data = bytearray()
    for i in range(0, len(data), combo_pixel_count * 2):
        byte = data[i : i + (combo_pixel_count * 2)]

        pixel_1 = int.from_bytes(byte[0:2], order)
        pixel_2 = int.from_bytes(byte[2:4], order)

        output_data.extend((pixel_1 >> 4).to_bytes(1, order))
        output_data.extend((pixel_2 >> 4).to_bytes(1, order))
        output_data.extend(
            (((pixel_1 & 0x0F) << 0) | ((pixel_2 & 0x0F) << 4)).to_bytes(1, order)
        )

    return output_data

3. mipiraw10 转 raw16

def mipiraw10_to_ispraw(data, order):
    combo_pixel_bytes, combo_pixel_count = get_combo_pixel_bytes(pixel_depth=10)

    # raw10: 5bytes store 4 pixels
    assert combo_pixel_bytes == 5
    assert combo_pixel_count == 4

    output_data = bytearray()

    for i in range(0, len(data), combo_pixel_bytes):
        byte = data[i : i + combo_pixel_bytes]

        output_data.extend(
            ((byte[0] << 2) | ((byte[4] >> 0) & 0x03)).to_bytes(2, order)
        )
        output_data.extend(
            ((byte[1] << 2) | ((byte[4] >> 2) & 0x03)).to_bytes(2, order)
        )
        output_data.extend(
            ((byte[2] << 2) | ((byte[4] >> 4) & 0x03)).to_bytes(2, order)
        )
        output_data.extend(
            ((byte[3] << 2) | ((byte[4] >> 6) & 0x03)).to_bytes(2, order)
        )

    return output_data

4. mipiraw12 转 raw16

def mipiraw12_to_ispraw(input_data, order):
    combo_pixel_bytes, combo_pixel_count = get_combo_pixel_bytes(pixel_depth=12)

    # raw12: 3bytes store 2 pixels
    assert combo_pixel_bytes == 3
    assert combo_pixel_count == 2

    output_data = bytearray()

    for i in range(0, len(input_data), combo_pixel_bytes):
        byte = input_data[i : i + combo_pixel_bytes]

        output_data.extend(
            ((byte[0] << 4) | ((byte[2] >> 0) & 0x0F)).to_bytes(2, order)
        )
        output_data.extend(
            ((byte[1] << 4) | ((byte[2] >> 4) & 0x0F)).to_bytes(2, order)
        )

    return output_data

5. 生成 color bar

def generate_bayer_raw(width, height, depth, bayer_format, packed_pattern):
    order = "big"
    golden = RGGB(depth)

    assert width % 8 == 0, "width should be a multiple of 8"
    assert height % 2 == 0, "height should be a multiple of 2"

    colors = [
        golden.black(),
        golden.white(),
        golden.azure(),
        golden.yellow(),
        golden.green(),
        golden.pink(),
        golden.blue(),
        golden.red(),
    ]

    colors = reorder_color(colors, bayer_format)

    data = gen_color_doubleline(colors, width // 8, order)
    if packed_pattern == "ispraw":
        # - continuous pixel data
        # - extra-zero bit padding
        # size = width * height * 16 / 8
        assert len(data) == 2 * (
            width * 16 / 8
        ), f"oops, ispraw size is mismatch, now={len(data)}, expect={2 * (width * 16 / 8)}"
    elif packed_pattern == "mipiraw":
        # - non-continuous pixel data (need decode)
        # - non-zero bit padding
        # size = width * height * depth / 8
        if depth == 10:
            data = ispraw_to_mipiraw10(data, order)
        elif depth == 12:
            data = ispraw_to_mipiraw12(data, order)
        else:
            assert False, f"Unsupported mipiraw depth {depth}"

        assert len(data) == 2 * (
            width * depth / 8
        ), f"oops, mipiraw size is mismatch, now={len(data)}, expect={2 * (width * depth / 8)}"

    else:
        assert False, f"Unsupported packed pattern {packed_pattern}"

    return data * (height // 2)

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值