简体   繁体   中英

Reading and saving 12bit Raw bayer image using OpenCV / Python

I'm trying to read and save a 12bit Raw file using Python and openCV. The code I'm using saves an image but the saved image is garbled / distorted.

The image is from a FLIR Oryx Camera 23MP (5320x4600) 12Bit with BayerRG12P pixelformat, which should be RG GB bayer pattern.

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)

I uploaded two raw files that I'm using to test the debayer/demoisaic. You can download them using the link below:

"RG12P.Raw" (this is the 12bit regular) and "RG12packed.Raw" (this is the 12bit packed)

Raw files download

** My end goal is to use openCV to process folders containing RAW image sequences and process/convert them to another high resolution format like DPX 10bit or equivalent.

I'm very new to this - any help is appreciated.

EDIT#1: Adding screenshot with information from FLIR manual about the 12bits formats used.

Link to 12 bit channel image formats (packed and regular)

We may reuse my answer from the following post .

OpenCV doesn't support DPX 10bit image format.
You may use Tiff format or 16 bits PNG, but you may need to scale the pixels by 16 (placing the 12 bits in the upper part of the 16 bits).


Code sample:

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)

Result:
在此处输入图像描述

I'm not sure of the difference between the two files you shared, but here is a fairly speedy technique to read and unpack the 12-bit samples. I am not really sure what you actually want so I have put plenty of debug code and comments so you can see what I am doing then you can fine-tune.

Don't be put off by the length of the code, there are only really 4 lines which I have numbered in comments:

#!/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)

Sample Output

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM