tracksperanto 1.1.1 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.DS_Store +0 -0
- data/History.txt +11 -0
- data/Manifest.txt +64 -20
- data/README.txt +82 -30
- data/Rakefile +1 -0
- data/bin/tracksperanto +21 -14
- data/lib/export/base.rb +16 -6
- data/lib/export/match_mover.rb +40 -0
- data/lib/export/nuke_script.rb +78 -0
- data/lib/export/pftrack.rb +14 -14
- data/lib/export/shake_text.rb +7 -8
- data/lib/export/syntheyes.rb +9 -5
- data/lib/import/base.rb +45 -12
- data/lib/import/flame_stabilizer.rb +17 -32
- data/lib/import/match_mover.rb +65 -0
- data/lib/import/nuke_script.rb +96 -0
- data/lib/import/pftrack.rb +9 -2
- data/lib/import/shake_grammar/catcher.rb +56 -0
- data/lib/import/shake_grammar/lexer.rb +95 -0
- data/lib/import/shake_script.rb +189 -103
- data/lib/import/shake_text.rb +5 -3
- data/lib/import/syntheyes.rb +9 -2
- data/lib/middleware/base.rb +6 -1
- data/lib/middleware/golden.rb +7 -0
- data/lib/middleware/reformat.rb +10 -3
- data/lib/middleware/scaler.rb +14 -4
- data/lib/middleware/shift.rb +10 -0
- data/lib/middleware/slipper.rb +3 -0
- data/lib/pipeline/base.rb +111 -37
- data/lib/tracksperanto/block_init.rb +7 -0
- data/lib/tracksperanto/casts.rb +31 -0
- data/lib/tracksperanto/format_detector.rb +35 -0
- data/lib/tracksperanto/keyframe.rb +31 -0
- data/lib/tracksperanto/safety.rb +20 -0
- data/lib/tracksperanto/tracker.rb +38 -0
- data/lib/tracksperanto/zip_tuples.rb +20 -0
- data/lib/tracksperanto.rb +13 -100
- data/test/.DS_Store +0 -0
- data/test/export/.DS_Store +0 -0
- data/test/export/README_EXPORT_TESTS.txt +15 -0
- data/test/export/samples/ref_NukeScript.nk +25 -0
- data/test/export/samples/ref_NukeScript.nk.autosave +77 -0
- data/test/export/samples/ref_PFTrack.2dt +50 -0
- data/test/export/samples/ref_ShakeText.txt +48 -0
- data/test/export/samples/ref_Syntheyes.txt +42 -0
- data/test/export/samples/ref_matchmover.rz2 +52 -0
- data/test/export/test_match_mover_export.rb +16 -0
- data/test/export/test_mux.rb +23 -0
- data/test/export/test_nuke_export.rb +22 -0
- data/test/export/test_pftrack_export.rb +19 -0
- data/test/export/test_shake_export.rb +15 -0
- data/test/export/test_syntheyes_export.rb +15 -0
- data/test/helper.rb +85 -2
- data/test/import/.DS_Store +0 -0
- data/test/{samples → import/samples}/.DS_Store +0 -0
- data/test/{samples → import/samples}/flyover2DP_syntheyes.txt +0 -0
- data/test/import/samples/four_tracks_in_one_matchmove.shk +323 -0
- data/test/import/samples/four_tracks_in_one_stabilizer.shk +321 -0
- data/test/{samples → import/samples}/fromCombustion_fromMidClip_wSnap.stabilizer +0 -0
- data/test/{samples → import/samples}/hugeFlameSetup.stabilizer +0 -0
- data/test/import/samples/kipPointsMatchmover.rz2 +523 -0
- data/test/{samples → import/samples}/megaTrack.action.3dtrack.stabilizer +0 -0
- data/test/{samples → import/samples}/one_shake_tracker.txt +0 -0
- data/test/{samples → import/samples}/one_shake_tracker_from_first.txt +0 -0
- data/test/import/samples/one_tracker_with_break.nk +71 -0
- data/test/import/samples/one_tracker_with_break_in_grp.nk +91 -0
- data/test/{samples → import/samples}/shake_tracker_nodes.shk +0 -0
- data/test/{samples → import/samples}/shake_tracker_nodes_to_syntheyes.txt +0 -0
- data/test/{samples → import/samples}/sourcefile_pftrack.2dt +0 -0
- data/test/{samples → import/samples}/three_tracks_in_one_stabilizer.shk +0 -0
- data/test/{samples → import/samples}/two_shake_trackers.txt +0 -0
- data/test/{samples → import/samples}/two_tracks_in_one_tracker.shk +0 -0
- data/test/{test_flame_import.rb → import/test_flame_import.rb} +15 -9
- data/test/import/test_match_mover_import.rb +44 -0
- data/test/import/test_nuke_import.rb +63 -0
- data/test/{test_pftrack_import.rb → import/test_pftrack_import.rb} +10 -4
- data/test/import/test_shake_catcher.rb +72 -0
- data/test/import/test_shake_lexer.rb +95 -0
- data/test/import/test_shake_script_import.rb +75 -0
- data/test/{test_shake_text_import.rb → import/test_shake_text_import.rb} +10 -3
- data/test/{test_syntheyes_import.rb → import/test_syntheyes_import.rb} +8 -3
- data/test/middleware/test_golden_middleware.rb +32 -0
- data/test/middleware/test_reformat_middleware.rb +35 -0
- data/test/middleware/test_scaler_middleware.rb +51 -0
- data/test/middleware/test_shift_middleware.rb +26 -0
- data/test/middleware/test_slip_middleware.rb +31 -0
- data/test/pipeline/test_pipeline_base.rb +14 -0
- data/test/test_format_detector.rb +39 -0
- data/test/test_tracker.rb +48 -0
- data/tracksperanto.gemspec +9 -7
- metadata +101 -30
- data/lib/middleware/close.rb +0 -6
- data/test/test_shake_export.rb +0 -58
- 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/
|
30
|
-
test/samples
|
31
|
-
test/samples/
|
32
|
-
test/samples/
|
33
|
-
test/samples/
|
34
|
-
test/samples/
|
35
|
-
test/samples/
|
36
|
-
test/samples/
|
37
|
-
test/samples/
|
38
|
-
test/samples/
|
39
|
-
test/samples/
|
40
|
-
test/samples/
|
41
|
-
test/samples/
|
42
|
-
test/
|
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/
|
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
|
-
|
11
|
-
*
|
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
|
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
|
-
|
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
|
35
|
-
but you need some operation applied to the result (like
|
36
|
-
|
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
|
-
|
39
|
-
|
40
|
-
|
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
|
-
==
|
93
|
+
== Importing your own formats
|
43
94
|
|
44
|
-
|
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
|
-
|
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
|
-
|
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
|
55
|
-
these differently, if at all). For some
|
56
|
-
|
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 =
|
18
|
-
width =
|
19
|
-
height =
|
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
|
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,
|
33
|
-
#{
|
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.
|
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 "
|
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,
|
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
|
data/lib/export/pftrack.rb
CHANGED
@@ -1,10 +1,16 @@
|
|
1
|
-
|
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
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
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 =
|
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
|
data/lib/export/shake_text.rb
CHANGED
@@ -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
|
21
|
-
@io
|
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)
|
data/lib/export/syntheyes.rb
CHANGED
@@ -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
|
-
|
27
|
-
|
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
|