tracksperanto 2.9.8 → 2.9.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/History.txt CHANGED
@@ -1,3 +1,7 @@
1
+ === 2.9.9
2
+
3
+ * Add lens distortion middleware. Adds the possibility to remove or add Syntheyes lens distortion to your plates.
4
+
1
5
  === 2.9.8
2
6
 
3
7
  * Ensure that Boujou vertical coords start off 1, not off 0 - both in import and export
data/bin/tracksperanto CHANGED
@@ -81,6 +81,16 @@ op.on(" -pad", "--pad PAD_FRACTION_VALUES_COMMA_SEPARATED", String, mwd("Pad"))
81
81
  $middlewares.push(["Pad", {"left_pad" => left, "right_pad"=> right, "top_pad" => top, "bottom_pad" => bottom}])
82
82
  end
83
83
 
84
+ op.on(" -u", "--undistort K_AND_KCUBE_COMMA_SEPARATED", String, mwd("LensDisto")) do | coefficients |
85
+ k, kcube = coefficients.split(",").map{|e| e.to_f }
86
+ $middlewares.push(["LensDisto", {"k" => k, "kcube"=> kcube, "remove" => true}])
87
+ end
88
+
89
+ op.on(" -d", "--distort K_AND_KCUBE_COMMA_SEPARATED", String, mwd("LensDisto")) do | coefficients |
90
+ k, kcube = coefficients.split(",").map{|e| e.to_f }
91
+ $middlewares.push(["LensDisto", {"k" => k, "kcube"=> kcube, "remove" => false}])
92
+ end
93
+
84
94
  op.on(" -crop", "--crop CROP_VALUES_COMMA_SEPARATED", String, mwd("Crop")) do | pads|
85
95
  left, right, top, bottom = pads.split(",").map{|e| e.to_i }
86
96
  $middlewares.push(["Crop", {"left" => left, "right"=> right, "top" => top, "bottom" => bottom}])
@@ -0,0 +1,130 @@
1
+ # -*- encoding : utf-8 -*-
2
+ class Tracksperanto::Middleware::LensDisto < Tracksperanto::Middleware::Base
3
+ include Tracksperanto::UVCoordinates
4
+
5
+ class Vector2 < Struct.new(:x, :y)
6
+ end
7
+
8
+ class RF < Struct.new(:r, :f)
9
+ def inspect
10
+ '(%0.3f %0.3f)' % [r, f]
11
+ end
12
+
13
+ def m
14
+ r * f
15
+ end
16
+ end
17
+
18
+ parameter :k, :cast => :float, :desc => "Quartic distortion coefficient", :default => 0
19
+ parameter :kcube, :cast => :float, :desc => "Cubic distortion coefficient", :default => 0
20
+ parameter :remove, :cast => :bool, :desc => "Remove distortion instead of adding it"
21
+
22
+ STEPS = 256
23
+
24
+ def self.action_description
25
+ "Apply or remove lens distortion with the Syntheyes algorithm"
26
+ end
27
+
28
+ def start_export(w, h)
29
+ @width, @height = w, h
30
+ @aspect = @width.to_f / @height
31
+
32
+ # Generate the lookup table
33
+ @lut = [RF.new(0.0, 1.0)]
34
+ max_r = @aspect + 1
35
+
36
+ increment = max_r / STEPS
37
+ r = 0
38
+ STEPS.times do | mult |
39
+ r += increment
40
+ @lut.push(RF.new(r, disto_radius(r)))
41
+ end
42
+
43
+ @lut.inspect
44
+ super
45
+ end
46
+
47
+ def export_point(frame, float_x, float_y, float_residual)
48
+ x, y = remove ? undisto(float_x, float_y) : disto(float_x, float_y)
49
+ super(frame, x, y, float_residual)
50
+ end
51
+
52
+ private
53
+
54
+ def with_uv(x, y)
55
+ vec = Vector2.new(convert_to_uv(x, @width), convert_to_uv(y, @height))
56
+ yield(vec)
57
+ [convert_from_uv(@width, vec.x), convert_from_uv(@height, vec.y)]
58
+ end
59
+
60
+ # Radius is equal to aspect at the rightmost extremity
61
+ def disto_radius(r)
62
+ r2 = r ** 2
63
+ # Skipping the square root speeds things up if we don't need it
64
+ f = if kcube.abs > 0.00001
65
+ 1 + (r2 * (k + kcube * Math.sqrt(r2)));
66
+ else
67
+ 1 + (r2 * k);
68
+ end
69
+ end
70
+
71
+ def disto(x, y)
72
+ with_uv(x, y) do | pt |
73
+ # Get the radius of the point
74
+ x = pt.x * @aspect
75
+ r = Math.sqrt(x.abs**2 + pt.y.abs**2)
76
+
77
+ # Find the good tuples to interpolate on
78
+ f = disto_interpolated(r)
79
+
80
+ pt.x = pt.x * f
81
+ pt.y = pt.y * f
82
+ end
83
+ end
84
+
85
+
86
+ def undisto(x, y)
87
+ with_uv(x, y) do | pt |
88
+ # Get the radius of the point
89
+ x = pt.x * @aspect
90
+ r = Math.sqrt(x.abs**2 + pt.y.abs**2)
91
+
92
+ # Find the good tuples to interpolate on
93
+ f = undisto_interpolated(r)
94
+
95
+ pt.x = pt.x / f
96
+ pt.y = pt.y / f
97
+ end
98
+ end
99
+
100
+ def disto_interpolated(r)
101
+ left , right = nil, nil
102
+ @lut.each_with_index do | rf, i |
103
+ if rf.r > r
104
+ right = rf
105
+ left = @lut[i -1]
106
+ return lerp(r, left.r, right.r, left.f, right.f)
107
+ end
108
+ end
109
+ end
110
+
111
+ def undisto_interpolated(r)
112
+ left , right = nil, nil
113
+ @lut.each_with_index do | xf, i |
114
+ if xf.m > r
115
+ right = xf
116
+ left = @lut[i -1]
117
+ return lerp(r, left.m, right.m, left.f, right.f)
118
+ end
119
+ end
120
+ end
121
+
122
+ def lerp(x, left_x, right_x, left_y, right_y)
123
+ dx = right_x - left_x
124
+ dy = right_y - left_y
125
+ t = (x - left_x) / dx
126
+ left_y + (dy * t)
127
+ end
128
+
129
+
130
+ end
@@ -29,4 +29,12 @@ module Tracksperanto::Casts
29
29
  define_method("#{an_attr}=") { |to| instance_variable_set("@#{an_attr}", to.to_s) }
30
30
  end
31
31
  end
32
+
33
+ def cast_to_bool(*attributes)
34
+ attributes.each do | an_attr |
35
+ define_method(an_attr) { !!instance_variable_get("@#{an_attr}") }
36
+ define_method("#{an_attr}=") { |to| instance_variable_set("@#{an_attr}", !!to) }
37
+ end
38
+ end
39
+
32
40
  end
data/lib/tracksperanto.rb CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  module Tracksperanto
5
5
  PATH = File.expand_path(File.dirname(__FILE__))
6
- VERSION = '2.9.8'
6
+ VERSION = '2.9.9'
7
7
 
8
8
  module Import; end
9
9
  module Export; end
@@ -27,4 +27,16 @@ class EqualizerImportTest < Test::Unit::TestCase
27
27
  assert_in_delta 232.449011732690479, first_kf.abs_y, DELTA
28
28
  assert_equal 39, first_kf.frame
29
29
  end
30
+
31
+ def test_parsing_from_another_fixture
32
+ fixture = File.open(File.dirname(__FILE__) + '/samples/3de_v4/FB1880_man_v05.txt')
33
+
34
+ parser = Tracksperanto::Import::Equalizer4.new(:io => fixture, :width => 1024, :height => 512)
35
+ trackers = parser.to_a
36
+ assert_equal 27, trackers.length
37
+
38
+ first_t = trackers[0]
39
+ assert_equal "01", first_t.name
40
+ assert_equal 115, first_t.length
41
+ end
30
42
  end
@@ -0,0 +1,75 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require File.expand_path(File.dirname(__FILE__)) + '/../helper'
3
+
4
+ class LensMiddlewareTest < Test::Unit::TestCase
5
+
6
+ def test_action_description
7
+ assert_equal "Apply or remove lens distortion with the Syntheyes algorithm", Tracksperanto::Middleware::LensDisto.action_description
8
+ end
9
+
10
+ def test_lens_bypasses_centerpoint
11
+ receiver = flexmock
12
+ receiver.should_receive(:start_export).once.with(1920, 1080)
13
+ receiver.should_receive(:start_tracker_segment).once.with("Tracker")
14
+ receiver.should_receive(:export_point).once.with(1, 1920 / 2.0, 1080.0 / 2.0, 0)
15
+ receiver.should_receive(:end_tracker_segment).once
16
+ receiver.should_receive(:end_export).once
17
+
18
+ m = Tracksperanto::Middleware::LensDisto.new(receiver, :k => 0.0168)
19
+ m.start_export(1920, 1080)
20
+ m.start_tracker_segment("Tracker")
21
+ m.export_point(1, 1920 / 2.0, 1080.0 / 2.0, 0)
22
+ m.end_tracker_segment
23
+ m.end_export
24
+ end
25
+
26
+ def test_lens_distorted
27
+ receiver = flexmock
28
+ receiver.should_receive(:start_export).once.with(1920, 1080)
29
+ receiver.should_receive(:start_tracker_segment).once.with("Tracker")
30
+ receiver.should_receive(:export_point).once.with(1, 66.03001446825158, 43.978678913818925, 0)
31
+ receiver.should_receive(:end_tracker_segment).once
32
+ receiver.should_receive(:end_export).once
33
+
34
+ m = Tracksperanto::Middleware::LensDisto.new(receiver, :k => -0.0298, :kcube => 0.0078)
35
+ m.start_export(1920, 1080)
36
+ m.start_tracker_segment("Tracker")
37
+ m.export_point(1, 12.0, 14.0, 0)
38
+ m.end_tracker_segment
39
+ m.end_export
40
+ end
41
+
42
+ def test_lens_undistorted
43
+ receiver = flexmock
44
+ receiver.should_receive(:start_export).once.with(1920, 1080)
45
+ receiver.should_receive(:start_tracker_segment).once.with("Tracker")
46
+ receiver.should_receive(:export_point).once.with(1, 11.999914830236555, 13.99995274335909, 0)
47
+ receiver.should_receive(:end_tracker_segment).once
48
+ receiver.should_receive(:end_export).once
49
+
50
+ m = Tracksperanto::Middleware::LensDisto.new(receiver, :k => -0.0298, :kcube => 0.0078, :remove => true)
51
+ m.start_export(1920, 1080)
52
+ m.start_tracker_segment("Tracker")
53
+ m.export_point(1, 66.03001446825158, 43.978678913818925, 0)
54
+ m.end_tracker_segment
55
+ m.end_export
56
+ end
57
+
58
+ def test_roundtrip
59
+ receiver = flexmock
60
+ receiver.should_receive(:start_export).once.with(1920, 1080)
61
+ receiver.should_receive(:start_tracker_segment).once.with("Tracker")
62
+ receiver.should_receive(:export_point).once.with(1, 1.0, 1.0, 0)
63
+ receiver.should_receive(:end_tracker_segment).once
64
+ receiver.should_receive(:end_export).once
65
+
66
+ apply = Tracksperanto::Middleware::LensDisto.new(receiver, :k => -0.0298, :kcube => 0.2178)
67
+ remove = Tracksperanto::Middleware::LensDisto.new(apply, :k => -0.0298, :kcube => 0.2178, :remove => true)
68
+
69
+ remove.start_export(1920, 1080)
70
+ remove.start_tracker_segment("Tracker")
71
+ remove.export_point(1, 1.0, 1.0, 0)
72
+ remove.end_tracker_segment
73
+ remove.end_export
74
+ end
75
+ end
data/test/test_casts.rb CHANGED
@@ -10,6 +10,7 @@ class TestCasts < Test::Unit::TestCase
10
10
  cast_to_string :str_attr
11
11
  cast_to_int :int_attr
12
12
  cast_to_float :float_attr
13
+ cast_to_bool :truthy
13
14
  end
14
15
 
15
16
  class Junk
@@ -31,7 +32,24 @@ class TestCasts < Test::Unit::TestCase
31
32
  assert_kind_of Float, t.float_attr
32
33
  assert_in_delta 0, t.float_attr, D
33
34
  end
34
-
35
+
36
+ def test_cast_to_bool
37
+ t = Testable.new
38
+ assert_equal false, t.truthy
39
+
40
+ t.truthy = nil
41
+ assert_equal false, t.truthy
42
+
43
+ t.truthy = false
44
+ assert_equal false, t.truthy
45
+
46
+ t.truthy = "yes"
47
+ assert_equal true, t.truthy
48
+
49
+ t.truthy = 1
50
+ assert_equal true, t.truthy
51
+ end
52
+
35
53
  def test_cast_to_int
36
54
  t = Testable.new
37
55
 
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "tracksperanto"
8
- s.version = "2.9.8"
8
+ s.version = "2.9.9"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Julik Tarkhanov"]
12
- s.date = "2012-03-21"
12
+ s.date = "2012-04-10"
13
13
  s.description = "Converts 2D track exports between different apps like Flame, MatchMover, PFTrack..."
14
14
  s.email = "me@julik.nl"
15
15
  s.executables = ["tracksperanto"]
@@ -66,6 +66,7 @@ Gem::Specification.new do |s|
66
66
  "lib/middleware/flop.rb",
67
67
  "lib/middleware/golden.rb",
68
68
  "lib/middleware/length_cutoff.rb",
69
+ "lib/middleware/lens_disto.rb",
69
70
  "lib/middleware/lerp.rb",
70
71
  "lib/middleware/lint.rb",
71
72
  "lib/middleware/move_to_first.rb",
@@ -153,6 +154,7 @@ Gem::Specification.new do |s|
153
154
  "test/middleware/test_flop_middleware.rb",
154
155
  "test/middleware/test_golden_middleware.rb",
155
156
  "test/middleware/test_length_cutoff_middleware.rb",
157
+ "test/middleware/test_lens_middleware.rb",
156
158
  "test/middleware/test_lerp_middleware.rb",
157
159
  "test/middleware/test_lint_middleware.rb",
158
160
  "test/middleware/test_move_to_first_frame_middleware.rb",
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tracksperanto
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.9.8
4
+ version: 2.9.9
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-03-21 00:00:00.000000000 Z
12
+ date: 2012-04-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: obuf
16
- requirement: &12522820 !ruby/object:Gem::Requirement
16
+ requirement: &12549320 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 1.1.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *12522820
24
+ version_requirements: *12549320
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: progressive_io
27
- requirement: &12522580 !ruby/object:Gem::Requirement
27
+ requirement: &12549080 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '1.0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *12522580
35
+ version_requirements: *12549080
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: flame_channel_parser
38
- requirement: &12522340 !ruby/object:Gem::Requirement
38
+ requirement: &12548840 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '4.0'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *12522340
46
+ version_requirements: *12548840
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: progressbar
49
- requirement: &12522100 !ruby/object:Gem::Requirement
49
+ requirement: &12548600 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - =
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: 0.10.0
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *12522100
57
+ version_requirements: *12548600
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: update_hints
60
- requirement: &12521860 !ruby/object:Gem::Requirement
60
+ requirement: &12548360 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ~>
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '1.0'
66
66
  type: :runtime
67
67
  prerelease: false
68
- version_requirements: *12521860
68
+ version_requirements: *12548360
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: jeweler
71
- requirement: &12521620 !ruby/object:Gem::Requirement
71
+ requirement: &12548120 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *12521620
79
+ version_requirements: *12548120
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: rake
82
- requirement: &12521380 !ruby/object:Gem::Requirement
82
+ requirement: &12547880 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ! '>='
@@ -87,10 +87,10 @@ dependencies:
87
87
  version: '0'
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *12521380
90
+ version_requirements: *12547880
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: flexmock
93
- requirement: &12521140 !ruby/object:Gem::Requirement
93
+ requirement: &12547640 !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements:
96
96
  - - ~>
@@ -98,10 +98,10 @@ dependencies:
98
98
  version: '0.8'
99
99
  type: :development
100
100
  prerelease: false
101
- version_requirements: *12521140
101
+ version_requirements: *12547640
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: cli_test
104
- requirement: &12520900 !ruby/object:Gem::Requirement
104
+ requirement: &12547400 !ruby/object:Gem::Requirement
105
105
  none: false
106
106
  requirements:
107
107
  - - ~>
@@ -109,7 +109,7 @@ dependencies:
109
109
  version: '1.0'
110
110
  type: :development
111
111
  prerelease: false
112
- version_requirements: *12520900
112
+ version_requirements: *12547400
113
113
  description: Converts 2D track exports between different apps like Flame, MatchMover,
114
114
  PFTrack...
115
115
  email: me@julik.nl
@@ -168,6 +168,7 @@ files:
168
168
  - lib/middleware/flop.rb
169
169
  - lib/middleware/golden.rb
170
170
  - lib/middleware/length_cutoff.rb
171
+ - lib/middleware/lens_disto.rb
171
172
  - lib/middleware/lerp.rb
172
173
  - lib/middleware/lint.rb
173
174
  - lib/middleware/move_to_first.rb
@@ -255,6 +256,7 @@ files:
255
256
  - test/middleware/test_flop_middleware.rb
256
257
  - test/middleware/test_golden_middleware.rb
257
258
  - test/middleware/test_length_cutoff_middleware.rb
259
+ - test/middleware/test_lens_middleware.rb
258
260
  - test/middleware/test_lerp_middleware.rb
259
261
  - test/middleware/test_lint_middleware.rb
260
262
  - test/middleware/test_move_to_first_frame_middleware.rb
@@ -297,7 +299,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
297
299
  version: '0'
298
300
  segments:
299
301
  - 0
300
- hash: 648854317
302
+ hash: 179279919
301
303
  required_rubygems_version: !ruby/object:Gem::Requirement
302
304
  none: false
303
305
  requirements: