Darkroom

Try Darkroom Online

Getting Started

Publications

Try Darkroom

import "darkroom" darkroomSimple = terralib.require("darkroomSimple") I = darkroomSimple.load("color.bmp") I = im(x,y) [float[3]](I) end bx = im(x,y) (I(x-1,y) + I(x,y) + I(x+1,y))/3 end by = im(x,y) (bx(x,y-1) + bx(x,y) + bx(x,y+1))/3 end difference = im(x,y) I(x,y)-by(x,y) end scaled = im(x,y) 4.0 * difference(x,y) end -- strength sharpened = im(x,y) I(x,y) + scaled(x,y) end -- clamp result = im(x,y) darkroom.vectorSelect(sharpened>255, [float[3]](255), sharpened) end result = im(x,y) darkroom.vectorSelect(result<0, [uint8[3]](0), [uint8[3]](result)) end result:save(arg[1])
import "darkroom" darkroomSimple = terralib.require("darkroomSimple") a = darkroomSimple.load("color.bmp") im a(x,y) [float[3]]( a(x,y) ) end im blurx(x,y) map i=-5,5 reduce(sum) a(x+i,y)/11 end end im blurx(x,y) [uint8[3]]( blurx ) end -- convert to 24 bit blurx:save(arg[1]) -- write to arg[1] to display
import "darkroom" darkroomSimple = terralib.require("darkroomSimple") -- simple, totally fixed function camera pipeline function blackLevel( in1, pedestal ) local rescale = 255/(255-pedestal) return im(x,y) (in1-pedestal)*rescale end end -- input = uint8 nxm -- output = RGB8 nxm function bilinearDemosaic(in1) -- most sensors are bayer, but some of them might be offset by a pixel in x or y -- remember, the origin is at the bottom left, x,y increasing to the right local xoff = 0 local yoff = 0 return im dem(x,y) out = [uint8[3]](0) -- build the red channel r_tr_a = in1(x,y+1) r_tr_b = in1(x,y-1) r_tr = (r_tr_a+r_tr_b)/[uint8](2) r_bl_a = in1(x-1,y) r_bl_b = in1(x+1,y) r_bl = (r_bl_a+r_bl_b)/[uint8](2) r_tl_a = in1(x+1,y+1) r_tl_b = in1(x-1,y-1) r_tl_c = in1(x-1,y+1) r_tl_d = in1(x+1,y-1) r_tl = (r_tl_a+r_tl_b+r_tl_c+r_tl_d)/[uint8](4) phase = {x+xoff,y+yoff}%2 out_r = if darkroom.arrayAnd(phase=={1,1}) then in1(x,y) else if darkroom.arrayAnd(phase=={0,1}) then r_bl else if darkroom.arrayAnd(phase=={1,0}) then r_tr else r_tl end end end -- build green g_tl_a = in1(x+1,y) g_tl_b = in1(x-1,y) g_tl_c = in1(x,y+1) g_tl_d = in1(x,y-1) g_tl = ( g_tl_a + g_tl_b + g_tl_c + g_tl_d )/[uint8](4) g_br_a = in1(x+1,y) g_br_b = in1(x-1,y) g_br_c = in1(x,y+1) g_br_d = in1(x,y-1) g_br = (g_br_a+g_br_b+g_br_c+g_br_d)/[uint8](4) out_g = if darkroom.arrayAnd(phase=={0,0}) then g_tl else if darkroom.arrayAnd(phase=={1,1}) then g_br else in1(x,y) end end -- build blue b_bl_a = in1(x,y+1) b_bl_b = in1(x,y-1) b_bl = (b_bl_a+b_bl_b)/[uint8](2) b_tr_a = in1(x-1,y) b_tr_b = in1(x+1,y) b_tr = (b_tr_a+b_tr_b)/[uint8](2) b_br_a = in1(x+1,y+1) b_br_b = in1(x-1,y-1) b_br_c = in1(x-1,y+1) b_br_d = in1(x+1,y-1) b_br = (b_br_a+b_br_b+b_br_c+b_br_d)/[uint8](4) out_b = if darkroom.arrayAnd(phase=={0,0}) then in1(x,y) else if darkroom.arrayAnd(phase=={0,1}) then b_bl else if darkroom.arrayAnd(phase=={1,0}) then b_tr else b_br end end end; in {out_r, out_g, out_b} end end -- input = RGB8 demosaiced -- output = RGB8 color/white balance corrected ccm={ {255/142,0,0}, {0, 196/255, 0}, {0,0,1}} function doccm(in1) return im(x,y) { darkroom.dot(in1(x,y),[ccm[1]]), darkroom.dot(in1(x,y),[ccm[2]]), darkroom.dot(in1(x,y),[ccm[3]])} end end function tonemap(in1, gamma) return im(x,y) darkroom.pow((in1(x,y)/255),gamma)*255 end end function campipe(in1) -- do the campipe using floats local im out(x,y) [float](in1(x,y)) end local out = blackLevel(out, 10) out = bilinearDemosaic(out) out = doccm(out) out = tonemap(out, 1/2.4) return im(x,y) [uint8[3]]( darkroom.vectorSelect(out>255,[uint8[3]](255),out) ) end end sensor = darkroomSimple.load("300d.bmp") campipeline = campipe(sensor) campipeline:save(arg[1])
import "darkroom" darkroomSimple = terralib.require "darkroomSimple" -- brute force optical flow searchWindowRadius = 2 SADWindowRadius = 2 local frame1 = darkroomSimple.load("frame10.bmp") frame1 = im(x,y) [int](frame1) end local frame2 = darkroomSimple.load("frame11.bmp") frame2 = im(x,y) [int](frame2) end im bruteofVectorField(x,y) map i=-searchWindowRadius, searchWindowRadius j=-searchWindowRadius, searchWindowRadius reduce(argmin) -- sum of absolute differences (SAD) map ii=-SADWindowRadius, SADWindowRadius jj=-SADWindowRadius, SADWindowRadius reduce(sum) darkroom.abs(frame1(x+ii,y+jj)-frame2(x+i+ii,y+j+jj)) end end end -- convert this to an RGB image so that the user can view it im ofRGB(x,y) [uint8[3]]({(bruteofVectorField(x,y)[0])*50+128, (bruteofVectorField(x,y)[1])*50+128, 0}) end ofRGB:save(arg[1])
import "darkroom" darkroomSimple = terralib.require("darkroomSimple") terralib.require "bilinear" windowRadius = 2 iterations = 1 -- iterations per level maxResampleX = 10 maxResampleY = 10 clamp = true function invert2x2( matrix ) local im denom(x,y) matrix[0]*matrix[3]-matrix[1]*matrix[2] end local im det(x,y) if denom(x,y)~=0 then 1/denom(x,y) else 0 end end return im(x,y) {det*matrix[3], -det*matrix[1], -det*matrix[2], det*matrix[0]} end end -- see here for ref: http://www.cs.ucf.edu/~mikel/Research/Optical_Flow.htm function makeLK(frame1, frame2) -- calculate stuff that we will use every iteration -- such as derivatives, matrix A^-1 of image gradients, weights. -- were calling frame1 F and frame2 G, as in the original LK paper -- calculate derivatives local im Fdx(x,y) (frame1(x+1,y)-frame1(x-1,y))/2 end local im Fdy(x,y) (frame1(x,y+1)-frame1(x,y-1))/2 end local im Gdx(x,y) (frame2(x+1,y)-frame2(x-1,y))/2 end local im Gdy(x,y) (frame2(x,y+1)-frame2(x,y-1))/2 end -- calculate A^-1 local im A(x,y) map wx = -windowRadius, windowRadius wy = -windowRadius, windowRadius reduce(sum) {Fdx(x+wx,y+wy)*Fdx(x+wx,y+wy), Fdx(x+wx,y+wy)*Fdy(x+wx,y+wy), Fdx(x+wx,y+wy)*Fdy(x+wx,y+wy), Fdy(x+wx,y+wy)*Fdy(x+wx,y+wy)} end end local Ainv = invert2x2(A) -- initial condition: no offset local im vectorField(x,y) [float[2]]({0,0}) end -- do LK calculation for i=1,iterations do local G = im(x,y) [resampleBilinear( clamp, frame2, maxResampleX, maxResampleY, im(x,y) vectorField[0] end, im(x,y) vectorField[1] end)] end im vectorField(x,y) -- loop over search window b = map wx = -windowRadius, windowRadius wy = -windowRadius, windowRadius reduce(sum) F = frame1 (x+wx, y+wy) in {Fdx(x+wx, y+wy)*(G(x+wx,y+wy)-F),Fdy(x+wx, y+wy)*(G(x+wx,y+wy)-F)} end in {Ainv[0](x,y)*(-b[0])+Ainv[1](x,y)*(-b[1])+vectorField[0], Ainv[2](x,y)*(-b[0])+Ainv[3](x,y)*(-b[1])+vectorField[1]} end end return im(x,y) [uint8[3]]({(vectorField(x,y)[0])*50+128, (vectorField(x,y)[1])*50+128, 0}) end end local frame1 = darkroomSimple.load("frame10.bmp") im frame1(x,y) [float](frame1) end local frame2 = darkroomSimple.load("frame11.bmp") im frame2(x,y) [float](frame2) end makeLK( frame1, frame2 ):save(arg[1])
import "darkroom" darkroomSimple = terralib.require("darkroomSimple") fusedIter = 5 function tofloat(input) return im(x,y) [float[3]](input(x,y)/([float](255))) end end function tobyte(input) return im(x,y) darkroom.vectorSelect( input>1, [uint8[3]](255), [uint8[3]](input*255) ) end end function convolve( K, input ) local N2 = math.floor(math.sqrt(#K)) assert(N2 % 2 == 1 and N2*N2 == #K) local N = math.floor(N2/2) return im(x,y) darkroom.crop( map i=-N,N j=-N,N reduce(sum) input(x+i, y+j) * K[(-j + N)*N2 + (i + N)] end) end end local function deconv( K, Khat, observed, latent_est, N) for i = 1,N do local est_conv = convolve(K,latent_est) local relative_blur = im(x,y) darkroom.crop(observed(x,y) / est_conv(x,y)) end local error_est = convolve(Khat,relative_blur) latent_est = im(x,y) darkroom.crop(latent_est(x,y)*error_est(x,y)) end end return tobyte(latent_est) end local K = {0.33333,0,0, 0,0.33333,0, 0,0,0.33333} local observed = tofloat(darkroomSimple.load("deconvolution_blurred.bmp")) local latent_est = im(x,y) [float[3]](0.5) end -- default value local convoutput = deconv( K, K, observed, latent_est, fusedIter ) convoutput:save(arg[1])
Input Image List