Convert RGB to RAW

Basic
Color spaces
kornia.color
In this tutorial we are going to learn how to convert image from raw color using kornia.color.
Author

Oskar Flordal

Published

October 13, 2021

Open in google colab

Download necessary files and libraries

%%capture
!pip install kornia
!pip install rawpy
import io

import requests


def download_image(url: str, filename: str = "") -> str:
    filename = url.split("/")[-1] if len(filename) == 0 else filename
    # Download
    bytesio = io.BytesIO(requests.get(url).content)
    # Save file
    with open(filename, "wb") as outfile:
        outfile.write(bytesio.getbuffer())

    return filename


url = "https://docs.google.com/uc?export=download&id=1nSM_FYJ7i9-_57ecPY5sCG2s8zt9dRhF"
download_image(url, "raw.dng")
'raw.dng'

Import necessary libraries

import kornia
import matplotlib.pyplot as plt
import numpy as np
import rawpy
import torch

Prepare the raw file through rawpy

path = "raw.dng"
raw = rawpy.imread(path)
cfa = "".join([chr(raw.color_desc[i]) for i in raw.raw_pattern.flatten()])

# Figure out which cfa we are using by looking at the component order from rawpy
# if we do this directly from a camera this would of course be known ahead
# of time
if cfa == "GRBG":
    korniacfa = kornia.color.CFA.GB
elif cfa == "GBRG":
    korniacfa = kornia.color.CFA.GR
elif cfa == "BGGR":
    korniacfa = kornia.color.CFA.RG
elif cfa == "RGGB":
    korniacfa = kornia.color.CFA.BG

# This is a GB file i.e. top left pixel is Green follow by Red (and the pair
# starting at (1,1) is Green, Blue)
print(cfa)
print(korniacfa)
GRBG
CFA.GB

Get the data into kornia by doing the conversion

# We find the data inside raw.raw_image
rawdata = raw.raw_image
# white level gives maximum value for a pixel
rawtensor = torch.Tensor(rawdata.astype(np.float32) / raw.white_level).reshape(
    1, 1, raw.raw_image.shape[0], raw.raw_image.shape[1]
)
rgbtensor = kornia.color.raw.raw_to_rgb(rawtensor, korniacfa)

Visualize

npimg = np.moveaxis(np.squeeze((rgbtensor * 255.0).numpy().astype(np.uint8)), 0, 2)
plt.figure()

# Show the image
# Colors will look a little funky because they need to be balanced properly, but
# the leaves are supposed to be redm berries blue and grass green
plt.imshow(npimg)

Gotchas: Rotation gives a different cfa

# if we do a pipeline were we first rotate the image, it will end up with a
# different cfa that isn't possible to describe since we are assuming all red
# samples are on t.he same row while they would not be rotated
rgbtensor = kornia.color.raw.raw_to_rgb(torch.rot90(rawtensor, 1, [2, 3]), korniacfa)
npimg = np.moveaxis(np.squeeze((rgbtensor * 255.0).numpy().astype(np.uint8)), 0, 2)
plt.figure()
plt.imshow(npimg)

# If we crop, we can adjust for this by using a different cfa
rgbtensor = kornia.color.raw.raw_to_rgb(rawtensor[:, :, 1:1023, 1:1023], kornia.color.raw.CFA.GR)
npimg = np.moveaxis(np.squeeze((rgbtensor * 255.0).numpy().astype(np.uint8)), 0, 2)
plt.figure()
plt.imshow(npimg)