使用 OpenCV / Python 读取和保存 12 位原始拜耳图像
Reading and saving 12bit Raw bayer image using OpenCV / Python
我正在尝试使用 Python 和 openCV 读取并保存 12 位 Raw 文件。我正在使用的代码保存了一张图片,但保存的图片出现乱码/失真。
图像来自 FLIR Oryx Camera 23MP (5320x4600) 12Bit,像素格式为 BayerRG12P,应该是 RG GB 拜耳模式。
import cv2
import numpy as np
width = 5320
height = 4600
with open("aaa12packed.Raw", "rb") as rawimg:
img = np.fromfile(rawimg, np.dtype('u1'), width * height).reshape(height, width)
colimg = cv2.cvtColor(img, cv2.COLOR_BAYER_GR2RGB)
cv2.imwrite("test.jpeg", colimg)
我上传了两个用于测试 debayer/demoisaic 的原始文件。您可以使用下面的 link 下载它们:
"RG12P.Raw"(这是 12 位常规)和"RG12packed.Raw"(这是 12 位压缩)
** 我的最终目标是使用 openCV 处理包含 RAW 图像序列的文件夹,并将它们 process/convert 转换为另一种高分辨率格式,如 DPX 10 位或同等格式。
我对此很陌生 - 感谢您的帮助。
编辑#1:添加屏幕截图,其中包含 FLIR 手册中有关所用 12 位格式的信息。
Link to 12 bit channel image formats (packed and regular)
我不确定您共享的两个文件之间的区别,但这里有一个相当快速的技术来读取和解压缩 12 位样本。我不太确定你到底想要什么,所以我放了很多调试代码和注释,这样你就可以看到我在做什么,然后你就可以微调了。
不要被代码的长度拖延,我在评论中真正编号的只有 4 行:
#!/usr/bin/env python3
# Demosaicing Bayer Raw image
import cv2
import numpy as np
filename = 'RG12P.Raw'
# Set width and height
w, h = 5320, 4600
# Read entire file and reshape as rows of 3 bytes
bayer = np.fromfile(filename, dtype=np.uint8).reshape((-1,3)) # LINE 1
print(f'DEBUG: bayer.shape={bayer.shape}')
for i in 0,1,2:
print(f'DEBUG: bayer[{i}]={bayer[i]}')
# Make each 3-byte row into a single np.uint32 containing 2 samples of 12-bits each
bayer32 = np.dot(bayer.astype(np.uint32), [1,256,65536]) # LINE 2
print(f'DEBUG: bayer32.shape={bayer32.shape}')
for i in 0,1,2:
print(f'DEBUG: bayer32[{i}]={bayer32[i]}')
# Extract high and low samples from pairs
his = bayer32 >> 12 # LINE 3
los = bayer32 & 0xfff # LINE 4
print(f'DEBUG: his.shape={his.shape}')
for i in 0,1,2:
print(f'DEBUG: his[{i}]={his[i]}')
print(f'DEBUG: los.shape={los.shape}')
for i in 0,1,2:
print(f'DEBUG: los[{i}]={los[i]}')
# Stack into 3 channel
#BGR16 = np.dstack((B,G,R)).astype(np.uint16)
# Save result as 16-bit PNG
#cv2.imwrite('result.png', BGR16)
示例输出
DEBUG: bayer.shape=(12236000, 3)
DEBUG: bayer[0]=[119 209 36]
DEBUG: bayer[1]=[249 17 29]
DEBUG: bayer[2]=[ 49 114 35]
DEBUG: bayer32.shape=(12236000,)
DEBUG: bayer32[0]=2412919
DEBUG: bayer32[1]=1905145
DEBUG: bayer32[2]=2322993
DEBUG: his.shape=(12236000,)
DEBUG: his[0]=589
DEBUG: his[1]=465
DEBUG: his[2]=567
DEBUG: los.shape=(12236000,)
DEBUG: los[0]=375
DEBUG: los[1]=505
DEBUG: los[2]=561
我们可能会重复使用我在以下 中的回答。
OpenCV 不支持 DPX 10 位图像格式。
您可以使用 Tiff 格式或 16 位 PNG,但您可能需要将像素缩放 16(将 12 位放在 16 位的上部)。
代码示例:
import cv2
import numpy as np
width = 5320
height = 4600
with open("RG12P.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].
# 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.jpeg", colimg)
结果:
我正在尝试使用 Python 和 openCV 读取并保存 12 位 Raw 文件。我正在使用的代码保存了一张图片,但保存的图片出现乱码/失真。
图像来自 FLIR Oryx Camera 23MP (5320x4600) 12Bit,像素格式为 BayerRG12P,应该是 RG GB 拜耳模式。
import cv2
import numpy as np
width = 5320
height = 4600
with open("aaa12packed.Raw", "rb") as rawimg:
img = np.fromfile(rawimg, np.dtype('u1'), width * height).reshape(height, width)
colimg = cv2.cvtColor(img, cv2.COLOR_BAYER_GR2RGB)
cv2.imwrite("test.jpeg", colimg)
我上传了两个用于测试 debayer/demoisaic 的原始文件。您可以使用下面的 link 下载它们:
"RG12P.Raw"(这是 12 位常规)和"RG12packed.Raw"(这是 12 位压缩)
** 我的最终目标是使用 openCV 处理包含 RAW 图像序列的文件夹,并将它们 process/convert 转换为另一种高分辨率格式,如 DPX 10 位或同等格式。
我对此很陌生 - 感谢您的帮助。
编辑#1:添加屏幕截图,其中包含 FLIR 手册中有关所用 12 位格式的信息。
Link to 12 bit channel image formats (packed and regular)
我不确定您共享的两个文件之间的区别,但这里有一个相当快速的技术来读取和解压缩 12 位样本。我不太确定你到底想要什么,所以我放了很多调试代码和注释,这样你就可以看到我在做什么,然后你就可以微调了。
不要被代码的长度拖延,我在评论中真正编号的只有 4 行:
#!/usr/bin/env python3
# Demosaicing Bayer Raw image
import cv2
import numpy as np
filename = 'RG12P.Raw'
# Set width and height
w, h = 5320, 4600
# Read entire file and reshape as rows of 3 bytes
bayer = np.fromfile(filename, dtype=np.uint8).reshape((-1,3)) # LINE 1
print(f'DEBUG: bayer.shape={bayer.shape}')
for i in 0,1,2:
print(f'DEBUG: bayer[{i}]={bayer[i]}')
# Make each 3-byte row into a single np.uint32 containing 2 samples of 12-bits each
bayer32 = np.dot(bayer.astype(np.uint32), [1,256,65536]) # LINE 2
print(f'DEBUG: bayer32.shape={bayer32.shape}')
for i in 0,1,2:
print(f'DEBUG: bayer32[{i}]={bayer32[i]}')
# Extract high and low samples from pairs
his = bayer32 >> 12 # LINE 3
los = bayer32 & 0xfff # LINE 4
print(f'DEBUG: his.shape={his.shape}')
for i in 0,1,2:
print(f'DEBUG: his[{i}]={his[i]}')
print(f'DEBUG: los.shape={los.shape}')
for i in 0,1,2:
print(f'DEBUG: los[{i}]={los[i]}')
# Stack into 3 channel
#BGR16 = np.dstack((B,G,R)).astype(np.uint16)
# Save result as 16-bit PNG
#cv2.imwrite('result.png', BGR16)
示例输出
DEBUG: bayer.shape=(12236000, 3)
DEBUG: bayer[0]=[119 209 36]
DEBUG: bayer[1]=[249 17 29]
DEBUG: bayer[2]=[ 49 114 35]
DEBUG: bayer32.shape=(12236000,)
DEBUG: bayer32[0]=2412919
DEBUG: bayer32[1]=1905145
DEBUG: bayer32[2]=2322993
DEBUG: his.shape=(12236000,)
DEBUG: his[0]=589
DEBUG: his[1]=465
DEBUG: his[2]=567
DEBUG: los.shape=(12236000,)
DEBUG: los[0]=375
DEBUG: los[1]=505
DEBUG: los[2]=561
我们可能会重复使用我在以下
OpenCV 不支持 DPX 10 位图像格式。
您可以使用 Tiff 格式或 16 位 PNG,但您可能需要将像素缩放 16(将 12 位放在 16 位的上部)。
代码示例:
import cv2
import numpy as np
width = 5320
height = 4600
with open("RG12P.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].
# 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.jpeg", colimg)
结果: