我正在努力用Python处理原始图像,将其转换为png格式.

图像数据(根据相机文档)是12位的小端序,带有拜耳模式.

我在here年里一直在关注@Rotem answer,但我得到的图像基本上只是噪音.代码如下.

你知道怎么做吗?

import cv2
import numpy as np

width = 2048
height = 1944

with open('.raw_image.raw', "rb") as rawimg:
    # Read the packed 12bits as bytes - each 3 bytes applies 2 pixels
    data = np.fromfile(rawimg, np.uint8, width * height * 3//2)

    data = data.astype(np.uint16)  # Cast the data to uint16 type.
    result = np.zeros(data.size*2//3, np.uint16)  # Initialize matrix for storing the pixels.

    # 12 bits packing: ######## ######## ########
    #                  | 8bits| | 4 | 4  |  8   |
    #                  |  lsb | |msb|lsb |  msb |
    #                  <-----------><----------->
    #                     12 bits       12 bits
    result[0::2] = ((data[1::3] & 15) << 8) | data[0::3]
    result[1::2] = (data[1::3] >> 4) | (data[2::3] << 4)
    bayer_im = np.reshape(result, (height, width))

    # Apply Demosacing (COLOR_BAYER_BG2BGR gives the best result out of the 4 combinations).
    bgr = cv2.cvtColor(bayer_im, cv2.COLOR_BAYER_BG2BGR)  # The result is BGR format with 16 bits per pixel and 12 bits range [0, 2^12-1].
    # bgr = cv2.cvtColor(bayer_im, cv2.COLOR_BayerGB2BGR)  # The result is BGR format with 16 bits per pixel and 12 bits range [0, 2^12-1].
    # bgr = cv2.cvtColor(bayer_im, cv2.COLOR_BayerRG2BGR)  # The result is BGR format with 16 bits per pixel and 12 bits range [0, 2^12-1].
    # bgr = cv2.cvtColor(bayer_im, cv2.COLOR_BayerGR2BGR )  # The result is BGR format with 16 bits per pixel and 12 bits range [0, 2^12-1].

    # Show image for testing (multiply by 16 because imshow requires full uint16 range [0, 2^16-1]).
    cv2.imshow('bgr', cv2.resize(bgr*16, [width//10, height//10]))
    cv2.waitKey()
    cv2.destroyAllWindows()

    # Convert to uint8 before saving as JPEG (not part of the conversion).
    colimg = np.round(bgr.astype(float) * (255/4095))
    cv2.imwrite("./test.png", colimg)

推荐答案

The raw image you have posted is 12 bit per pixel but without packing.
The 12 bits data are stored in the higher 12 bits of every 16 bits.

We can see by the size of the file, that there are 2 bytes per pixel:
7962624 = 2048*1944*2

我们可以用uint16个元素表示12位数据,如下所示:

 ------------------------------------------------------------------------------- 
|    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |
| b11| b10| b9 | b8 | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 |  0 |  0 |  0 |  0 |
 -------------------------------------------------------------------------------

This format is much more simple to work with compared to the 12 bits packed format...
We don't need to unpack the data, we may look at it as 16 bits per pixel.


代码示例:

import cv2
import numpy as np

width = 2048
height = 1944

with open("raw_image.ims_rgb", "rb") as rawimg:
    # Read the raw image as uint16 (two bytes per pixel).
    bayer_im = np.fromfile(rawimg, np.uint16, width * height).reshape(height, width)

    # The 12 bits of each pixel are stored in the upper 12 bits of every uint16 element.
    # The lower 4 bits of the uint16 element are zeros.
    # <--- 16 bits -->
    # ************0000
    # <-12 bits -><4->    
    #    data     zeros

    # Apply Demosacing.
    # It look like COLOR_BAYER_BG2BGR gives the best result, but it hard to tell from the given input.
    bgr = cv2.cvtColor(bayer_im, cv2.COLOR_BAYER_BG2BGR)  # The result is BGR format with 16 bits per pixel range [0, 2^16-1].

    # Apply manual "white balance".
    # The result image is greenish - this is normal for most cameras.
    # We may fix it by scaling up the red and the blue color channels.
    # It look like approximate scaling is about 1.5 for the red and about 1.25 for the blue.
    bgr[:, :, 0] = (bgr[:, :, 0].astype(np.float32)*1.25).clip(0, 65535).astype(np.uint16)
    bgr[:, :, 2] = (bgr[:, :, 2].astype(np.float32)*1.5).clip(0, 65535).astype(np.uint16)


    # Show image for testing (multiply by 16 because imshow requires full uint16 range [0, 2^16-1]).
    cv2.imshow('bgr', cv2.resize(bgr, [width//10, height//10]))
    cv2.waitKey()
    cv2.destroyAllWindows()

    # Save the output as tiff with 16 bits per color component.
    cv2.imwrite("rgb16.tif", bgr)

We can see, it's a picture of the moon:
enter image description here

月亮不是最好的 Select ,因为我们无法验证 colored颜色 的正确性...

Note:
I "manually" scaled up the red and the blue color channels to make the moon gray (instead of green).
We may refer the scaling as manual White Balance.

Python相关问答推荐

Pandas 群内滚动总和

Python中两个矩阵的自定义Hadamard风格产物

使用imap-tools时错误,其邮箱地址包含域名中的非默认字符

跟踪我已从数组中 Select 的样本的最有效方法

如何计算列表列行之间的公共元素

如何从具有多个嵌入选项卡的网页中Web抓取td类元素

Polars比较了两个预设-有没有方法在第一次不匹配时立即失败

重新匹配{ }中包含的文本,其中文本可能包含{{var}

追溯(最近最后一次调用):文件C:\Users\Diplom/PycharmProject\Yolo01\Roboflow-4.py,第4行,在模块导入roboflow中

scikit-learn导入无法导入名称METRIC_MAPPING64'

删除字符串中第一次出现单词后的所有内容

如何在Python脚本中附加一个Google tab(已经打开)

ODE集成中如何终止solve_ivp的无限运行

海上重叠直方图

如何根据一列的值有条件地 Select 前N个组,然后按两列分组?

当递归函数的返回值未绑定到变量时,非局部变量不更新:

Python导入某些库时非法指令(核心转储)(beautifulsoup4."" yfinance)

实现神经网络代码时的TypeError

在pandas数据框中计算相对体积比指标,并添加指标值作为新列

(Python/Pandas)基于列中非缺失值的子集DataFrame