Skip to content
Snippets Groups Projects
Commit c3b3905d authored by Jay's avatar Jay
Browse files

Initial commit

parent c8e44e48
No related branches found
No related tags found
No related merge requests found
setup.py 0 → 100644
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=[]
)
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')
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)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment