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])