photoscan_outputs 0.0.1

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 25904f3b8fba33b0149a2e7340a8c5c906838ea0
4
+ data.tar.gz: dff0ab70fbb174768344fd99c0b0a1bea6c5ae28
5
+ SHA512:
6
+ metadata.gz: f050e0944859cc8522c46cac44da3f126ab98f57800297cc5453fe5daead51d0956502648859209b8065b55557a46c77486e26c4756cddb2c2e307a4d5c9f564
7
+ data.tar.gz: 5650def2dfe939aeab7aee087214043a4473a81fb4646dbb2c65f66ec2f2393d4977357aa9f2534cfcd10c61560082fd018fb58437d9de29f679372ccfcb343f
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in photoscan.gemspec
4
+ gemspec
5
+
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Aaron Marburg
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,33 @@
1
+ # photoscan_outputs
2
+
3
+ A simple gem to load and parse the various output files which are generate
4
+ by the [Photoscan](http://www.agisoft.ru/products/photoscan/)
5
+ reconstruction/photogrammetry software from
6
+ [Agisoft.](http://www.agisoft.ru)
7
+
8
+ Please note I am currently testing against Photoscan Professional
9
+ version 0.9.0.1586.
10
+
11
+ At present the Gem only parses the camera XML files generated by "Export
12
+ -> Cameras" (sorry, it's all I need at this point). I'm happy to merge
13
+ in support for the other export (and import) file formats.
14
+
15
+
16
+ ## Installation
17
+
18
+ Add this line to your application's Gemfile:
19
+
20
+ gem 'photoscan_outputs'
21
+
22
+ And then execute:
23
+
24
+ $ bundle
25
+
26
+ Or install it yourself as:
27
+
28
+ $ gem install photoscan_outputs
29
+
30
+ ## Usage
31
+
32
+ See the demo applications in demo/
33
+
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ task :default => :test
5
+
6
+ Rake::TestTask.new do |t|
7
+ t.libs.push "lib"
8
+ t.test_files = FileList['test/*_test.rb']
9
+ t.verbose = true
10
+ end
data/demo/cameras.xml ADDED
@@ -0,0 +1,299 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <collection>
3
+ <cameras>
4
+ <camera label="IMG_7618.jpg">
5
+ <resolution width="972" height="648"/>
6
+ <calibration>
7
+ <width>972</width>
8
+ <height>648</height>
9
+ <fx>1.8707469131103019e+003</fx>
10
+ <fy>1.8738616128634769e+003</fy>
11
+ <cx>5.2586579873845619e+002</cx>
12
+ <cy>4.0083738488303931e+002</cy>
13
+ <skew>-8.6319592049510652e-001</skew>
14
+ <k1>-1.6675726916786160e-001</k1>
15
+ <k2>7.5676071357423513e-001</k2>
16
+ <k3>-2.1665527393930941e+000</k3>
17
+ <p1>-1.4556415480751863e-003</p1>
18
+ <p2>-5.2912191800171066e-005</p2>
19
+ </calibration>
20
+ <transform>9.9683301478165265e-001 -3.1558264817455866e-003 -7.9460565065562733e-002 7.0737615896838760e-002 -3.8926618731656795e-004 9.9900665522955223e-001 -4.4559525119754598e-002 -4.0025763682849508e-001 7.9522255458184948e-002 4.4449337073568851e-002 9.9584158746286722e-001 2.0569299557796403e-001 0.0000000000000000e+000 0.0000000000000000e+000 0.0000000000000000e+000 1.0000000000000000e+000</transform>
21
+ </camera>
22
+ <camera label="IMG_7619.jpg">
23
+ <resolution width="972" height="648"/>
24
+ <calibration>
25
+ <width>972</width>
26
+ <height>648</height>
27
+ <fx>1.8707469131103019e+003</fx>
28
+ <fy>1.8738616128634769e+003</fy>
29
+ <cx>5.2586579873845619e+002</cx>
30
+ <cy>4.0083738488303931e+002</cy>
31
+ <skew>-8.6319592049510652e-001</skew>
32
+ <k1>-1.6675726916786160e-001</k1>
33
+ <k2>7.5676071357423513e-001</k2>
34
+ <k3>-2.1665527393930941e+000</k3>
35
+ <p1>-1.4556415480751863e-003</p1>
36
+ <p2>-5.2912191800171066e-005</p2>
37
+ </calibration>
38
+ <transform>9.9995079112895813e-001 -2.4330375639054305e-003 -9.6174658192002774e-003 3.4813301046660902e-002 1.8212922240356147e-003 9.9800476908715929e-001 -6.3112310795284288e-002 -2.1875746956572956e-001 9.7518313770044215e-003 6.3091688894009762e-002 9.9796008967157401e-001 2.2311358197820985e-001 0.0000000000000000e+000 0.0000000000000000e+000 0.0000000000000000e+000 1.0000000000000000e+000</transform>
39
+ </camera>
40
+ <camera label="IMG_7620.jpg">
41
+ <resolution width="972" height="648"/>
42
+ <calibration>
43
+ <width>972</width>
44
+ <height>648</height>
45
+ <fx>1.8707469131103019e+003</fx>
46
+ <fy>1.8738616128634769e+003</fy>
47
+ <cx>5.2586579873845619e+002</cx>
48
+ <cy>4.0083738488303931e+002</cy>
49
+ <skew>-8.6319592049510652e-001</skew>
50
+ <k1>-1.6675726916786160e-001</k1>
51
+ <k2>7.5676071357423513e-001</k2>
52
+ <k3>-2.1665527393930941e+000</k3>
53
+ <p1>-1.4556415480751863e-003</p1>
54
+ <p2>-5.2912191800171066e-005</p2>
55
+ </calibration>
56
+ <transform>9.9969511729032934e-001 4.4396443170881326e-004 -2.4687554788964932e-002 6.0846460822818978e-002 -2.1107747184909492e-003 9.9771492720697230e-001 -6.7531242091891541e-002 -5.0158941809979991e-002 2.4601160459672370e-002 6.7562762850325031e-002 9.9741167828538491e-001 2.4972906063642900e-001 0.0000000000000000e+000 0.0000000000000000e+000 0.0000000000000000e+000 1.0000000000000000e+000</transform>
57
+ </camera>
58
+ <camera label="IMG_7621.jpg">
59
+ <resolution width="972" height="648"/>
60
+ <calibration>
61
+ <width>972</width>
62
+ <height>648</height>
63
+ <fx>1.8707469131103019e+003</fx>
64
+ <fy>1.8738616128634769e+003</fy>
65
+ <cx>5.2586579873845619e+002</cx>
66
+ <cy>4.0083738488303931e+002</cy>
67
+ <skew>-8.6319592049510652e-001</skew>
68
+ <k1>-1.6675726916786160e-001</k1>
69
+ <k2>7.5676071357423513e-001</k2>
70
+ <k3>-2.1665527393930941e+000</k3>
71
+ <p1>-1.4556415480751863e-003</p1>
72
+ <p2>-5.2912191800171066e-005</p2>
73
+ </calibration>
74
+ <transform>9.9652890103780079e-001 1.7698078703274452e-002 -8.1344498317991759e-002 1.1882692862157447e-001 -2.5270727403893904e-002 9.9534269889267679e-001 -9.3028501533241145e-002 1.3134349940164564e-001 7.9319226754117733e-002 9.4761225040914651e-002 9.9233500920600093e-001 2.8755965252008003e-001 0.0000000000000000e+000 0.0000000000000000e+000 0.0000000000000000e+000 1.0000000000000000e+000</transform>
75
+ </camera>
76
+ <camera label="IMG_7622.jpg">
77
+ <resolution width="972" height="648"/>
78
+ <calibration>
79
+ <width>972</width>
80
+ <height>648</height>
81
+ <fx>1.8707469131103019e+003</fx>
82
+ <fy>1.8738616128634769e+003</fy>
83
+ <cx>5.2586579873845619e+002</cx>
84
+ <cy>4.0083738488303931e+002</cy>
85
+ <skew>-8.6319592049510652e-001</skew>
86
+ <k1>-1.6675726916786160e-001</k1>
87
+ <k2>7.5676071357423513e-001</k2>
88
+ <k3>-2.1665527393930941e+000</k3>
89
+ <p1>-1.4556415480751863e-003</p1>
90
+ <p2>-5.2912191800171066e-005</p2>
91
+ </calibration>
92
+ <transform>9.9940441433919347e-001 2.3013627842912800e-002 -2.5713605986746095e-002 9.6489185048266493e-002 -2.5744744369210006e-002 9.9343141192277939e-001 -1.1149546153309167e-001 3.1093616503153787e-001 2.2978788843142833e-002 1.1209104664789693e-001 9.9343221838466722e-001 3.1312932753838985e-001 0.0000000000000000e+000 0.0000000000000000e+000 0.0000000000000000e+000 1.0000000000000000e+000</transform>
93
+ </camera>
94
+ <camera label="IMG_7623.jpg">
95
+ <resolution width="972" height="648"/>
96
+ <calibration>
97
+ <width>972</width>
98
+ <height>648</height>
99
+ <fx>1.8707469131103019e+003</fx>
100
+ <fy>1.8738616128634769e+003</fy>
101
+ <cx>5.2586579873845619e+002</cx>
102
+ <cy>4.0083738488303931e+002</cy>
103
+ <skew>-8.6319592049510652e-001</skew>
104
+ <k1>-1.6675726916786160e-001</k1>
105
+ <k2>7.5676071357423513e-001</k2>
106
+ <k3>-2.1665527393930941e+000</k3>
107
+ <p1>-1.4556415480751863e-003</p1>
108
+ <p2>-5.2912191800171066e-005</p2>
109
+ </calibration>
110
+ <transform>9.9998256428382182e-001 4.6421242458977979e-003 3.6499055929911646e-003 8.9851705873163254e-002 -4.3536680975287036e-003 9.9714252885660992e-001 -7.5417655224366026e-002 4.3675109307960908e-001 -3.9895742189688848e-003 7.5400449785995527e-002 9.9714535323072173e-001 3.3400276497949261e-001 0.0000000000000000e+000 0.0000000000000000e+000 0.0000000000000000e+000 1.0000000000000000e+000</transform>
111
+ </camera>
112
+ <camera label="IMG_7624.jpg">
113
+ <resolution width="972" height="648"/>
114
+ <calibration>
115
+ <width>972</width>
116
+ <height>648</height>
117
+ <fx>1.8707469131103019e+003</fx>
118
+ <fy>1.8738616128634769e+003</fy>
119
+ <cx>5.2586579873845619e+002</cx>
120
+ <cy>4.0083738488303931e+002</cy>
121
+ <skew>-8.6319592049510652e-001</skew>
122
+ <k1>-1.6675726916786160e-001</k1>
123
+ <k2>7.5676071357423513e-001</k2>
124
+ <k3>-2.1665527393930941e+000</k3>
125
+ <p1>-1.4556415480751863e-003</p1>
126
+ <p2>-5.2912191800171066e-005</p2>
127
+ </calibration>
128
+ <transform>9.9889233961272583e-001 1.2323952477504905e-002 -4.5411607088353505e-002 1.4646016411805665e-001 -1.7154733175385028e-002 9.9404904382007031e-001 -1.0757422372522733e-001 6.1565656251444423e-001 4.3815624983516342e-002 1.0823409202158125e-001 9.9315938918764080e-001 3.7565540950423082e-001 0.0000000000000000e+000 0.0000000000000000e+000 0.0000000000000000e+000 1.0000000000000000e+000</transform>
129
+ </camera>
130
+ <camera label="IMG_7625.jpg">
131
+ <resolution width="972" height="648"/>
132
+ <calibration>
133
+ <width>972</width>
134
+ <height>648</height>
135
+ <fx>1.8707469131103019e+003</fx>
136
+ <fy>1.8738616128634769e+003</fy>
137
+ <cx>5.2586579873845619e+002</cx>
138
+ <cy>4.0083738488303931e+002</cy>
139
+ <skew>-8.6319592049510652e-001</skew>
140
+ <k1>-1.6675726916786160e-001</k1>
141
+ <k2>7.5676071357423513e-001</k2>
142
+ <k3>-2.1665527393930941e+000</k3>
143
+ <p1>-1.4556415480751863e-003</p1>
144
+ <p2>-5.2912191800171066e-005</p2>
145
+ </calibration>
146
+ <transform>9.9953421365070405e-001 -6.9992773541669769e-003 -2.9704643714209611e-002 1.4954104635287307e-001 2.4167515690802673e-003 9.8844141937373331e-001 -1.5158403536749149e-001 8.0508275964818365e-001 3.0422278900865324e-002 1.5144164084874084e-001 9.8799793236803835e-001 4.1429005269516289e-001 0.0000000000000000e+000 0.0000000000000000e+000 0.0000000000000000e+000 1.0000000000000000e+000</transform>
147
+ </camera>
148
+ <camera label="IMG_7626.jpg">
149
+ <resolution width="972" height="648"/>
150
+ <calibration>
151
+ <width>972</width>
152
+ <height>648</height>
153
+ <fx>1.8707469131103019e+003</fx>
154
+ <fy>1.8738616128634769e+003</fy>
155
+ <cx>5.2586579873845619e+002</cx>
156
+ <cy>4.0083738488303931e+002</cy>
157
+ <skew>-8.6319592049510652e-001</skew>
158
+ <k1>-1.6675726916786160e-001</k1>
159
+ <k2>7.5676071357423513e-001</k2>
160
+ <k3>-2.1665527393930941e+000</k3>
161
+ <p1>-1.4556415480751863e-003</p1>
162
+ <p2>-5.2912191800171066e-005</p2>
163
+ </calibration>
164
+ <transform>9.9942928868384739e-001 -3.1607953746682869e-002 -1.1917809397974041e-002 1.4989577460907832e-001 2.9829737771353587e-002 9.9136114115572971e-001 -1.2772342992145849e-001 9.4489958557760867e-001 1.5851929390177176e-002 1.2729503158551395e-001 9.9173821710583077e-001 4.4156530649216508e-001 0.0000000000000000e+000 0.0000000000000000e+000 0.0000000000000000e+000 1.0000000000000000e+000</transform>
165
+ </camera>
166
+ <camera label="IMG_7652.jpg">
167
+ <resolution width="972" height="648"/>
168
+ <calibration>
169
+ <width>972</width>
170
+ <height>648</height>
171
+ <fx>1.8707469131103019e+003</fx>
172
+ <fy>1.8738616128634769e+003</fy>
173
+ <cx>5.2586579873845619e+002</cx>
174
+ <cy>4.0083738488303931e+002</cy>
175
+ <skew>-8.6319592049510652e-001</skew>
176
+ <k1>-1.6675726916786160e-001</k1>
177
+ <k2>7.5676071357423513e-001</k2>
178
+ <k3>-2.1665527393930941e+000</k3>
179
+ <p1>-1.4556415480751863e-003</p1>
180
+ <p2>-5.2912191800171066e-005</p2>
181
+ </calibration>
182
+ <transform>-9.7820830084418986e-001 -1.6610725820767722e-001 -1.2456684522877992e-001 3.4887451129890107e-001 2.0010400438170020e-001 -9.1427099603148332e-001 -3.5223136323446241e-001 1.3383829123060498e+000 -5.5379667658187248e-002 -3.6948196787709048e-001 9.2758620506330358e-001 4.9061174685682785e-001 0.0000000000000000e+000 0.0000000000000000e+000 0.0000000000000000e+000 1.0000000000000000e+000</transform>
183
+ </camera>
184
+ <camera label="IMG_7653.jpg">
185
+ <resolution width="972" height="648"/>
186
+ <calibration>
187
+ <width>972</width>
188
+ <height>648</height>
189
+ <fx>1.8707469131103019e+003</fx>
190
+ <fy>1.8738616128634769e+003</fy>
191
+ <cx>5.2586579873845619e+002</cx>
192
+ <cy>4.0083738488303931e+002</cy>
193
+ <skew>-8.6319592049510652e-001</skew>
194
+ <k1>-1.6675726916786160e-001</k1>
195
+ <k2>7.5676071357423513e-001</k2>
196
+ <k3>-2.1665527393930941e+000</k3>
197
+ <p1>-1.4556415480751863e-003</p1>
198
+ <p2>-5.2912191800171066e-005</p2>
199
+ </calibration>
200
+ <transform>-9.7839987037768705e-001 -1.8455517231586849e-001 -9.3129383206296934e-002 2.9565895830542449e-001 2.0625061786669885e-001 -9.0188359314954736e-001 -3.7956115059008172e-001 1.2041343917721126e+000 -1.3941889202334377e-002 -3.9057057336558504e-001 9.2046740895392332e-001 4.5444368890461845e-001 0.0000000000000000e+000 0.0000000000000000e+000 0.0000000000000000e+000 1.0000000000000000e+000</transform>
201
+ </camera>
202
+ <camera label="IMG_7654.jpg">
203
+ <resolution width="972" height="648"/>
204
+ <calibration>
205
+ <width>972</width>
206
+ <height>648</height>
207
+ <fx>1.8707469131103019e+003</fx>
208
+ <fy>1.8738616128634769e+003</fy>
209
+ <cx>5.2586579873845619e+002</cx>
210
+ <cy>4.0083738488303931e+002</cy>
211
+ <skew>-8.6319592049510652e-001</skew>
212
+ <k1>-1.6675726916786160e-001</k1>
213
+ <k2>7.5676071357423513e-001</k2>
214
+ <k3>-2.1665527393930941e+000</k3>
215
+ <p1>-1.4556415480751863e-003</p1>
216
+ <p2>-5.2912191800171066e-005</p2>
217
+ </calibration>
218
+ <transform>-9.7550502444367981e-001 -1.9892699298582306e-001 -9.3904199835545377e-002 2.7479539563603050e-001 2.1874772718137020e-001 -9.2229516787832622e-001 -3.1862368895183385e-001 9.8816550707499695e-001 -2.3224537414565684e-002 -3.3136033976610485e-001 9.4321839787610706e-001 3.9697273531447702e-001 0.0000000000000000e+000 0.0000000000000000e+000 0.0000000000000000e+000 1.0000000000000000e+000</transform>
219
+ </camera>
220
+ <camera label="IMG_7655.jpg">
221
+ <resolution width="972" height="648"/>
222
+ <calibration>
223
+ <width>972</width>
224
+ <height>648</height>
225
+ <fx>1.8707469131103019e+003</fx>
226
+ <fy>1.8738616128634769e+003</fy>
227
+ <cx>5.2586579873845619e+002</cx>
228
+ <cy>4.0083738488303931e+002</cy>
229
+ <skew>-8.6319592049510652e-001</skew>
230
+ <k1>-1.6675726916786160e-001</k1>
231
+ <k2>7.5676071357423513e-001</k2>
232
+ <k3>-2.1665527393930941e+000</k3>
233
+ <p1>-1.4556415480751863e-003</p1>
234
+ <p2>-5.2912191800171066e-005</p2>
235
+ </calibration>
236
+ <transform>-9.7180956362178894e-001 -1.9439190618113866e-001 -1.3340899094323269e-001 2.7804858706995900e-001 2.2216153649895798e-001 -9.4446757821157656e-001 -2.4212650703213340e-001 7.6645869949757039e-001 -7.8933033348847853e-002 -2.6493920155088974e-001 9.6102902959688330e-001 3.5012064711110896e-001 0.0000000000000000e+000 0.0000000000000000e+000 0.0000000000000000e+000 1.0000000000000000e+000</transform>
237
+ </camera>
238
+ <camera label="IMG_7656.jpg">
239
+ <resolution width="972" height="648"/>
240
+ <calibration>
241
+ <width>972</width>
242
+ <height>648</height>
243
+ <fx>1.8707469131103019e+003</fx>
244
+ <fy>1.8738616128634769e+003</fy>
245
+ <cx>5.2586579873845619e+002</cx>
246
+ <cy>4.0083738488303931e+002</cy>
247
+ <skew>-8.6319592049510652e-001</skew>
248
+ <k1>-1.6675726916786160e-001</k1>
249
+ <k2>7.5676071357423513e-001</k2>
250
+ <k3>-2.1665527393930941e+000</k3>
251
+ <p1>-1.4556415480751863e-003</p1>
252
+ <p2>-5.2912191800171066e-005</p2>
253
+ </calibration>
254
+ <transform>-9.7464812449045679e-001 -1.5623188378533115e-001 -1.6016439028736024e-001 2.7971726219048454e-001 1.9165133687418667e-001 -9.5234540151881220e-001 -2.3729307044309017e-001 6.0996542075537263e-001 -1.1545907717270255e-001 -2.6197296558015126e-001 9.5814370884725242e-001 3.2255907578697951e-001 0.0000000000000000e+000 0.0000000000000000e+000 0.0000000000000000e+000 1.0000000000000000e+000</transform>
255
+ </camera>
256
+ <camera label="IMG_7657.jpg">
257
+ <resolution width="972" height="648"/>
258
+ <calibration>
259
+ <width>972</width>
260
+ <height>648</height>
261
+ <fx>1.8707469131103019e+003</fx>
262
+ <fy>1.8738616128634769e+003</fy>
263
+ <cx>5.2586579873845619e+002</cx>
264
+ <cy>4.0083738488303931e+002</cy>
265
+ <skew>-8.6319592049510652e-001</skew>
266
+ <k1>-1.6675726916786160e-001</k1>
267
+ <k2>7.5676071357423513e-001</k2>
268
+ <k3>-2.1665527393930941e+000</k3>
269
+ <p1>-1.4556415480751863e-003</p1>
270
+ <p2>-5.2912191800171066e-005</p2>
271
+ </calibration>
272
+ <transform>-9.7955798936859784e-001 -9.9802520741764128e-002 -1.7465853061828876e-001 2.8145559243671753e-001 1.4642368683748003e-001 -9.4909870698574350e-001 -2.7887586545075799e-001 4.8948776405639516e-001 -1.3793567122782105e-001 -2.9874922803511889e-001 9.4431067416997450e-001 2.9676650737131621e-001 0.0000000000000000e+000 0.0000000000000000e+000 0.0000000000000000e+000 1.0000000000000000e+000</transform>
273
+ </camera>
274
+ <camera label="IMG_7658.jpg">
275
+ <resolution width="972" height="648"/>
276
+ <calibration>
277
+ <width>972</width>
278
+ <height>648</height>
279
+ <fx>1.8707469131103019e+003</fx>
280
+ <fy>1.8738616128634769e+003</fy>
281
+ <cx>5.2586579873845619e+002</cx>
282
+ <cy>4.0083738488303931e+002</cy>
283
+ <skew>-8.6319592049510652e-001</skew>
284
+ <k1>-1.6675726916786160e-001</k1>
285
+ <k2>7.5676071357423513e-001</k2>
286
+ <k3>-2.1665527393930941e+000</k3>
287
+ <p1>-1.4556415480751863e-003</p1>
288
+ <p2>-5.2912191800171066e-005</p2>
289
+ </calibration>
290
+ <transform>-9.7946896579623943e-001 -1.5342530714685727e-002 -2.0101032757874407e-001 3.0616146468203392e-001 7.1705812807688535e-002 -9.5840694057764930e-001 -2.7625063377697240e-001 3.0789882933411478e-001 -1.8841130924558061e-001 -2.8499253148786047e-001 9.3983000353495205e-001 2.6267990531094587e-001 0.0000000000000000e+000 0.0000000000000000e+000 0.0000000000000000e+000 1.0000000000000000e+000</transform>
291
+ </camera>
292
+ </cameras>
293
+ <transform>2.7694900329729840e+001 2.5392011594365184e+002 5.4118470162177800e+001 6.6670066415987478e+005 2.5949821314888629e+002 -2.8762442620351280e+001 2.1542666622218207e+000 5.4456422027225094e+006 8.0567652359546997e+000 5.3558736089261856e+001 -2.5541689826685177e+002 4.6848797492713061e+002 0.0000000000000000e+000 0.0000000000000000e+000 0.0000000000000000e+000 1.0000000000000000e+000</transform>
294
+ <region>
295
+ <center>4.6769198108370075e-002 1.6672089950935109e-001 1.8757319005504849e+000</center>
296
+ <size>2.0527148246765137e+000 1.1775308847427368e+000 2.6224559545516968e-001</size>
297
+ <R>-1.8076817302331005e-001 -9.6340638630316500e-001 -1.9791665531756450e-001 -9.8137346285726212e-001 1.8998827486136224e-001 -2.8470718549935770e-002 6.5030715983763018e-002 1.8908355360919263e-001 -9.7980529480767686e-001</R>
298
+ </region>
299
+ </collection>
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "trollop"
4
+ require "ox"
5
+ require "pathname"
6
+
7
+ require "photoscan_outputs"
8
+ include PhotoscanOutputs
9
+
10
+ opts = Trollop.options do
11
+ opt :camera_file, "Location of camera file.", :default => Pathname.new(__FILE__).parent.join("cameras.xml").to_s
12
+ end
13
+
14
+ Trollop::die "Can't find camera file #{opts[:camera_file]}" unless File.readable? opts[:camera_file]
15
+
16
+ cameras = CameraFile.load( opts[:camera_file] )
17
+
18
+ unless ARGV.length > 0
19
+ puts "Specify name(s) of cameras to show on the command line. Since you haven't specified a camera, I'll show you \"IMG_7625.jpg\""
20
+ ARGV.push "IMG_7625.jpg"
21
+ end
22
+
23
+ ARGV.each { |camera_name|
24
+
25
+ cam = cameras.find_by_name camera_name
26
+
27
+ unless cam
28
+ puts "Couldn't find a camera named \"#{camera_name}\""
29
+ next
30
+ end
31
+
32
+ cam.dump
33
+ }
data/demo/point ADDED
@@ -0,0 +1,70 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ #
4
+
5
+ require "trollop"
6
+ require "ox"
7
+ require "photoscan_outputs"
8
+ include PhotoscanOutputs
9
+
10
+
11
+ opts = Trollop.options do
12
+ opt :camera_file, "Location of camera file.", :default => Pathname.new(__FILE__).parent.join("cameras.xml").to_s
13
+ end
14
+
15
+ class Matrix
16
+ def print( opts = {} )
17
+ puts opts[:caption] if opts[:caption]
18
+ to_a.each { |row|
19
+ puts row.map { |x| "%12.4f" % x }.join(' ')
20
+ }
21
+ end
22
+ end
23
+
24
+ class Vector
25
+ def print( opts = {} )
26
+ puts opts[:caption] if opts[:caption]
27
+ puts to_a.map { |x| "%12.4f" % x }.join(' ')
28
+ end
29
+ end
30
+
31
+
32
+ raise "Can't find #{opts[:camera_file]}" unless File.readable? opts[:camera_file]
33
+
34
+ cameras = CameraFile.load( opts[:camera_file] )
35
+
36
+ name = "IMG_7622.jpg"
37
+ cam = cameras.find_by_name( name )
38
+ Trollop::die "Can't find image #{name}" unless cam
39
+
40
+ puts "Camera projection matrix is"
41
+ cam.calibration.k.print
42
+
43
+ puts "Total transform from camera to world origin is"
44
+ cam.transform.dump
45
+
46
+ # From the model used to generate cameras.xml, I know the ground control point "P1"
47
+ # appears in IMG_7622.jpg at "img_pt"
48
+ p1 = Vector[ 666813.226289, 5445609.922365, 0.782823, 1 ]
49
+ img_pt = Vector[299.3, 306.8, 1]
50
+
51
+ puts
52
+ p1.print(caption: "The control point at")
53
+ img_pt.print(caption: "appears in the image at:")
54
+
55
+ puts "Transform from world to body is then:"
56
+ world_to_body = cam.transform.inv
57
+ world_to_body.dump
58
+
59
+ p1_b = world_to_body * p1
60
+ p1_b.print(caption: "The control point in the body frame is")
61
+
62
+ # Convert to inhomogeneous quantity
63
+ p1_b_inhom = Vector.elements( p1_b.to_a.first(3) )
64
+ p1_img = cam.calibration.k * p1_b_inhom
65
+ p1_img = p1_img.map { |x| x / p1_img[2] }
66
+
67
+ p1_img.print(caption: "It appears at the image at:")
68
+
69
+
70
+
@@ -0,0 +1,175 @@
1
+ require "matrix"
2
+
3
+ module PhotoscanOutputs
4
+
5
+ def print_mat( mat, io = STDOUT )
6
+ mat.to_a.each { |row| io.puts row.map { |x| "% 10.5f" % x }.join(' ') }
7
+ end
8
+
9
+ class Calibration
10
+ attr_accessor :fx, :fy, :cx, :cy, :skew
11
+
12
+ def initialize( fx, fy, cx, cy, skew )
13
+ @fx = fx
14
+ @fy = fy
15
+ @cx = cx
16
+ @cy = cy
17
+ @skew = skew
18
+ end
19
+
20
+ def k
21
+ Matrix.rows [ [ @fx, @skew, @cx ], [ 0, @fy, @cy ], [0,0,1] ]
22
+ end
23
+
24
+ def dump( io )
25
+ [ :fx, :fy, :cx, :cy, :skew ].each { |key|
26
+ io.puts " %10s: %10f" % [key.to_s, send(key)]
27
+ }
28
+ io.puts "Camera projection matrix:"
29
+ print_mat( k, io )
30
+ end
31
+
32
+
33
+ def self.from_xml( xml )
34
+ Calibration.new( xml.fx.text.to_f, xml.fy.text.to_f,
35
+ xml.cx.text.to_f, xml.cy.text.to_f,
36
+ xml.skew.text.to_f )
37
+ end
38
+ end
39
+
40
+ class Resolution
41
+ attr_reader :h, :w
42
+ alias_method :height, :h
43
+ alias_method :width, :w
44
+
45
+ def initialize( w, h )
46
+ @w = w
47
+ @h = h
48
+ end
49
+
50
+ def self.from_xml( xml )
51
+ w = xml.width
52
+ h = xml.height
53
+ Resolution.new( w, h )
54
+ end
55
+ end
56
+
57
+ # "Transform" is the 3D homogeneous transform from camera to world.
58
+ # That is, T * [0 0 0 1]^T (the origin of the camera frame)
59
+ # yields the camera's position in world coordinate frame
60
+ #
61
+ # Or
62
+ #
63
+ # R T
64
+ # 0 1
65
+ #
66
+ class Transform
67
+ attr_reader :mat
68
+
69
+ def initialize( mat, opts = {} )
70
+ @mat = case mat
71
+ when Transform
72
+ mat.mat
73
+ else
74
+ mat
75
+ end
76
+ end
77
+
78
+ def r_mat
79
+ Matrix.rows mat.to_a.first(3).map { |row| row.first(3) }
80
+ end
81
+
82
+ def t_mat
83
+ Vector[ *( mat.to_a.first(3).map { |row| row.at(3) } ) ]
84
+ end
85
+
86
+ def t
87
+ t_mat
88
+ end
89
+
90
+ def inv
91
+ Transform.new mat.inv
92
+ end
93
+
94
+ def *(b)
95
+ mat * b
96
+ end
97
+
98
+
99
+ def dump( io = STDOUT )
100
+ print_mat( mat, io )
101
+ end
102
+
103
+ def self.from_xml( xml, global = nil )
104
+ m = xml.text.split(/\s/).map(&:to_f)
105
+ raise "Not enough elements in matrix" unless m.length == 16
106
+
107
+ arr = 4.times.map { m.shift(4) }
108
+
109
+ if global
110
+ IncrementalTransform.new( global.mat, Matrix.rows(arr) )
111
+ else
112
+ Transform.new( Matrix.rows( arr ) )
113
+ end
114
+ end
115
+ end
116
+
117
+ class IncrementalTransform < Transform
118
+ def initialize( global, increment )
119
+ @global = global
120
+ @increment = increment
121
+ super (@global * @increment)
122
+ end
123
+
124
+ def global; Transform.new @global; end
125
+ def incremental; Transform.new @increment; end
126
+
127
+ def dump( io = STDOUT )
128
+ io.puts "Incremental transform:"
129
+ io.puts " increment:"
130
+ print_mat( @increment )
131
+ io.puts " global:"
132
+ print_mat( @global )
133
+ io.puts " total transform:"
134
+ print_mat mat
135
+ end
136
+ end
137
+
138
+ class Camera
139
+ attr_reader :name, :resolution, :transform, :calibration
140
+
141
+ def initialize( label, resolution, calibration, transform )
142
+ @name = label
143
+ @resolution = resolution
144
+ @calibration = calibration
145
+ @transform = transform
146
+ end
147
+
148
+ alias_method :body_to_world, :transform
149
+
150
+ def world_to_body
151
+ transform.inv
152
+ end
153
+
154
+ def dump( io = STDOUT )
155
+ io.puts "Camera \"#{name}\""
156
+ io.puts "Resolution: %d x %d" % [resolution.width, resolution.height]
157
+ io.puts "Calibration:"
158
+ calibration.dump io
159
+
160
+ io.puts "Body-to-world transform"
161
+ body_to_world.dump( io )
162
+ end
163
+
164
+
165
+
166
+ def self.from_xml( xml, global )
167
+ # Leverage Ox::Element's method_missing support
168
+ res = Resolution.from_xml xml.resolution
169
+ trans = Transform.from_xml xml.transform, global
170
+ calib = Calibration.from_xml xml.calibration
171
+
172
+ Camera.new( xml.label, res, calib, trans )
173
+ end
174
+ end
175
+ end
@@ -0,0 +1,49 @@
1
+
2
+ require "ox"
3
+ require "photoscan_outputs/camera"
4
+
5
+ module PhotoscanOutputs
6
+
7
+ class CameraFile
8
+ attr_reader :cameras, :global_transform
9
+
10
+ include Enumerable
11
+
12
+ def initialize( cameras, global )
13
+ @cameras = cameras
14
+ @global_transform = global
15
+ end
16
+
17
+ def find_by_name( name )
18
+ find { |cam| cam.name == name }
19
+ end
20
+
21
+ def each
22
+ if block_given?
23
+ @cameras.each { |blk| yield blk }
24
+ else
25
+ @cameras.each
26
+ end
27
+ end
28
+
29
+
30
+ def self.load( file )
31
+ raise "Can't read file \"#{file}\"" unless File.readable? file
32
+
33
+ xml = Ox.load File.read( file )
34
+
35
+ cameras = xml.locate("collection/cameras").first.nodes
36
+
37
+ global = Transform.from_xml xml.locate("collection").first.transform
38
+
39
+ cameras.map! { |cam|
40
+ Camera.from_xml( cam, global )
41
+ }
42
+
43
+ CameraFile.new( cameras, global )
44
+ end
45
+
46
+ end
47
+ end
48
+
49
+
@@ -0,0 +1,3 @@
1
+ module PhotoscanOutputs
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,7 @@
1
+ require "photoscan_outputs/version"
2
+ require "photoscan_outputs/camera"
3
+ require "photoscan_outputs/camera_file"
4
+
5
+ module PhotoscanOutputs
6
+ # Your code goes here...
7
+ end
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'photoscan_outputs/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "photoscan_outputs"
8
+ spec.version = PhotoscanOutputs::VERSION
9
+ spec.authors = ["Aaron Marburg"]
10
+ spec.email = ["amarburg@notetofutureself.org"]
11
+ spec.summary = %q{A Ruby Gem to parse the Photoscan export file formats.}
12
+ spec.homepage = "http://github.com/amarburg/rb_photoscan_outputs"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_development_dependency "bundler", "~> 1.5"
21
+ spec.add_development_dependency "rake"
22
+ spec.add_development_dependency "trollop"
23
+
24
+ spec.add_dependency "ox"
25
+ end
@@ -0,0 +1,18 @@
1
+
2
+ require "minitest/autorun"
3
+ require "photoscan_outputs"
4
+
5
+ class TestCameraFile < MiniTest::Unit::TestCase
6
+
7
+ include PhotoscanOutputs
8
+
9
+ def demo_cameras_xml
10
+ Pathname.new(__FILE__).parent.parent.join("demo", "cameras.xml")
11
+ end
12
+
13
+ def test_loads_a_file
14
+ cameras = CameraFile.load( demo_cameras_xml )
15
+ assert_kind_of( CameraFile, cameras )
16
+ end
17
+
18
+ end
metadata ADDED
@@ -0,0 +1,115 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: photoscan_outputs
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Aaron Marburg
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-02-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: trollop
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: ox
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description:
70
+ email:
71
+ - amarburg@notetofutureself.org
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - Gemfile
78
+ - LICENSE
79
+ - README.md
80
+ - Rakefile
81
+ - demo/cameras.xml
82
+ - demo/parse_cameras
83
+ - demo/point
84
+ - lib/photoscan_outputs.rb
85
+ - lib/photoscan_outputs/camera.rb
86
+ - lib/photoscan_outputs/camera_file.rb
87
+ - lib/photoscan_outputs/version.rb
88
+ - photoscan_outputs.gemspec
89
+ - test/load_file_test.rb
90
+ homepage: http://github.com/amarburg/rb_photoscan_outputs
91
+ licenses:
92
+ - MIT
93
+ metadata: {}
94
+ post_install_message:
95
+ rdoc_options: []
96
+ require_paths:
97
+ - lib
98
+ required_ruby_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ required_rubygems_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ requirements: []
109
+ rubyforge_project:
110
+ rubygems_version: 2.2.1
111
+ signing_key:
112
+ specification_version: 4
113
+ summary: A Ruby Gem to parse the Photoscan export file formats.
114
+ test_files:
115
+ - test/load_file_test.rb