【问题标题】:RAW 12 bits per pixel data formatRAW 12 位/像素数据格式
【发布时间】:2021-10-19 14:20:42
【问题描述】:

我正在分析每像素 12 位、GRBG、Little Endian、1920x1280 分辨率的原始图像,但我对如何存储数据或 RGB 像素感到困惑。图像大小为 4915200 字节,计算为 4915200/(1920x1280) = 2。这意味着每个像素占用 2 个字节,2 个字节中的 4 位用于填充。我试图用十六进制编辑器编辑图像,但我不知道像素是如何存储在图像中的。如果您有任何想法,请分享。

Image Link

【问题讨论】:

  • 也许可以分享图片 - 可能使用 Dropbox 或 Google Drive。
  • 如果您知道如何在 Irfanview 中查看图像,您当然可以包含一个屏幕抓图,显示 a)图像的外观和 b)您为 Irfanview 提供的数据设置/描述?如果您希望人们帮助您 - 让他们轻松! ????

标签: image image-processing


【解决方案1】:

这意味着每个像素占用 2 个字节,2 个字节中的 4 位用于填充

嗯,有点。这意味着每个 sample 存储在两个连续的字节中,并带有 4 位填充。但在原始图像中,样本通常不是像素,也不完全是像素。原始图像还没有去马赛克,毕竟它们是原始的。对于 GRGB,拜耳模式如下所示:

文件中的内容是一个 1920x1280 的 12+4 位样本网格,排列顺序与像素的顺序相同,但每个样本只有一个通道,即与其在拜耳模式中的位置相对应的通道.

此外,色彩空间可能是线性的,而不是 Gamma 压缩的。除非您对其进行逆向工程,否则色彩平衡是未知的。一个合适的解码器会有一个校准的颜色矩阵,但我没有。

我把这两件事结合起来,猜了一个色彩平衡来做一个非常基本的解码(去马赛克不好,只是为了证明上面的信息可能是准确的):

使用此 C# 代码:

    Bitmap bm = new Bitmap(1920, 1280);        
    for (int y = 0; y < 1280; y += 2)
    {
        int i = y * 1920 * 2;
        for (int x = 0; x < 1920; x += 2)
        {
            const int stride = 1920 * 2;
            int d0 = data[i] + (data[i + 1] << 8);
            int d1 = data[i + 2] + (data[i + 3] << 8);
            int d2 = data[i + stride] + (data[i + stride + 1] << 8);
            int d3 = data[i + stride + 2] + (data[i + stride + 3] << 8);
            i += 4;
            int r = Math.Min((int)(Math.Sqrt(d1) * 4.5), 255);
            int b = Math.Min((int)(Math.Sqrt(d2) * 9), 255);
            int g0 = Math.Min((int)(Math.Sqrt(d0) * 5), 255);
            int g3 = Math.Min((int)(Math.Sqrt(d3) * 5), 255);
            int g1 = Math.Min((int)(Math.Sqrt((d0 + d3) * 0.5) * 5), 255);
            bm.SetPixel(x, y,         Color.FromArgb(r, g0, b));
            bm.SetPixel(x + 1, y,     Color.FromArgb(r, g1, b));
            bm.SetPixel(x, y + 1,     Color.FromArgb(r, g1, b));
            bm.SetPixel(x + 1, y + 1, Color.FromArgb(r, g3, b));
        }
    }

【讨论】:

  • 谢谢@harold。我知道如何查看图像的内容。我使用Irfanview 来查看去马赛克图像。但我的问题是如何存储像素或数据的模式(GRBG)。我试图分析你的代码,但我很困惑。假设我想创建一个 12bpp、2x2 的原始图像,第一种颜色为红色,其余为白色。那么十六进制数据将是 | 0F 00 | FF FF | FF FF | FF FF |。但是当我将这些数据放入 Irfanview(RAW 图像查看器)时,图像并不是预期的那样。
  • @saivamsi 您提出的方案对我来说毫无意义,左上角的示例根据定义是绿色的。您不能像图像是普通位图一样独立选择每个像素的颜色。 GRBG 不是指对样本中十六进制数字的解释,而是指样本的模式。
  • 我明白了。我在想 RGB 颜色组合存储在 12 位中。我对每个像素的位数感到困惑,实际上是每种颜色的位数。谢谢@harold 的解释和代码。
【解决方案2】:

您可以将图像加载到 Numpy 数组中并像这样正确重塑:

import numpy as np

# Load image and reshape
img = np.fromfile('Image_12bpp_grbg_LittleEndian_1920x1280.raw',dtype=np.uint16).reshape((1280,1920))

print(img.shape)
(1280, 1920)

然后你可以去马赛克和缩放以获得一个 16 位的 PNG。请注意,我不知道您的校准系数,所以我猜测:

#!/usr/bin/env python3
# Demosaicing Bayer Raw image
# https://stackoverflow.com/a/68823014/2836621

import cv2
import numpy as np

filename = 'Image_12bpp_grbg_LittleEndian_1920x1280.raw'

# Set width and height
w, h = 1920, 1280

# Read mosaiced image as GRGRGR...
#                        BGBGBG...
bayer = np.fromfile(filename, dtype=np.uint16).reshape((h,w))

# Extract g0, g1, b, r from mosaic
g0 = bayer[0::2, 0::2]      # every second pixel down and across starting at 0,0
g1 = bayer[1::2, 1::2]      # every second pixel down and across starting at 1,1
r  = bayer[0::2, 1::2]      # every second pixel down and across starting at 0,1
b  = bayer[1::2, 0::2]      # every second pixel down and across starting at 1,0

# Apply (guessed) color matrix for 16-bit PNG
R = np.sqrt(r) * 1200
B = np.sqrt(b) * 2300
G = np.sqrt((g0+g1)/2) * 1300    # very crude

# Stack into 3 channel
BGR16 = np.dstack((B,G,R)).astype(np.uint16)

# Save result as 16-bit PNG
cv2.imwrite('result.png', BGR16)

关键字:Python、raw、图像处理、Bayer、de-Bayer、马赛克、去马赛克、去马赛克、GBRG、12 位。

【讨论】:

    猜你喜欢
    • 2020-11-25
    • 1970-01-01
    • 2017-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-21
    • 1970-01-01
    • 2020-01-06
    相关资源
    最近更新 更多