Skip to content

ezwelty/glimpse

Repository files navigation

glimpse Glacier Image Particle Sequencer

tests coverage code style: black

glimpse is a Python package built for quickly and precisely analyzing time-lapse photographs of glaciers. Some useful things one can do with glimpse:

Camera calibration

  • glimpse.Camera: Model a distorted camera and perform incoming and outgoing ray projections, accounting for earth curvature and atmospheric refraction.
  • glimpse.convert: Convert between MATLAB, OpenCV, Agisoft PhotoScan, PhotoModeler, and glimpse camera formats, accounting for uncertainties in camera parameters.
  • glimpse.optimize: Perform single and multi-camera calibrations (controlling which parameters are fixed, varied, or synched across multiple cameras) using points and lines in image and world coordinates.
  • glimpse.svg: Load manual vector image annotations as inputs for camera calibration.
  • glimpse.Raster.horizon(): Compute the visible horizon from a position as input for camera calibration.
  • glimpse.Camera.project_dem(): Generate photorealistic synthetic images (and depth maps) from a camera model, gridded elevations, and optional orthophoto for automated control point collection and camera model validation.
  • glimpse.optimize.KeypointMatcher: Stabilize photographic sequences of arbitrary length using automatic image matching and globally optimal orientation estimates.

Velocity tracking

  • glimpse.Tracker: Compute the velocity (and corresponding uncertainty) of points visible in photographs taken from one or more positions.
  • glimpse.Raster.viewshed(): Compute the viewshed of a position, for tracking point selection.

References

The methods implemented in this software are described in great detail across two PhD dissertations.

  • Douglas Brinkerhoff (2017): Bayesian methods in glaciology, chapter 4. Uses particle filtering to extract velocities from one year of oblique time-lapse images of Columbia Glacier, Alaska.

  • Ethan Welty (2018): High-precision photogrammetry for glaciology. Calibrates and stabilizes time-lapse cameras using landscape cues, extends the particle filter from 2-d to 3-d (to account for uncertain surface elevations), and uses the methods on thirteen years of oblique time-lapse images of Columbia Glacier, Alaska.

Installation

glimpse has not yet been released for distribution, but can still be installed with pip from the source code on GitHub:

pip install git+https://github.com/ezwelty/glimpse

The installation requires gdal to be present. The simplest way of achieving this is to install gdal into a conda environment:

conda create -n glimpse -c conda-forge python=3.8 gdal=3.2.0
conda activate glimpse
pip install git+https://github.com/ezwelty/glimpse

Contribute

Thank you for considering contributing to glimpse!

What follows is intended to make contribution more accessible by codifying conventions. Don’t be afraid to open unfinished pull requests or to ask questions if something is unclear!

  • No contribution is too small.
  • Try to limit each pull request to one change only (one bug fix, one new feature).
  • Always add tests and docstrings for your code.
  • Make sure your changes pass the continuous integration tests.

Code & docstrings

Code follows PEP 8. It is formatted (automatically, if you use the pre-commit hooks) to conform to the black code style and import order with a maximum line length of 88 characters.

Docstrings follow PEP 257 and the Google style, with the exception of using section title "Arguments:" instead of "Args:". Argument and return types are specified as type annotations and not included in the docstrings. Examples are formatted for testing by doctest. Unless the docstring fits in a single line, the """ are on separate lines.

def xyz_to_uv(xyz: np.ndarray) -> np.ndarray:
    """
    Convert world coordinates to image coordinates.

    Arguments:
        xyz: World coordinates (n, [x, y, z]).

    Returns:
        Image coordinates (n, 2).

    Examples:
        >>> xyz = np.array([[0., 1., 0.]])
        >>> xyz_to_uv(xyz)
        array([[ 50.,  50.]])
    """

Tests

Unit tests are written for pytest. As with the rest of the code, they should include type annotations and good docstrings.

To run the full test suite on the current Python version, simply run:

make test

if you have make installed, or run the equivalent:

poetry run pytest --doctest-modules src tests

The package manager poetry (see below) will manage the virtual environment and dependencies for you. To easily install and switch between different Python versions, consider using pyenv.

Development environment

Before you begin, you will need to have gdal, a modern stable release of Python 3, and the package manager poetry. For example, using conda:

conda activate base
conda install -c conda-forge python=3.8 gdal=3.2.0 poetry=1

First, clone the glimpse repository and change into the newly created directory:

git clone https://github.com/ezwelty/glimpse
cd glimpse

Use poetry to install glimpse (and its dependencies) into a new virtual environment linked to your current Python version:

poetry install

Run commands on this virtual environment using poetry run. For example, run unit tests with:

poetry run pytest

or open a Python console with:

poetry run python

To avoid committing code that breaks tests or violates the style guide, consider installing pre-commit (if needed) and installing the hooks:

pre-commit install

You can run the pre-commit hooks anytime using:

pre-commit run --all-files

Other useful commands are listed in the Makefile. For example, to build the documentation:

make docs
# Equivalent to:
# poetry run sphinx-build docs docs/build