lib/middleware/lens_disto.rb in tracksperanto-2.9.9 vs lib/middleware/lens_disto.rb in tracksperanto-2.10.0
- old
+ new
@@ -1,22 +1,10 @@
# -*- encoding : utf-8 -*-
class Tracksperanto::Middleware::LensDisto < Tracksperanto::Middleware::Base
include Tracksperanto::UVCoordinates
+
- class Vector2 < Struct.new(:x, :y)
- end
-
- class RF < Struct.new(:r, :f)
- def inspect
- '(%0.3f %0.3f)' % [r, f]
- end
-
- def m
- r * f
- end
- end
-
parameter :k, :cast => :float, :desc => "Quartic distortion coefficient", :default => 0
parameter :kcube, :cast => :float, :desc => "Cubic distortion coefficient", :default => 0
parameter :remove, :cast => :bool, :desc => "Remove distortion instead of adding it"
STEPS = 256
@@ -27,72 +15,77 @@
def start_export(w, h)
@width, @height = w, h
@aspect = @width.to_f / @height
+ generate_lut
+ super
+ end
+
+ def export_point(frame, float_x, float_y, float_residual)
+ x, y = remove ? undisto(float_x, float_y) : disto(float_x, float_y)
+ super(frame, x, y, float_residual)
+ end
+
+ private
+
+ class Vector2 < Struct.new(:x, :y)
+ end
+
+ class RF < Struct.new(:r, :f)
+ def inspect
+ '(%0.3f %0.3f)' % [r, f]
+ end
+
+ def m
+ r * f
+ end
+ end
+
+ # We apply disto using a lookup table of y = f(r)
+ def generate_lut
# Generate the lookup table
@lut = [RF.new(0.0, 1.0)]
max_r = @aspect + 1
increment = max_r / STEPS
r = 0
STEPS.times do | mult |
r += increment
- @lut.push(RF.new(r, disto_radius(r)))
+ @lut.push(RF.new(r, distort_radius(r)))
end
-
- @lut.inspect
- super
end
- def export_point(frame, float_x, float_y, float_residual)
- x, y = remove ? undisto(float_x, float_y) : disto(float_x, float_y)
- super(frame, x, y, float_residual)
- end
-
- private
-
def with_uv(x, y)
vec = Vector2.new(convert_to_uv(x, @width), convert_to_uv(y, @height))
yield(vec)
[convert_from_uv(@width, vec.x), convert_from_uv(@height, vec.y)]
end
# Radius is equal to aspect at the rightmost extremity
- def disto_radius(r)
- r2 = r ** 2
- # Skipping the square root speeds things up if we don't need it
- f = if kcube.abs > 0.00001
- 1 + (r2 * (k + kcube * Math.sqrt(r2)));
- else
- 1 + (r2 * k);
- end
+ def distort_radius(r)
+ 1 + (r*r*(k + kcube * r))
end
def disto(x, y)
with_uv(x, y) do | pt |
- # Get the radius of the point
- x = pt.x * @aspect
- r = Math.sqrt(x.abs**2 + pt.y.abs**2)
-
# Find the good tuples to interpolate on
- f = disto_interpolated(r)
-
+ f = disto_interpolated(get_radius(pt))
pt.x = pt.x * f
pt.y = pt.y * f
end
end
+ def get_radius(pt)
+ # Get the radius of the point
+ x = pt.x * @aspect
+ r = Math.sqrt(x.abs**2 + pt.y.abs**2)
+ end
def undisto(x, y)
with_uv(x, y) do | pt |
- # Get the radius of the point
- x = pt.x * @aspect
- r = Math.sqrt(x.abs**2 + pt.y.abs**2)
-
# Find the good tuples to interpolate on
- f = undisto_interpolated(r)
-
+ f = undisto_interpolated(get_radius(pt))
pt.x = pt.x / f
pt.y = pt.y / f
end
end