Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
K
Knoten
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
aflab
astrogeology
Knoten
Commits
c3b3905d
Commit
c3b3905d
authored
Nov 29, 2018
by
Jay
Browse files
Options
Downloads
Patches
Plain Diff
Initial commit
parent
c8e44e48
No related branches found
No related tags found
No related merge requests found
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
requirements.txt
+7
-0
7 additions, 0 deletions
requirements.txt
setup.py
+10
-0
10 additions, 0 deletions
setup.py
spaetzle/__init__.py
+12
-0
12 additions, 0 deletions
spaetzle/__init__.py
spaetzle/csm.py
+308
-0
308 additions, 0 deletions
spaetzle/csm.py
with
337 additions
and
0 deletions
requirements.txt
0 → 100644
+
7
−
0
View file @
c3b3905d
csmapi
jinja
pyproj
numpy
scipy
gdal
pvl
This diff is collapsed.
Click to expand it.
setup.py
0 → 100644
+
10
−
0
View file @
c3b3905d
from
setuptools
import
setup
,
find_packages
setup
(
name
=
'
spaetzle
'
,
version
=
'
0.1.0
'
,
long_description
=
''
,
packages
=
find_packages
(),
include_package_data
=
True
,
zip_safe
=
True
,
scripts
=
[]
)
This diff is collapsed.
Click to expand it.
spaetzle/__init__.py
0 → 100644
+
12
−
0
View file @
c3b3905d
import
ctypes
from
distutils
import
sysconfig
import
os
import
warnings
from
csmapi
import
csmapi
# Register the usgscam plugin with the csmapi
lib
=
ctypes
.
CDLL
(
os
.
path
.
abspath
(
os
.
path
.
join
(
sysconfig
.
get_python_lib
(),
'
../../libusgscsm.so
'
)))
if
not
lib
:
warnings
.
warn
(
'
Unable to load usgscsm shared library
'
)
This diff is collapsed.
Click to expand it.
spaetzle/csm.py
0 → 100644
+
308
−
0
View file @
c3b3905d
import
datetime
import
json
import
os
from
csmapi
import
csmapi
import
jinja2
import
numpy
as
np
import
scipy.stats
import
pyproj
import
gdal
from
gdal
import
ogr
import
pvl
def
generate_boundary
(
isize
,
nnodes
=
5
,
n_points
=
10
):
'''
Generates a bounding box given a camera model
Parameters
----------
camera : object
csmapi generated camera model
nnodes : int
Not sure
n_points : int
Number of points to generate between the corners of the bounding
box per side.
Returns
-------
boundary : list
List of full bounding box
'''
x
=
np
.
linspace
(
0
,
isize
[
0
],
n_points
)
y
=
np
.
linspace
(
0
,
isize
[
1
],
n_points
)
boundary
=
[(
i
,
0.
)
for
i
in
x
]
+
[(
isize
[
0
],
i
)
for
i
in
y
[
1
:]]
+
\
[(
i
,
isize
[
1
])
for
i
in
x
[::
-
1
][
1
:]]
+
[(
0.
,
i
)
for
i
in
y
[::
-
1
][
1
:]]
return
boundary
def
generate_latlon_boundary
(
camera
,
nnodes
=
5
,
semi_major
=
3396190
,
semi_minor
=
3376200
,
n_points
=
10
):
'''
Generates a latlon bounding box given a camera model
Parameters
----------
camera : object
csmapi generated camera model
nnodes : int
Not sure
semi_major : int
Semimajor axis of the target body
semi_minor : int
Semiminor axis of the target body
n_points : int
Number of points to generate between the corners of the bounding
box per side.
Returns
-------
lons : list
List of longitude values
lats : list
List of latitude values
alts : list
List of altitude values
'''
isize
=
camera
.
getImageSize
()
isize
=
(
isize
.
line
,
isize
.
samp
)
boundary
=
generate_boundary
(
isize
,
nnodes
=
nnodes
,
n_points
=
n_points
)
ecef
=
pyproj
.
Proj
(
proj
=
'
geocent
'
,
a
=
semi_major
,
b
=
semi_minor
)
lla
=
pyproj
.
Proj
(
proj
=
'
latlon
'
,
a
=
semi_major
,
b
=
semi_minor
)
gnds
=
np
.
empty
((
len
(
boundary
),
3
))
for
i
,
b
in
enumerate
(
boundary
):
# Could be potential errors or warnings from imageToGround
try
:
gnd
=
camera
.
imageToGround
(
csmapi
.
ImageCoord
(
*
b
),
0
)
except
:
pass
gnds
[
i
]
=
[
gnd
.
x
,
gnd
.
y
,
gnd
.
z
]
lons
,
lats
,
alts
=
pyproj
.
transform
(
ecef
,
lla
,
gnds
[:,
0
],
gnds
[:,
1
],
gnds
[:,
2
])
return
lons
,
lats
,
alts
def
generate_gcps
(
camera
,
nnodes
=
5
,
semi_major
=
3396190
,
semi_minor
=
3376200
,
n_points
=
10
):
'''
Generates an area of ground control points formated as:
<GCP Id=
""
Info=
""
Pixel=
""
Line=
""
X=
""
Y=
""
Z=
""
/> per record
Parameters
----------
camera : object
csmapi generated camera model
nnodes : int
Not sure
semi_major : int
Semimajor axis of the target body
semi_minor : int
Semiminor axis of the target body
n_points : int
Number of points to generate between the corners of the bounding
box per side.
Returns
-------
gcps : list
List of all gcp records generated
'''
lons
,
lats
,
alts
=
generate_latlon_boundary
(
camera
,
nnodes
=
nnodes
,
semi_major
=
semi_major
,
semi_minor
=
semi_minor
,
n_points
=
n_points
)
lla
=
np
.
vstack
((
lons
,
lats
,
alts
)).
T
tr
=
zip
(
boundary
,
lla
)
gcps
=
[]
for
i
,
t
in
enumerate
(
tr
):
l
=
'
<GCP Id=
"
{}
"
Info=
"
{}
"
Pixel=
"
{}
"
Line=
"
{}
"
X=
"
{}
"
Y=
"
{}
"
Z=
"
{}
"
/>
'
.
format
(
i
,
i
,
t
[
0
][
1
],
t
[
0
][
0
],
t
[
1
][
0
],
t
[
1
][
1
],
t
[
1
][
2
])
gcps
.
append
(
l
)
return
gcps
def
generate_latlon_footprint
(
camera
,
nnodes
=
5
,
semi_major
=
3396190
,
semi_minor
=
3376200
,
n_points
=
10
):
'''
Generates a latlon footprint from a csmapi generated camera model
Parameters
----------
camera : object
csmapi generated camera model
nnodes : int
Not sure
semi_major : int
Semimajor axis of the target body
semi_minor : int
Semiminor axis of the target body
n_points : int
Number of points to generate between the corners of the bounding
box per side.
Returns
-------
: object
ogr multipolygon containing between one and two polygons
'''
lons
,
lats
,
_
=
generate_latlon_boundary
(
camera
,
nnodes
=
nnodes
,
semi_major
=
semi_major
,
semi_minor
=
semi_minor
,
n_points
=
n_points
)
# Transform coords from -180, 180 to 0, 360
# Makes crossing the maridian easier to identify
ll_coords
=
[
*
zip
(((
lons
+
180
)
%
360
),
lats
)]
ring
=
ogr
.
Geometry
(
ogr
.
wkbLinearRing
)
wrap_ring
=
ogr
.
Geometry
(
ogr
.
wkbLinearRing
)
poly
=
ogr
.
Geometry
(
ogr
.
wkbPolygon
)
wrap_poly
=
ogr
.
Geometry
(
ogr
.
wkbPolygon
)
multipoly
=
ogr
.
Geometry
(
ogr
.
wkbMultiPolygon
)
current_ring
=
ring
switch_point
=
None
previous_point
=
ll_coords
[
0
]
for
coord
in
ll_coords
:
coord_diff
=
previous_point
[
0
]
-
coord
[
0
]
if
coord_diff
>
0
and
np
.
isclose
(
previous_point
[
0
],
360
,
rtol
=
1e-03
)
and
\
np
.
isclose
(
coord
[
0
],
0
,
atol
=
1e0
,
rtol
=
1e-01
):
regression
=
scipy
.
stats
.
linregress
([
previous_point
[
0
],
coord
[
0
]],
[
previous_point
[
1
],
coord
[
1
]])
slope
,
b
=
regression
.
slope
,
regression
.
intercept
current_ring
.
AddPoint
(
360
-
180
,
(
slope
*
360
+
b
))
current_ring
=
wrap_ring
switch_point
=
0
-
180
,
(
slope
*
0
+
b
)
current_ring
.
AddPoint
(
*
switch_point
)
elif
coord_diff
<
0
and
np
.
isclose
(
previous_point
[
0
],
0
,
atol
=
1e0
,
rtol
=
1e-01
)
and
\
np
.
isclose
(
coord
[
0
],
360
,
rtol
=
1e-03
):
regression
=
scipy
.
stats
.
linregress
([
previous_point
[
0
],
coord
[
0
]],
[
previous_point
[
1
],
coord
[
1
]])
slope
,
b
=
regression
.
slope
,
regression
.
intercept
current_ring
.
AddPoint
(
0
-
180
,
(
slope
*
0
+
b
))
current_ring
.
AddPoint
(
*
switch_point
)
current_ring
=
ring
current_ring
.
AddPoint
(
360
-
180
,
(
slope
*
360
+
b
))
lat
,
lon
=
coord
current_ring
.
AddPoint
(
lat
-
180
,
lon
)
previous_point
=
coord
poly
.
AddGeometry
(
ring
)
wrap_poly
.
AddGeometry
(
wrap_ring
)
if
not
wrap_poly
.
IsEmpty
():
multipoly
.
AddGeometry
(
wrap_poly
)
if
not
poly
.
IsEmpty
():
multipoly
.
AddGeometry
(
poly
)
return
multipoly
def
generate_bodyfixed_footprint
(
camera
,
nnodes
=
5
,
semi_major
=
3396190
,
semi_minor
=
3376200
,
n_points
=
10
):
'''
Generates a bodyfixed footprint from a csmapi generated camera model
Parameters
----------
camera : object
csmapi generated camera model
nnodes : int
Not sure
n_points : int
Number of points to generate between the corners of the bounding
box per side.
Returns
-------
: object
ogr polygon
'''
latlon_fp
=
generate_latlon_footprint
(
camera
,
nnodes
=
5
,
semi_major
=
semi_major
,
semi_minor
=
semi_minor
,
n_points
=
n_points
)
ecef
=
pyproj
.
Proj
(
proj
=
'
geocent
'
,
a
=
semi_major
,
b
=
semi_minor
)
lla
=
pyproj
.
Proj
(
proj
=
'
latlon
'
,
a
=
semi_major
,
b
=
semi_minor
)
# Step over all geometry objects in the latlon footprint
for
i
in
range
(
latlon_fp
.
GetGeometryCount
()):
latlon_coords
=
np
.
array
(
latlon_fp
.
GetGeometryRef
(
i
).
GetGeometryRef
(
0
).
GetPoints
())
# Check if the geometry object is populated with points
if
len
(
latlon_coords
)
>
0
:
x
,
y
,
z
=
pyproj
.
transform
(
lla
,
ecef
,
latlon_coords
[:,
0
],
latlon_coords
[:,
1
],
latlon_coords
[:,
2
])
# Step over all coordinate points in a geometry object and update said point
for
j
,
_
in
enumerate
(
latlon_coords
):
latlon_fp
.
GetGeometryRef
(
i
).
GetGeometryRef
(
0
).
SetPoint
(
j
,
x
[
j
],
y
[
j
],
0
)
return
latlon_fp
def
generate_vrt
(
camera
,
raster_size
,
fpath
,
outpath
=
None
,
no_data_value
=
0
):
gcps
=
generate_gcps
(
camera
)
xsize
,
ysize
=
raster_size
if
outpath
is
None
:
outpath
=
os
.
path
.
dirname
(
fpath
)
outname
=
os
.
path
.
splitext
(
os
.
path
.
basename
(
fpath
))[
0
]
+
'
.vrt
'
outname
=
os
.
path
.
join
(
outpath
,
outname
)
xsize
,
ysize
=
raster_size
vrt
=
r
'''
<VRTDataset rasterXSize=
"
{{ xsize }}
"
rasterYSize=
"
{{ ysize }}
"
>
<Metadata/>
<GCPList Projection=
"
{{ proj }}
"
>
{% for gcp in gcps -%}
{{gcp}}
{% endfor -%}
</GCPList>
<VRTRasterBand dataType=
"
Float32
"
band=
"
1
"
>
<NoDataValue>{{ no_data_value }}</NoDataValue>
<Metadata/>
<ColorInterp>Gray</ColorInterp>
<SimpleSource>
<SourceFilename relativeToVRT=
"
0
"
>{{ fpath }}</SourceFilename>
<SourceBand>1</SourceBand>
<SourceProperties rasterXSize=
"
{{ xsize }}
"
rasterYSize=
"
{{ ysize }}
"
DataType=
"
Float32
"
BlockXSize=
"
512
"
BlockYSize=
"
512
"
/>
<SrcRect xOff=
"
0
"
yOff=
"
0
"
xSize=
"
{{ xsize }}
"
ySize=
"
{{ ysize }}
"
/>
<DstRect xOff=
"
0
"
yOff=
"
0
"
xSize=
"
{{ xsize }}
"
ySize=
"
{{ ysize }}
"
/>
</SimpleSource>
</VRTRasterBand>
</VRTDataset>
'''
context
=
{
'
xsize
'
:
xsize
,
'
ysize
'
:
ysize
,
'
gcps
'
:
gcps
,
'
proj
'
:
'
+proj=longlat +a=3396190 +b=3376200 +no_defs
'
,
'
fpath
'
:
fpath
,
'
no_data_value
'
:
no_data_value
}
template
=
jinja2
.
Template
(
vrt
)
tmp
=
template
.
render
(
context
)
warp_options
=
gdal
.
WarpOptions
(
format
=
'
VRT
'
,
dstNodata
=
0
)
gdal
.
Warp
(
outname
,
tmp
,
options
=
warp_options
)
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
sign in
to comment