tracksperanto 1.1.1 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. data/.DS_Store +0 -0
  2. data/History.txt +11 -0
  3. data/Manifest.txt +64 -20
  4. data/README.txt +82 -30
  5. data/Rakefile +1 -0
  6. data/bin/tracksperanto +21 -14
  7. data/lib/export/base.rb +16 -6
  8. data/lib/export/match_mover.rb +40 -0
  9. data/lib/export/nuke_script.rb +78 -0
  10. data/lib/export/pftrack.rb +14 -14
  11. data/lib/export/shake_text.rb +7 -8
  12. data/lib/export/syntheyes.rb +9 -5
  13. data/lib/import/base.rb +45 -12
  14. data/lib/import/flame_stabilizer.rb +17 -32
  15. data/lib/import/match_mover.rb +65 -0
  16. data/lib/import/nuke_script.rb +96 -0
  17. data/lib/import/pftrack.rb +9 -2
  18. data/lib/import/shake_grammar/catcher.rb +56 -0
  19. data/lib/import/shake_grammar/lexer.rb +95 -0
  20. data/lib/import/shake_script.rb +189 -103
  21. data/lib/import/shake_text.rb +5 -3
  22. data/lib/import/syntheyes.rb +9 -2
  23. data/lib/middleware/base.rb +6 -1
  24. data/lib/middleware/golden.rb +7 -0
  25. data/lib/middleware/reformat.rb +10 -3
  26. data/lib/middleware/scaler.rb +14 -4
  27. data/lib/middleware/shift.rb +10 -0
  28. data/lib/middleware/slipper.rb +3 -0
  29. data/lib/pipeline/base.rb +111 -37
  30. data/lib/tracksperanto/block_init.rb +7 -0
  31. data/lib/tracksperanto/casts.rb +31 -0
  32. data/lib/tracksperanto/format_detector.rb +35 -0
  33. data/lib/tracksperanto/keyframe.rb +31 -0
  34. data/lib/tracksperanto/safety.rb +20 -0
  35. data/lib/tracksperanto/tracker.rb +38 -0
  36. data/lib/tracksperanto/zip_tuples.rb +20 -0
  37. data/lib/tracksperanto.rb +13 -100
  38. data/test/.DS_Store +0 -0
  39. data/test/export/.DS_Store +0 -0
  40. data/test/export/README_EXPORT_TESTS.txt +15 -0
  41. data/test/export/samples/ref_NukeScript.nk +25 -0
  42. data/test/export/samples/ref_NukeScript.nk.autosave +77 -0
  43. data/test/export/samples/ref_PFTrack.2dt +50 -0
  44. data/test/export/samples/ref_ShakeText.txt +48 -0
  45. data/test/export/samples/ref_Syntheyes.txt +42 -0
  46. data/test/export/samples/ref_matchmover.rz2 +52 -0
  47. data/test/export/test_match_mover_export.rb +16 -0
  48. data/test/export/test_mux.rb +23 -0
  49. data/test/export/test_nuke_export.rb +22 -0
  50. data/test/export/test_pftrack_export.rb +19 -0
  51. data/test/export/test_shake_export.rb +15 -0
  52. data/test/export/test_syntheyes_export.rb +15 -0
  53. data/test/helper.rb +85 -2
  54. data/test/import/.DS_Store +0 -0
  55. data/test/{samples → import/samples}/.DS_Store +0 -0
  56. data/test/{samples → import/samples}/flyover2DP_syntheyes.txt +0 -0
  57. data/test/import/samples/four_tracks_in_one_matchmove.shk +323 -0
  58. data/test/import/samples/four_tracks_in_one_stabilizer.shk +321 -0
  59. data/test/{samples → import/samples}/fromCombustion_fromMidClip_wSnap.stabilizer +0 -0
  60. data/test/{samples → import/samples}/hugeFlameSetup.stabilizer +0 -0
  61. data/test/import/samples/kipPointsMatchmover.rz2 +523 -0
  62. data/test/{samples → import/samples}/megaTrack.action.3dtrack.stabilizer +0 -0
  63. data/test/{samples → import/samples}/one_shake_tracker.txt +0 -0
  64. data/test/{samples → import/samples}/one_shake_tracker_from_first.txt +0 -0
  65. data/test/import/samples/one_tracker_with_break.nk +71 -0
  66. data/test/import/samples/one_tracker_with_break_in_grp.nk +91 -0
  67. data/test/{samples → import/samples}/shake_tracker_nodes.shk +0 -0
  68. data/test/{samples → import/samples}/shake_tracker_nodes_to_syntheyes.txt +0 -0
  69. data/test/{samples → import/samples}/sourcefile_pftrack.2dt +0 -0
  70. data/test/{samples → import/samples}/three_tracks_in_one_stabilizer.shk +0 -0
  71. data/test/{samples → import/samples}/two_shake_trackers.txt +0 -0
  72. data/test/{samples → import/samples}/two_tracks_in_one_tracker.shk +0 -0
  73. data/test/{test_flame_import.rb → import/test_flame_import.rb} +15 -9
  74. data/test/import/test_match_mover_import.rb +44 -0
  75. data/test/import/test_nuke_import.rb +63 -0
  76. data/test/{test_pftrack_import.rb → import/test_pftrack_import.rb} +10 -4
  77. data/test/import/test_shake_catcher.rb +72 -0
  78. data/test/import/test_shake_lexer.rb +95 -0
  79. data/test/import/test_shake_script_import.rb +75 -0
  80. data/test/{test_shake_text_import.rb → import/test_shake_text_import.rb} +10 -3
  81. data/test/{test_syntheyes_import.rb → import/test_syntheyes_import.rb} +8 -3
  82. data/test/middleware/test_golden_middleware.rb +32 -0
  83. data/test/middleware/test_reformat_middleware.rb +35 -0
  84. data/test/middleware/test_scaler_middleware.rb +51 -0
  85. data/test/middleware/test_shift_middleware.rb +26 -0
  86. data/test/middleware/test_slip_middleware.rb +31 -0
  87. data/test/pipeline/test_pipeline_base.rb +14 -0
  88. data/test/test_format_detector.rb +39 -0
  89. data/test/test_tracker.rb +48 -0
  90. data/tracksperanto.gemspec +9 -7
  91. metadata +101 -30
  92. data/lib/middleware/close.rb +0 -6
  93. data/test/test_shake_export.rb +0 -58
  94. data/test/test_shake_script_import.rb +0 -50
data/.DS_Store CHANGED
Binary file
data/History.txt CHANGED
@@ -1,3 +1,14 @@
1
+ === 1.2.0 / 2009-09-20
2
+
3
+ * Add experimental MatchMoverPro import and export support
4
+ * Rewrite the Shake parser, support MatchMove and Stabilize nodes and many tracks per node
5
+ * Officially add and test the Reformat middleware
6
+ * Remove the Close middleware and close IOs automatically at pipeline end
7
+ * Much improved documentation
8
+ * Use IO as base for all the parsers (if a parser needs a string it will have to read by himself)
9
+ * Much improved test coverage
10
+ * Support Nuke import and export
11
+
1
12
  === 1.0.0 / 2009-04-19
2
13
 
3
14
  * Welcome
data/Manifest.txt CHANGED
@@ -6,44 +6,88 @@ Rakefile
6
6
  bin/tracksperanto
7
7
  lib/.DS_Store
8
8
  lib/export/base.rb
9
+ lib/export/match_mover.rb
9
10
  lib/export/mux.rb
11
+ lib/export/nuke_script.rb
10
12
  lib/export/pftrack.rb
11
13
  lib/export/shake_text.rb
12
14
  lib/export/syntheyes.rb
13
15
  lib/import/base.rb
14
16
  lib/import/flame_stabilizer.rb
17
+ lib/import/match_mover.rb
18
+ lib/import/nuke_script.rb
15
19
  lib/import/pftrack.rb
20
+ lib/import/shake_grammar/catcher.rb
21
+ lib/import/shake_grammar/lexer.rb
16
22
  lib/import/shake_script.rb
17
23
  lib/import/shake_text.rb
18
24
  lib/import/syntheyes.rb
19
25
  lib/middleware/base.rb
20
- lib/middleware/close.rb
21
26
  lib/middleware/golden.rb
22
27
  lib/middleware/reformat.rb
23
28
  lib/middleware/scaler.rb
29
+ lib/middleware/shift.rb
24
30
  lib/middleware/slipper.rb
25
31
  lib/pipeline/base.rb
26
32
  lib/tracksperanto.rb
33
+ lib/tracksperanto/block_init.rb
34
+ lib/tracksperanto/casts.rb
35
+ lib/tracksperanto/format_detector.rb
36
+ lib/tracksperanto/keyframe.rb
37
+ lib/tracksperanto/safety.rb
38
+ lib/tracksperanto/tracker.rb
39
+ lib/tracksperanto/zip_tuples.rb
27
40
  test/.DS_Store
41
+ test/export/.DS_Store
42
+ test/export/README_EXPORT_TESTS.txt
43
+ test/export/samples/ref_NukeScript.nk
44
+ test/export/samples/ref_NukeScript.nk.autosave
45
+ test/export/samples/ref_PFTrack.2dt
46
+ test/export/samples/ref_ShakeText.txt
47
+ test/export/samples/ref_Syntheyes.txt
48
+ test/export/samples/ref_matchmover.rz2
49
+ test/export/test_match_mover_export.rb
50
+ test/export/test_mux.rb
51
+ test/export/test_nuke_export.rb
52
+ test/export/test_pftrack_export.rb
53
+ test/export/test_shake_export.rb
54
+ test/export/test_syntheyes_export.rb
28
55
  test/helper.rb
29
- test/samples/.DS_Store
30
- test/samples/flyover2DP_syntheyes.txt
31
- test/samples/fromCombustion_fromMidClip_wSnap.stabilizer
32
- test/samples/hugeFlameSetup.stabilizer
33
- test/samples/megaTrack.action.3dtrack.stabilizer
34
- test/samples/one_shake_tracker.txt
35
- test/samples/one_shake_tracker_from_first.txt
36
- test/samples/shake_tracker_nodes.shk
37
- test/samples/shake_tracker_nodes_to_syntheyes.txt
38
- test/samples/sourcefile_pftrack.2dt
39
- test/samples/three_tracks_in_one_stabilizer.shk
40
- test/samples/two_shake_trackers.txt
41
- test/samples/two_tracks_in_one_tracker.shk
42
- test/test_flame_import.rb
56
+ test/import/.DS_Store
57
+ test/import/samples/.DS_Store
58
+ test/import/samples/flyover2DP_syntheyes.txt
59
+ test/import/samples/four_tracks_in_one_matchmove.shk
60
+ test/import/samples/four_tracks_in_one_stabilizer.shk
61
+ test/import/samples/fromCombustion_fromMidClip_wSnap.stabilizer
62
+ test/import/samples/hugeFlameSetup.stabilizer
63
+ test/import/samples/kipPointsMatchmover.rz2
64
+ test/import/samples/megaTrack.action.3dtrack.stabilizer
65
+ test/import/samples/one_shake_tracker.txt
66
+ test/import/samples/one_shake_tracker_from_first.txt
67
+ test/import/samples/one_tracker_with_break.nk
68
+ test/import/samples/one_tracker_with_break_in_grp.nk
69
+ test/import/samples/shake_tracker_nodes.shk
70
+ test/import/samples/shake_tracker_nodes_to_syntheyes.txt
71
+ test/import/samples/sourcefile_pftrack.2dt
72
+ test/import/samples/three_tracks_in_one_stabilizer.shk
73
+ test/import/samples/two_shake_trackers.txt
74
+ test/import/samples/two_tracks_in_one_tracker.shk
75
+ test/import/test_flame_import.rb
76
+ test/import/test_match_mover_import.rb
77
+ test/import/test_nuke_import.rb
78
+ test/import/test_pftrack_import.rb
79
+ test/import/test_shake_catcher.rb
80
+ test/import/test_shake_lexer.rb
81
+ test/import/test_shake_script_import.rb
82
+ test/import/test_shake_text_import.rb
83
+ test/import/test_syntheyes_import.rb
84
+ test/middleware/test_golden_middleware.rb
85
+ test/middleware/test_reformat_middleware.rb
86
+ test/middleware/test_scaler_middleware.rb
87
+ test/middleware/test_shift_middleware.rb
88
+ test/middleware/test_slip_middleware.rb
89
+ test/pipeline/test_pipeline_base.rb
90
+ test/test_format_detector.rb
43
91
  test/test_keyframe.rb
44
- test/test_pftrack_import.rb
45
- test/test_shake_export.rb
46
- test/test_shake_script_import.rb
47
- test/test_shake_text_import.rb
48
- test/test_syntheyes_import.rb
92
+ test/test_tracker.rb
49
93
  tracksperanto.gemspec
data/README.txt CHANGED
@@ -6,51 +6,103 @@
6
6
 
7
7
  Tracksperanto is a universal 2D-track translator between many apps.
8
8
 
9
+ == Why Tracksperanto?
10
+
11
+ Historically, every matchmoving app uses it's own UI for tracking 2D features.
12
+ Unfortunately, the UIs of these are all different and not very user-friendly. It happens
13
+ that an app cannot solve a shot that another one will, but you usually have to redo your 2D
14
+ tracks in each one of them.
15
+
16
+ Another problem with today's matchmoving apps is that they are vastly inefficient when
17
+ doing 2D tracks. Almost all of them use OpenGL and want to load the whole frame into memory
18
+ at once. When doing tracks of long shots at high resolutions (like 2K and HD), especially
19
+ on 32bit platforms, the app usually cannot even cache the whole shot and tracking is very
20
+ very slow.
21
+
22
+ Compositing apps, in contrast, are very efficient in this. Both Shake and Nuke offer very
23
+ fast trackers because they can load only the search area for the tracker into memory and
24
+ not a pixel more. When you use manual feature selection you can create many tracks very
25
+ quickyl even without having fast IO. Flame is also very fast since it has virtually zero IO
26
+ overhead thanks to it's fast storage. Compositing apps also allow for precise, local
27
+ preprocessing of tracking features like boosting contrast, doing expensive (especially
28
+ temporal) denoise, blurs and so on, while matchmoving apps offer only a single, global
29
+ preprocessing step (like a LUT or a gamma curve adjustment) which is not adequate for all
30
+ of the features being tracked.
31
+
32
+ It's thusly very natural to track in a modern compositing app that has selective image
33
+ loading, and then export one single group of tracks into all of the matchmoving
34
+ applications and figuring out which one gives a better camera solve. Also, you can always
35
+ escape into the 2D world if no 3D app proves to be adequate. If you need to move from one
36
+ app to another, you won't have to retrack.
37
+
38
+ Another issue with tracks is adjusting to formats. Very few apps allow you to convert your
39
+ tracks in one stop from format to format - like doing an unproportional scale on the
40
+ tracks, or moving them a few pixels left and right. This comes at a high cost of the
41
+ footage you are tracking came cropped or in a wrong aspect - the only way to solve the shot
42
+ will be to retrack it from scratch. Tracksperanto allows you to work around this
43
+ by applying simple transformations to the tracks.
44
+
45
+ == Usage
46
+
47
+ The main way to use Tracksperanto is to use the supplied "tracksperanto" binary, like so:
48
+
49
+ tracksperanto -w 1920 -h 1080 /Films/Blockbuster/Shots/001/script.shk
50
+
51
+ -w and -h stand for Width and Height and define the size of your comp (different tracking
52
+ apps use different coordinate systems and we need to know the size of the comp to properly
53
+ convert these). You also have additional options like -xs, -ys and --slip - consult the
54
+ usage info for the tracksperanto binary.
55
+
56
+ The converted files will be saved in the same directory as the source, if resulting
57
+ converted files already exist <b>they will be overwritten without warning</b>.
58
+
59
+ == Format support
60
+
9
61
  Import support:
10
- * Shake script (one tracker node per tracker)
11
- * Shake tracker node export (textfile with many tracks per file), also exported by Boujou and others
62
+
63
+ * Flame .stabilizer file (not the .stabilizer.p blob format)
64
+ * Nuke script (Tracker3 nodes, also known as Tracker)
65
+ * Shake script (Tracker, Matchmove and Stabilize nodes)
66
+ * Shake tracker node export (textfile with many tracks per file)
12
67
  * PFTrack 2dt files
13
- * Syntheyes 2D tracking data exports (UV coordinates)
68
+ * Syntheyes 2D tracking data exports
69
+ * MatchMover Pro .rz2
14
70
 
15
71
  Export support:
16
72
 
17
- * Shake text file (many trackers per file), also accepted by Boujou
73
+ * Shake text file (many trackers per file), also accepted by Boujou.
74
+ May crash Shake with more than 4-5 tracks.
18
75
  * PFTrack 2dt file (with residuals)
19
76
  * Syntheyes 2D tracking data import (UV coordinates)
20
-
21
- The main way to use Tracksperanto is to use the supplied "tracksperanto" binary, like so:
22
-
23
- tracksperanto -f ShakeScript -w 1920 -h 1080 /Films/Blockbuster/Shots/001/script.shk
24
-
25
- ShakeScript is the name of the translator that will be used to read the file (many apps export tracks as .txt files so
26
- there is no way for us to autodetect them all). -w and -h stand for Width and Height and define the size of your comp (different
27
- tracking apps use different coordinate systems and we need to know the size of the comp to properly convert these). You also have
28
- additional options like -xs, -ys and --slip - consult the usage info for the tracksperanto binary.
29
-
30
- The converted files will be saved in the same directory as the source, if resulting converted files already exist ++they will be overwritten without warning++.
77
+ * Nuke script
78
+ * MatchMover Pro .rz2
31
79
 
32
80
  == Modularity
33
81
 
34
- Tracksperanto supports many export and import formats. It also can help when you need to import and export the same format,
35
- but you need some operation applied to the result (like scaling a proxy track up). Internally, Tracksperanto talks
36
- Exporters, Importers and Middlewares. Any processing chain usually works like this:
82
+ Tracksperanto supports many export and import formats. It also can help when you need to
83
+ import and export the same format, but you need some operation applied to the result (like
84
+ scaling a proxy track up). Internally, Tracksperanto talks Exporters, Importers and
85
+ Middlewares. Any processing chain (called a Pipeline) usually works like this:
37
86
 
38
- 1) The tracker file is read and trackers and their keyframes are extracted, converting them to the internal representation.
39
- For some formats you need to supply the width and height of the source material
40
- 2) The trackers and their keyframes are dumped to all export formats Tracksperanto supports, optionally passing through middleware
87
+ * Tracker file is read and trackers and their
88
+ keyframes are extracted, converting them to
89
+ the internal representation.
90
+ * Trackers and their keyframes are dumped to all export
91
+ formats Tracksperanto supports, optionally passing through middleware
41
92
 
42
- == Internal coordinate system
93
+ == Importing your own formats
43
94
 
44
- Frame numbers start from zero (frame 0 is first frame of the track).
95
+ You can easily write a Tracksperanto import module - refer to Tracksperanto::Import::Base
96
+ docs. Your importer should return an array of Tracksperanto::Tracker objects which
97
+ are themselves arrays of Tracksperanto::Keyframe objects.
45
98
 
46
- Tracksperanto uses the Shake coordinates as base. Image is Y-positive, X-positive, absolute pixel values up and right (zero is in the
47
- lower left corner). Some apps use a different coordinate system so translation will take place on import or on export, respectively.
99
+ == Exporting your own formats
48
100
 
49
- We also use residual and not correlation (residual is how far the tracker strolls away, correlation is how sure the tracker is
50
- about what it's doing). Residual is the inverse of correlation (with total correlation of one the residual excursion becomes zero).
101
+ You can easily write an exporter. Refer to the Tracksperanto::Export::Base docs.
51
102
 
52
103
  == Limitations
53
104
 
54
- Information about the search area, reference area and offset is not passed along (outside of scope for the app and different trackers handle
55
- these differently, if at all). For some modules no residual will be passed along (3D tracking apps generally do not export residual with
56
- backprojected 3D features).
105
+ Information about the search area, reference area and offset is not passed along (outside
106
+ of scope for the app and different trackers handle these differently, if at all). For some
107
+ modules no residual will be passed along (3D tracking apps generally do not export residual
108
+ with backprojected 3D features).
data/Rakefile CHANGED
@@ -9,6 +9,7 @@ Hoe::RUBY_FLAGS.replace ENV['RUBY_FLAGS'] || "-I#{%w(lib test).join(File::PATH_S
9
9
 
10
10
  Hoe.spec('tracksperanto') do | p |
11
11
  p.version = Tracksperanto::VERSION
12
+ p.extra_deps = {"flexmock" => ">=0"}
12
13
  p.rubyforge_name = 'guerilla-di'
13
14
  p.developer('Julik Tarkhanov', 'me@julik.nl')
14
15
  p.extra_rdoc_files = p.extra_rdoc_files.reject{|e| e =~ "samples\/"}
data/bin/tracksperanto CHANGED
@@ -14,33 +14,34 @@ require File.dirname(__FILE__) + '/../lib/tracksperanto'
14
14
  require 'optparse'
15
15
 
16
16
  # Sane defaults
17
- reader_klass = Tracksperanto::Import::ShakeScript
18
- width = 1920
19
- height = 1080
17
+ reader_klass = nil
18
+ width = nil
19
+ height = nil
20
20
  reformat_w = nil
21
21
  reformat_h = nil
22
22
  scale_x = 1.0
23
23
  scale_y = 1.0
24
24
  slip = 0
25
25
  golden_tracks = false
26
+ x_shift = 0
27
+ y_shift = 0
26
28
 
27
- readers = Tracksperanto::Import.constants.map{|e| e.to_s }.reject{|e| e == 'Base'}
28
- informative_readers = readers.reject{|e| e == 'ShakeScript'}
29
+ readers = Tracksperanto.importer_names
29
30
 
30
31
  parser = OptionParser.new do | p |
31
32
  p.banner = "Usage: tracksperanto -f ShakeScript -w 1920 -h 1080 /Films/Blockbuster/Shots/001/script.shk"
32
- p.on(" -f", "--from TRANSLATOR", String, "Use the specific import translator (defaults to ShakeScript, but can be \
33
- #{informative_readers.join(', ')})") do | f |
33
+ p.on(" -f", "--from TRANSLATOR", String,
34
+ "Use the specific import translator (will try to autodetect, but can be #{readers.join(', ')})") do | f |
34
35
  begin
35
36
  reader_klass = Tracksperanto::Import.const_get(f)
36
37
  rescue NameError => e
37
38
  reader_list = readers.join("\n\t")
38
- STDERR.puts "Unknown reader #{f.inspect}, available readers:\n\t#{readers}"
39
+ STDERR.puts "Unknown reader #{f.inspect}, available readers:\n\t#{readers.join(', ')}"
39
40
  exit(-1)
40
41
  end
41
42
  end
42
- p.on(" -w", "--width WIDTH_IN_PIXELS", Integer, "Absolute input comp width in pixels") { |w| width = w }
43
- p.on(" -h", "--height HEIGHT_IN_PIXELS", Integer, "Absolute input comp height in pixels") {|w| height = w }
43
+ p.on(" -w", "--width WIDTH_IN_PIXELS", Integer, "Absolute input comp width in pixels (will try to autodetect)") { |w| width = w }
44
+ p.on(" -h", "--height HEIGHT_IN_PIXELS", Integer, "Absolute input comp height in pixels (will try to autodetect)") {|w| height = w }
44
45
  p.on(" -xs", "--xscale X_SCALING_FACTOR", Float, "Scale the result in X by this factor (1.0 is the default)") {|sx| scale_x = sx }
45
46
  p.on(" -ys", "--yscale Y_SCALING_FACTOR", Float, "Scale the result in Y by this factor (1.0 is the default)") {|sy| scale_y = sy }
46
47
  p.on(" -s", "--slip FRAMES", Integer, "Slip the result by this number of frames, positive is 'later'") {|sy| slip = sy }
@@ -53,7 +54,12 @@ parser = OptionParser.new do | p |
53
54
  p.on(" -ry", "--reformat-y NEW_PIX_HEIGHT", Integer, "Reformat the comp to this height and scale all tracks to it") {|rh|
54
55
  reformat_h = rh
55
56
  }
56
-
57
+ p.on(" -xm", "--xshift X_IN_PIXELS", Float, "Move the points left or right") {|sx| x_shift = sx }
58
+ p.on(" -ym", "--yshift Y_IN_PIXELS", Float, "Move the points up or down") {|sx| y_shift = sx }
59
+ p.on("--version", "Show the version and exit") {|v|
60
+ puts "#{Tracksperanto::VERSION} running on Ruby #{RUBY_VERSION} on #{RUBY_PLATFORM}"
61
+ exit(0)
62
+ }
57
63
  end
58
64
 
59
65
  begin
@@ -73,12 +79,13 @@ end
73
79
 
74
80
  pipe = Tracksperanto::Pipeline::Base.new
75
81
  pipe.progress_block = lambda{|percent, msg| puts("#{msg}..#{percent.to_i}%") }
76
-
77
- pipe.run(input_file, width, height, reader_klass) do | scaler, slipper, golden, reformat |
82
+ pipe.run(input_file, :pix_w => width, :pix_h => height, :parser => parser) do | scaler, slipper, golden, reformat, shift |
78
83
  slipper.slip = slip
79
84
  scaler.x_factor = scale_x
80
85
  scaler.y_factor = scale_y
81
86
  golden.enabled = golden_tracks
82
87
  reformat.width = reformat_w if reformat_w
83
- reformat.width = reformat_h if reformat_h
88
+ reformat.height = reformat_h if reformat_h
89
+ shift.x_shift = x_shift
90
+ shift.y_shift = y_shift
84
91
  end
data/lib/export/base.rb CHANGED
@@ -1,5 +1,9 @@
1
- # Base exporter
1
+ # Base exporter. Inherit from this class to automatically register another export format.
2
+ # The exporters in Tracksperanto are event-driven and follow the same conventions - your
3
+ # exporter will be notified when a tracker will be exported and when a tracker has been passed
4
+ # (the last keyframe has been sent)
2
5
  class Tracksperanto::Export::Base
6
+
3
7
  attr_reader :io
4
8
 
5
9
  def self.inherited(by)
@@ -7,25 +11,31 @@ class Tracksperanto::Export::Base
7
11
  super
8
12
  end
9
13
 
10
- # Should return the suffix and extension of this export file (like "_flame.stabilizer"). It's a class
14
+ # Should return the suffix and extension of this export file (like "flame.stabilizer"). It's a class
11
15
  # method because it gets requested before the exporter is instantiated
12
16
  def self.desc_and_extension
13
17
  "data.txt"
14
18
  end
15
19
 
20
+ # Should return the human-readable (read: with spaces) name of the export module
21
+ def self.human_name
22
+ "Abstract export format"
23
+ end
24
+
25
+ # The constructor for an exporter should accept a handle to the IO object that you can write to.
16
26
  def initialize(write_to_io)
17
27
  @io = write_to_io
18
28
  end
19
29
 
20
- # Called on export start
30
+ # Called on export start. Will receive the width and height of the comp being exported
21
31
  def start_export( img_width, img_height)
22
32
  end
23
33
 
24
- # Called on export end
34
+ # Called on export end. No need to close the passed IO, it will be done for you afterwards
25
35
  def end_export
26
36
  end
27
37
 
28
- # Called on tracker start, one for each tracker
38
+ # Called on tracker start, once for each tracker. Receives the name of the tracker.
29
39
  def start_tracker_segment(tracker_name)
30
40
  end
31
41
 
@@ -33,7 +43,7 @@ class Tracksperanto::Export::Base
33
43
  def end_tracker_segment
34
44
  end
35
45
 
36
- # Called for each tracker keyframe
46
+ # Called for each tracker keyframe, with the Tracksperanto internal coordinates and frame numbers
37
47
  def export_point(at_frame_i, abs_float_x, abs_float_y, float_residual)
38
48
  end
39
49
  end
@@ -0,0 +1,40 @@
1
+ # Export for Autodesk MatchMover/Image Modeler
2
+ class Tracksperanto::Export::MatchMover < Tracksperanto::Export::Base
3
+
4
+ def self.desc_and_extension
5
+ "matchmover.rz2"
6
+ end
7
+
8
+ def self.human_name
9
+ "Matchmover 2D export .rz2 file"
10
+ end
11
+
12
+ PREAMBLE = %[imageSequence "Sequence 01"\n{\n\t2560\t1080\tf( "D:/temp/sequence.%04d.dpx" )\tb( 1 211 1 )\t\n}\n]
13
+ TRACKER_PREAMBLE = "pointTrack %s rgb( 255 0 0 ) \n{\n"
14
+ TRACKER_POSTAMBLE = "}\n"
15
+ FIRST_KEYFRAME_TEMPLATE = "\t%d\t %.3f %.3f ki( 0.8 )\t s( 66 66 64 64 ) p( 24 24 25 25 )"
16
+ KEYFRAME_TEMPLATE = "\t%d\t %.3f %.3f p+( %.6f )\t"
17
+
18
+ def start_export( img_width, img_height)
19
+ @io.puts(PREAMBLE.gsub(/2560/, img_width.to_s).gsub(/1080/, img_height.to_s))
20
+ end
21
+
22
+
23
+ def start_tracker_segment(tracker_name)
24
+ @tracker_name = tracker_name
25
+ @at_first_point = true
26
+ @io.write(TRACKER_PREAMBLE % tracker_name.inspect)
27
+ end
28
+
29
+ def end_tracker_segment
30
+ @io.write(TRACKER_POSTAMBLE)
31
+ end
32
+
33
+ def export_point(frame, abs_float_x, abs_float_y, float_residual)
34
+ template = @at_first_point ? FIRST_KEYFRAME_TEMPLATE : KEYFRAME_TEMPLATE
35
+ values = [frame + 1, abs_float_x, abs_float_y, (1 - float_residual)]
36
+ @io.puts(template % values)
37
+ @at_first_point = false
38
+ end
39
+
40
+ end
@@ -0,0 +1,78 @@
1
+ # Export each tracker as a single Tracker3 node
2
+ class Tracksperanto::Export::NukeScript < Tracksperanto::Export::Base
3
+ NODE_TEMPLATE = %[
4
+ Tracker3 {
5
+ track1 {%s}
6
+ name %s
7
+ xpos 0
8
+ ypos %d
9
+ }
10
+ ]
11
+ KEYFRAME_PRECISION_TEMPLATE = "%.4f"
12
+ PREAMBLE = %[
13
+ version 5.1200
14
+ Constant {
15
+ inputs 0
16
+ channels rgb
17
+ format "1920 1080 0 0 1920 1080 1"
18
+ name CompSize_1920x1080
19
+ postage_stamp false
20
+ xpos 0
21
+ ypos -60
22
+ }]
23
+ SCHEMATIC_OFFSET = 30
24
+ class T < Array
25
+ attr_accessor :name
26
+ include ::Tracksperanto::BlockInit
27
+ end
28
+
29
+ # Should return the suffix and extension of this export file (like "_flame.stabilizer")
30
+ def self.desc_and_extension
31
+ "nuke.nk"
32
+ end
33
+
34
+ def self.human_name
35
+ "Nuke .nk script"
36
+ end
37
+
38
+ def start_export(w, h)
39
+ @io.puts(PREAMBLE.gsub(/1920/, w.to_s).gsub(/1080/, h.to_s))
40
+ @ypos = 0
41
+ end
42
+
43
+ # We accumulate a tracker and on end dump it out in one piece
44
+ def start_tracker_segment(tracker_name)
45
+ # Setup for the next tracker
46
+ @tracker = T.new
47
+ @tracker.name = tracker_name
48
+ end
49
+
50
+ def end_tracker_segment
51
+ @io.puts(
52
+ NODE_TEMPLATE % [curves_from_tuples(@tracker), @tracker.name, (@ypos += SCHEMATIC_OFFSET)]
53
+ )
54
+ end
55
+
56
+ def export_point(frame, abs_float_x, abs_float_y, float_residual)
57
+ # Nuke uses 1-based frames
58
+ @tracker << [frame + 1, abs_float_x, abs_float_y]
59
+ end
60
+
61
+ private
62
+ # Generates a couple of Nuke curves (x and y) from the passed tuples of [frame, x, y]
63
+ def curves_from_tuples(tuples)
64
+ x_values, y_values, last_frame_exported = [], [], nil
65
+ tuples.each do | t |
66
+ f = t.shift
67
+ unless last_frame_exported == (f - 1) # new section
68
+ x_values << "x#{f}"
69
+ y_values << "x#{f}"
70
+ end
71
+ t.map!{|e| KEYFRAME_PRECISION_TEMPLATE % e }
72
+ x_values << t.shift
73
+ y_values << t.shift
74
+ last_frame_exported = f
75
+ end
76
+ st = [x_values.join(" "), y_values.join(" ")].map{|e| "{curve i %s}" % e }.join(" ")
77
+ end
78
+ end
@@ -1,10 +1,16 @@
1
- class Tracksperanto::Export::Pftrack < Tracksperanto::Export::Base
1
+ # Export for PFTrack .2dt files
2
+ class Tracksperanto::Export::PFTrack < Tracksperanto::Export::Base
3
+
4
+ KEYFRAME_TEMPLATE = "%s %.3f %.3f %.3f"
2
5
 
3
- # Should return the suffix and extension of this export file (like "_flame.stabilizer")
4
6
  def self.desc_and_extension
5
7
  "pftrack.2dt"
6
8
  end
7
9
 
10
+ def self.human_name
11
+ "PFTrack .2dt file"
12
+ end
13
+
8
14
  def start_tracker_segment(tracker_name)
9
15
  # Setup for the next tracker
10
16
  @prev_tracker = []
@@ -12,21 +18,15 @@ class Tracksperanto::Export::Pftrack < Tracksperanto::Export::Base
12
18
  end
13
19
 
14
20
  def end_tracker_segment
15
- # If there was a previous tracker, write it out
16
- # - now we know how many keyframes it has
17
- if @prev_tracker && @prev_tracker.any?
18
- block = [
19
- "\n",
20
- @tracker_name.inspect, # "autoquotes"
21
- @prev_tracker.length,
22
- @prev_tracker.join("\n")
23
- ]
24
- @io.puts block.join("\n")
25
- end
21
+ block = [ "\n",
22
+ @tracker_name.inspect, # "autoquotes"
23
+ @prev_tracker.length,
24
+ @prev_tracker.join("\n") ]
25
+ @io.puts block.join("\n")
26
26
  end
27
27
 
28
28
  def export_point(frame, abs_float_x, abs_float_y, float_residual)
29
- line = "%s %.3f %.3f %.3f" % [frame, abs_float_x, abs_float_y, float_residual]
29
+ line = KEYFRAME_TEMPLATE % [frame, abs_float_x, abs_float_y, float_residual / 8]
30
30
  @prev_tracker << line
31
31
  end
32
32
  end
@@ -1,3 +1,4 @@
1
+ # Export for Shake .txt tracker blobs
1
2
  class Tracksperanto::Export::ShakeText < Tracksperanto::Export::Base
2
3
  PREAMBLE = "TrackName %s\n Frame X Y Correlation\n"
3
4
  POSTAMBLE = "\n"
@@ -7,18 +8,16 @@ class Tracksperanto::Export::ShakeText < Tracksperanto::Export::Base
7
8
  "shake_trackers.txt"
8
9
  end
9
10
 
11
+ def self.human_name
12
+ "Shake trackers in a .txt file"
13
+ end
14
+
10
15
  def start_tracker_segment(tracker_name)
11
- if @any_tracks
12
- @io.puts POSTAMBLE
13
- else
14
- @any_tracks = true
15
- end
16
-
17
16
  @io.puts PREAMBLE % tracker_name
18
17
  end
19
18
 
20
- def end_export
21
- @io << "\n"
19
+ def end_tracker_segment
20
+ @io.puts POSTAMBLE
22
21
  end
23
22
 
24
23
  def export_point(frame, abs_float_x, abs_float_y, float_residual)
@@ -1,3 +1,4 @@
1
+ # Export for Syntheyes tracker UVs
1
2
  class Tracksperanto::Export::SynthEyes < Tracksperanto::Export::Base
2
3
 
3
4
  # Should return the suffix and extension of this export file (like "_flame.stabilizer")
@@ -5,6 +6,10 @@ class Tracksperanto::Export::SynthEyes < Tracksperanto::Export::Base
5
6
  "syntheyes_2dt.txt"
6
7
  end
7
8
 
9
+ def self.human_name
10
+ "Syntheyes 2D tracker .txt file"
11
+ end
12
+
8
13
  def start_export( img_width, img_height)
9
14
  @width, @height = img_width, img_height
10
15
  end
@@ -14,7 +19,7 @@ class Tracksperanto::Export::SynthEyes < Tracksperanto::Export::Base
14
19
  end
15
20
 
16
21
  def export_point(frame, abs_float_x, abs_float_y, float_residual)
17
- values = [@tracker_name, frame] + syntheyes_coords(abs_float_x, abs_float_y)
22
+ values = [@tracker_name, frame] + syntheyes_coords(abs_float_x, abs_float_y, @width, @height)
18
23
  @io.puts("%s %d %.6f %.6f 30" % values)
19
24
  end
20
25
 
@@ -22,10 +27,9 @@ class Tracksperanto::Export::SynthEyes < Tracksperanto::Export::Base
22
27
 
23
28
  # Syntheyes wants very special coordinates, Y down X right,
24
29
  # 0 is center and values are UV float -1 to 1, doubled
25
- def syntheyes_coords(abs_x, abs_y)
26
- w, h = 2560, 1080
27
- x = (abs_x / @width.to_f) - 0.5
28
- y = (abs_y / @height.to_f) - 0.5
30
+ def syntheyes_coords(abs_x, abs_y, w, h)
31
+ x = (abs_x / w.to_f) - 0.5
32
+ y = (abs_y / h.to_f) - 0.5
29
33
  # .2 to -.3, y is reversed and coords are double
30
34
  [x * 2, y * -2]
31
35
  end