Almost all digital camera sensors are organized in a grid of photosensors. Each photo sensor is sensitive for one of the primary colors: red, green and blue. The way those photo sensors are organized is called the Bayer filter, after its inventor, Bryce Bayer of Eastman Kodak. After an image is taken, four photo sensors compose the RGB value of one pixel in the resulting image. Your task is to reverse that process and colorize the resulting pixels according to their filter color. For the sake of simplicity, we will ignore gamma correction.

For example: the "normal" forward Bayer filter steps are:

  • a lightray with a Pantone Beeswax color hits the sensor;
  • the BGGR (Blue - Green / Green - Red) filter decomposes this into four rays.
  • The four rays hit the sensor, which reads: 81 - 168 / 168 - 235 (sensor values range from 0 - 255);
  • The Bayer filter translates this to one RGB pixel with color (235, 168, 81).

The reverse Bayer filter steps are:

  • RGB pixel with color (235, 168, 81) is split into four pixels with RGB values: (0,0,81) - (0,168,0) / (0,168,0) - (235,0,0).

Challenge

You should write the shortest possible function or program that does the following:

  • Take a filename as in input and output the DeBayered image.
  • The output may be written to a file or displayed on the screen.
  • The output must be twice the width and twice the height of the original image.
  • Each pixel of the input image must be mapped according to the BGGR (Blue - Green / Green - Red) Bayer filter pattern as explained graphically in the following picture:

    Bayer Filter - BGGR - graphical explanation

  • We'll assume that both green photosensors receive the same signal, so both the G values in the Bayer matrix are equal to the G value in the RGB image.

  • You may not return an array representation of the resulting image. The output must be an image or a file (in any suitable image format) that can be displayed as an image.

Example

Given this file as an input:

Mona Lisa

The resulting image should be:

DeBayered Mona Lisa

Reference python implementation:

from PIL import Image
import numpy
import sys

if len(sys.argv) == 1:
    print "Usage: python DeByer.py <<image_filename>>"
    sys.exit()

# Open image and put it in a numpy array
srcArray = numpy.array(Image.open(sys.argv[1]), dtype=numpy.uint8)
w, h, _ = srcArray.shape

# Create target array, twice the size of the original image
resArray = numpy.zeros((2*w, 2*h, 3), dtype=numpy.uint8)

# Map the RGB values in the original picture according to the BGGR pattern# 

# Blue
resArray[::2, ::2, 2] = srcArray[:, :, 2]

# Green (top row of the Bayer matrix)
resArray[1::2, ::2, 1] = srcArray[:, :, 1]

# Green (bottom row of the Bayer matrix)
resArray[::2, 1::2, 1] = srcArray[:, :, 1]

# Red
resArray[1::2, 1::2, 0] = srcArray[:, :, 0]

# Save the imgage
Image.fromarray(resArray, "RGB").save("output.png")

Remember: this is a , so shortest code wins!

  • 5
    Nearly got a seizure when I scrolled – Fatalize Jul 23 '16 at 17:26
  • 1
    @Fatalize sorry for that! ;-) Weird effect, isn't it? – agtoever Jul 23 '16 at 18:10
  • The instructions show a cell with BG on the top row and GR on the bottom, while the example image shows RG on top and GB on the bottom. Does that mean any arrangement that puts the two green cells on a diagonal is acceptable? (the others would be GB / RG and GR / BG.) – Level River St Jul 23 '16 at 20:02
  • @LevelRiverSt my intention was to adhere to BGGR (as specified in the fourth challenge bullet). My mistake if the actual example image is in RGGB. I'll correct that as soon as I'm on my laptop. – agtoever Jul 23 '16 at 20:26
  • I don't think your example image is correct, for one it has a weird blue tint – orlp Jul 24 '16 at 6:11
up vote 6 down vote accepted

Pyth, 26 bytes

MXm03H@GH.wsMsgLRRR,U2tU3'

Expects the input filename with quotation marks on stdin, and writes to o.png. Example output:

  • You answer is the shortest so far. I tend to accept it, but it would be nice if you could add an explanation how your program works. – agtoever Jul 30 '16 at 18:51
  • I just used the Kronecker product, using an answer from a previous question: codegolf.stackexchange.com/questions/78797/…. – orlp Jul 30 '16 at 21:36

Matlab, 104 92 bytes

This makes use of the 3d-array/matrix representation of RGB images in Matlab, as well as the Kronecker product which is exactly what we need creating this new 2x2 "metapixel" form each source pixel. The output is then displayed in a popup window.

a=double(imread(input('')));for n=1:3;b(:,:,n)=kron(a(:,:,n),[1:2;2:3]==n)/255;end;imshow(b)

Resized screencapture:

  • That [1:2;2:3]==n is clever! Can't you remove b=[a,a;a,a];? – Luis Mendo Jul 24 '16 at 2:57
  • @LuisMendo Thanks=) It does indeed work, I didn't expect that! – flawr Jul 24 '16 at 8:20

Python 3, 259 254 bytes

from PIL.Image import*
o=open(input())
w,h=o.size
n=new('RGB',(2*w,2*h))
P=Image.putpixel
for b in range(w*h):x=b//h;y=b%h;r,g,b=o.getpixel((x,y));c=2*x;d=2*y;G=0,g,0;P(n,(c,d),(0,0,b));P(n,(c+1,d),G);P(n,(c,d+1),G);P(n,(c+1,d+1),(r,0,0))
n.save('o.png')

The input filename is given in standard input. Outputs to o.png.

Example usage:

$ echo mona-lisa.jpg | python bayer.py

Mona Lisa with reverse Bayer filter applied

  • 2
    Welcome to PPCG, nice first answer! – Leaky Nun Jul 24 '16 at 12:09

Mathematica 118 127 bytes

The original submission used an actual picture as input. This uses a filename instead.

It applies two replacement rules to the image data of the referenced file:

  1. For each row of the image data matrix,replace each pixel {r,b,g} with a blue pixel, {0,0,b} followed by a green pixel, {0,g,0};
  2. Separately, for each row of the image data matrix, replace each pixel {r,b,g} with a green pixel {0,g,0} followed by a red pixel, {r,0,0};

Then Riffle (i.e. interleave) the matrices resulting from 1 and 2.

Image[Riffle[#/.{{_,g_,b_}:>(s=Sequence)[{0,0,b},{0,g,0}]}&/@(m=Import[#,"Data"]/255),#/.{{r_,g_,_}:>s[{0,g,0},{r,0,0}]}&/@m]]&

Image[Riffle[#/.{{_,g_,b_}:>(s=Sequence)[{0,0,b},{0,g,0}]}&/@(m=Import[#,"Data"]/255),#/.{{r_,g_,_}:>s[{0,g,0},{r,0,0}]}&/@m]]&["mona.jpg"]

reverse bayer

  • Not sure, but this doesn't seem to satisfy "Take a filename as in input" – agtoever Jul 24 '16 at 6:14
  • agtoever, It now uses as input a filename instead of an image. – DavidC Jul 24 '16 at 18:47

J, 100 96 90 bytes

load'bmp'
'o'writebmp~,./,./($a)$2 1 1 0(_2]\(2^0 8 8 16)*{)"1(3#256)#:,a=:readbmp]stdin''

This is a script in J that reads the filename of the input image from stdin and outputs the result to a file named o. The input and output images will both be in bmp format. It also expects only the filename to be input, meaning that leading and trailing whitespace should not be present.

Sample Usage

$ echo -n mona.bmp | jconsole reversebayer.ijs

Sample

Explanation

A=:readbmp]stdin''  Store the image in A as a 2d array of 24-bit rgb ints
,                   Flatten it into a list
(3#256) #:          Convert each 24-bit int to a tuple of 8-bit r/g/b ints
2 1 1 0 {"1         Select each column in BGGR order
(2^0 8 8 16) *      Shift each color to make it a 24-bit rgb value
_2 ]\               Convert each row from dimensions 1x4 to 2x2
($A) $              Reshape the list of 2x2 matrices into a matrix of
                    2x2 matrices with dimensions matching A
,./                 Append the 2x2 matrices by column
,./                 Append the 2x2 matrices by row - This is now a matrix of
                     24-bit rgb values with twice the dimensions of A
'o'writebmp~        Write the image array to a bmp file named 'o'

Python 2, 256 275 bytes

First I simplified the original code:

from PIL import Image
from numpy import*
import sys

# Open image and put it in a numpy array
srcArray = array(Image.open(sys.argv[1]), dtype=uint8)
w, h, _ = srcArray.shape

# Create target array, twice the size of the original image
resArray = zeros((2*w, 2*h, 3), dtype=uint8)

# Map the RGB values in the original picture according to the BGGR pattern# 

# Blue
resArray[::2, ::2, 2] = srcArray[:, :, 2]

# Green (top row of the Bayer matrix)
resArray[1::2, ::2, 1] = srcArray[:, :, 1]

# Green (bottom row of the Bayer matrix)
resArray[::2, 1::2, 1] = srcArray[:, :, 1]

# Red
resArray[1::2, 1::2, 0] = srcArray[:, :, 0]

# Save the imgage
Image.fromarray(resArray, "RGB").save("o.png")

Then minify to:

from PIL import Image
from numpy import*
import sys
a=array(Image.open(sys.argv[1]),dtype=uint8)
w,h,_=a.shape
b=zeros((2*w,2*h,3),dtype=uint8)
b[::2,::2,2]=a[:,:,2]
b[1::2,::2,1]=a[:,:,1]
b[::2,1::2,1]=a[:,:,1]
b[1::2,1::2,0]=a[:,:,0]
Image.fromarray(b,"RGB").save("o.png")

Resulting in the image o.png:

o.png image after processing

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.