From 7b049daa25ee03113623c26262db3780adc5047d Mon Sep 17 00:00:00 2001 From: koray kavukcuoglu Date: Wed, 22 Feb 2012 12:10:59 -0500 Subject: [PATCH] init repo --- README | 2 + dist.lua | 19 ++++++++ init.lua | 7 +++ sift.lua | 94 ++++++++++++++++++++++++++++++++++++ utils.lua | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 261 insertions(+) create mode 100644 README create mode 100644 dist.lua create mode 100644 init.lua create mode 100644 sift.lua create mode 100644 utils.lua diff --git a/README b/README new file mode 100644 index 0000000..d16235b --- /dev/null +++ b/README @@ -0,0 +1,2 @@ +Feature Extractor Library for Torch7 +!!! This is not complete yet !!! diff --git a/dist.lua b/dist.lua new file mode 100644 index 0000000..d78ce19 --- /dev/null +++ b/dist.lua @@ -0,0 +1,19 @@ +fex = fex or {} +local function stdnormalpdf(pdf) + pdf:cmul(pdf) + pdf:div(-2) + pdf:exp() + pdf:mul(1/math.sqrt(2*math.pi)) + return pdf +end + +function fex.normpdf(x,mean,std) + mean = mean or 0 + std = std or 1 + local pdf = x:clone() + pdf:add(-mean) + pdf:div(std) + pdf = stdnormalpdf(pdf) + pdf:div(std) + return pdf +end diff --git a/init.lua b/init.lua new file mode 100644 index 0000000..2a45727 --- /dev/null +++ b/init.lua @@ -0,0 +1,7 @@ + +local fex = {} + +torch.include('fex','dist.lua') +torch.include('fex','sift.lua') +torch.include('fex','hog.lua') +torch.include('fex','utils.lua') \ No newline at end of file diff --git a/sift.lua b/sift.lua new file mode 100644 index 0000000..35f15c4 --- /dev/null +++ b/sift.lua @@ -0,0 +1,94 @@ + +function gendgauss(sigma) + + --Laplacian of size sigma + local f_wid = 4 * math.floor(sigma); + local G = fex.normpdf(torch.range(-f_wid,f_wid),0,sigma); + G = torch.ger(G,G) + GX,GY = fex.gradient(G); + + GX:div(torch.sum(torch.abs(GX))):mul(2) + GY:div(torch.sum(torch.abs(GY))):mul(2) + return GX, GY +end + +function fex.dsift(im, grid_spacing, patch_size) + local I + if im:dim() == 3 then + I = torch.sum(im,1)/3 + I = I[1] + elseif im:dim() == 2 then + I = im + else + error('im has to be 2D or 3D') + end + + patch_size = patch_size or 16 + grid_spacing = grid_spacing or patch_size/2 + + local num_angles = 8 + local num_bins = 4 + local num_samples = num_bins * num_bins + + local alpha = 9 + local sigma_edge = 1 + + local angle_step = 2 * math.pi / num_angles + local angles = torch.range(0,2*math.pi,angle_step) + angles = angles:narrow(1,1,num_angles):clone() + + local hgt = I:size(1) + local wid = I:size(2) + + local G_X,G_Y = gendgauss(sigma_edge) + + I:add(-torch.mean(I)) + local I_X = fex.xcorr2(I, G_X, 'S') + local I_Y = fex.xcorr2(I, G_Y, 'S') + + local I_mag = torch.sqrt(torch.pow(I_X,2) + torch.pow(I_Y,2)) + local I_theta = torch.atan(torch.cdiv(I_Y,I_X)) + I_theta[torch.ne(I_theta,I_theta)]=0 + + local grid_x = torch.range(patch_size/2,wid-patch_size/2,grid_spacing) + local grid_y = torch.range(patch_size/2,hgt-patch_size/2,grid_spacing) + + local I_orientation = torch.zeros(num_angles, hgt, wid) + + local cosI = torch.cos(I_theta) + local sinI = torch.sin(I_theta) + + for a=1,num_angles do + local tmp = cosI*math.cos(angles[a]) + sinI*math.sin(angles[a]) + tmp:pow(alpha) + tmp[torch.le(tmp,0)] = 0 + torch.cmul(I_orientation[a], tmp, I_mag) + end + + local weight_kernel = torch.zeros(patch_size,patch_size) + local r = patch_size/2; + local cx = r-0.5; + local sample_res = patch_size/num_bins; + local weight_x = torch.abs(torch.range(1,patch_size)-cx)/sample_res + weight_x:apply(function(x) if x <= 1 then return 1-x else return x end end) + local tw = torch.ger(weight_x, weight_x) + + for a=1,num_angles do + I_orientation[a]:copy(fex.conv2(I_orientation[a],tw,'S')) + end + return I_orientation +end + + + + + + + + + + + + + + diff --git a/utils.lua b/utils.lua new file mode 100644 index 0000000..3e7c4b3 --- /dev/null +++ b/utils.lua @@ -0,0 +1,139 @@ +function fex.conv2(...) + local arg = {...} + if arg[#arg] == 'S' then + local ro,x,k = nil,nil,nil + if #arg == 4 then + ro = arg[1] + x = arg[2] + k = arg[3] + else + x = arg[1] + k = arg[2] + ro = x.new(x:size()) + end + local r = torch.conv2(x,k,'F') + local shifti = math.floor((r:size(1)-x:size(1))/2) + local shiftj = math.floor((r:size(2)-x:size(2))/2) + local ii = r:dim()-1 + local jj = r:dim() + ro:resizeAs(x) + ro:copy(r:narrow(ii,shifti,x:size(1)):narrow(jj,shiftj,x:size(2))) + return ro + else + return torch.conv2(...) + end +end +function fex.xcorr2(...) + local arg = {...} + if arg[#arg] == 'S' then + local ro,x,k = nil,nil,nil + if #arg == 4 then + ro = arg[1] + x = arg[2] + k = arg[3] + else + x = arg[1] + k = arg[2] + ro = x.new(x:size()) + end + local r = torch.xcorr2(x,k,'F') + local shifti = math.floor((r:size(1)-x:size(1))/2) + local shiftj = math.floor((r:size(2)-x:size(2))/2) + local ii = r:dim()-1 + local jj = r:dim() + ro:resizeAs(x) + ro:copy(r:narrow(ii,shifti,x:size(1)):narrow(jj,shiftj,x:size(2))) + return ro + else + return torch.xcorr2(...) + end +end + +function fex.gradient(x,dim) + + if not dim then dim = torch.range(0,x:dim()):narrow(1,2,x:dim()) end + if type(dim) == 'number' then dim = torch.Tensor({dim}) end + local ndim = x:dim() + + local function grad(x,dim) + local sz = x:size() + if sz[dim] == 1 then return x:clone():zero() end + sz[dim] = sz[dim]+2 + local xx = x.new(sz):zero() + -- copy center + xx:narrow(dim,2,x:size(dim)):copy(x) + -- extrapolate the beginning + local ff = xx:narrow(dim,1,1) + local f1 = xx:narrow(dim,2,1) + local f2 = xx:narrow(dim,3,1) + torch.add(ff,f1,-1,f2) + ff:add(f1) + -- extrapolate the ending + local xend = xx:size(dim) + local fe = xx:narrow(dim,xend,1) + local ff1 = xx:narrow(dim,xend-1,1) + local ff2 = xx:narrow(dim,xend-2,1) + torch.add(fe,ff1,-1,ff2) + fe:add(ff1) + -- now subtract + local d = xx:narrow(dim,3,xend-2):clone() + d:add(-1,xx:narrow(dim,1,xend-2)) + return d:div(2) + end + + local res = {} + for i=1,ndim do + table.insert(res,i,grad(x,ndim-i+1)) + end + return unpack(res) +end + +local function dimnarrow(x,sz,pad,dim) + local xn = x + for i=1,x:dim() do + if i > dim then + xn = xn:narrow(i,pad[i]+1,sz[i]) + end + end + return xn +end +local function padzero(x,pad) + local sz = x:size() + for i=1,x:dim() do sz[i] = sz[i]+pad[i]*2 end + local xx = x.new(sz):zero() + local xn = dimnarrow(xx,x:size(),pad,-1) + xn:copy(x) + return xx +end +local function padmirror(x,pad) + local xx = padzero(x,pad) + local sz = xx:size() + for i=1,x:dim() do + local xxn = dimnarrow(xx,x:size(),pad,i) + for j=1,pad[i] do + xxn:select(i,j):copy(xxn:select(i,pad[i]*2-j+1)) + xxn:select(i,sz[i]-j+1):copy(xxn:select(i,sz[i]-pad[i]*2+j)) + end + end + return xx +end +function fex.padarray(x,pad,padtype) + if x:dim() ~= #pad then + error('number of dimensions of Input should match number of padding sizes') + end + if padtype == 'zero' then return padzero(x,pad) end + if padtype == 'mirror' then return padmirror(x,pad) end + error('unknown paddtype ' .. padtype) +end + + + + + + + + + + + +