Python:将 RAW 图像转换为 PNG
我正在努力使用 Python 处理原始图像以将其转换为 png 格式。 处理这些类型的数据对我来说是新的,我还不太理解其中的逻辑。
图像数据(根据相机文档)是 12 位、具有拜耳模式的小端序。 图像尺寸为 2048x1944 像素。 图片位于此处。
我在这里遵循了@Rotem的答案,但是我的图像get 基本上只是噪音。代码如下。
关于如何解决这个问题有什么想法吗?
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)
I am struggling with processing a raw image with Python to convert it to png format.
Processing these type of data is new to me and I don't quite understand the logic yet.
The image data (as per the camera doc) is 12 bit, little-Endian order with a Bayer pattern.
The image is 2048x1944 px.
Image available here.
I have followed @Rotem answer in here but the image I get is basically just noise. Code below.
Any idea on how to approach this?
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)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您发布的原始图像为每像素 12 位,但未打包。
12位数据存储在每16位的高12位中。
我们可以通过文件的大小看到,每个像素有 2 个字节:
7962624 = 2048*1944*2
我们可以将
uint16
元素中的 12 位数据表示如下:与 12 位打包格式相比,这种格式使用起来要简单得多...
我们不需要解压数据,我们可以将其视为每像素 16 位。
代码示例:
我们可以看到,这是一张月亮的图片:

月亮不是最佳选择,因为我们无法验证颜色的正确性...
注意:
我“手动”放大了红色和蓝色通道,使月亮变成灰色(而不是绿色)。
我们可以将缩放称为手动白平衡。
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
We may represent the 12 bits data in
uint16
element as follows: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.
Code sample:
We can see, it's a picture of the moon:

The moon is not the best choice, because we can't verify the correctness of the colors...
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.