Skip to content

Commit

Permalink
Merge branch 'docs'
Browse files Browse the repository at this point in the history
  • Loading branch information
tayden committed Dec 4, 2024
2 parents dadf54b + 5c19497 commit c1bf563
Show file tree
Hide file tree
Showing 12 changed files with 1,402 additions and 184 deletions.
2 changes: 1 addition & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ updates:
- "*"
update-types:
- "minor"
- "patch"
- "patch"
19 changes: 19 additions & 0 deletions .readthedocs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
version: 2

build:
os: "ubuntu-20.04"
tools:
python: "3.9"

mkdocs:
configuration: mkdocs.yml
fail_on_warning: false

python:
# Install our python package before building the docs
install:
- requirements: docs/requirements.txt
- method: pip
path: .
extra_requirements:
- docs
16 changes: 16 additions & 0 deletions docs/faq.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Common Questions

Here are some answers to the questions we get most often

**What settings do you recommend?**

The current threshold defaults in all interfaces are what we found works best, in our own testing. We recommend
starting there and making small adjustments as needed. It may be useful to process just a subset of your images for
testing purposes for the sake of quickly iterating and finding what works best for you.

We typically use a pixel buffer of 2 to slightly expand our masked areas.

**What number of workers should I use?**

We typically use the default of 4. If you have a really powerful machine with a lot of memory, you might benefit from
increasing this value. If you're machine is grinding to a halt, lower it.
15 changes: 15 additions & 0 deletions docs/how_it_works.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# How it works

Structure from Motion (SfM) photogrammetry offers an effective solution for handling masked or obscured areas in imagery
through its multi-image processing capabilities. As illustrated in the diagram, when two overlapping images contain
masks identifying problematic areas (such as glints or data gaps), SfM can leverage the complementary information from
both images during the alignment and mosaicking process.

![How it works](images/howitdo.png)

**Key Requirements for Optimal Results:**

- Image overlap >50% recommended
- Consistent lighting conditions
- Proper camera settings
- Quality source imagery
76 changes: 76 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# Glint Mask Generator

Glint Mask Generator is a utility for generating mask images that correspond to the area of spectral glint in some
source imagery. Once generated, the masks can be used by 3rd party structure-from-motion (SfM) software to replace glint
areas with data from overlapping imagery that are not glinty.

## Quick Start

1. Download the [latest release](https://github.com/HakaiInstitute/glint-mask-tools/releases) for your platform
2. Launch the GUI application
3. Select your imagery type and input directory
4. Click Run to generate masks

<div style="margin-top: 50px; overflow: hidden; display: flex; justify-content:center; gap:10px;">
<img alt="Glint" src="./images/glint.gif" width="80%" />
</div>

## Features

### Multiple interfaces to suit your workflow:
- User-friendly GUI for interactive use
- CLI for automation and scripting
- Python package for integration into existing pipelines

### Support for various camera types:
- RGB cameras
- PhaseOne 4-band CIRs
- MicaSense RedEdge
- DJI Phantom 4 MS

### Advanced processing capabilities:
- Configurable band thresholds
- Pixel buffering around glint areas
- Parallel processing for improved performance
- Batch processing of multiple images

## System Requirements

- Operating Systems:
- Windows 10 or later
- Linux (modern distributions)
- Python 3.9 - 3.12 (for CLI/Python package)
- Minimum 4GB RAM
- Storage space: 100MB + space for your imagery

## Interface Comparison

| Feature | GUI | CLI | Python Package |
|--------------------------|------------------|--------------------|------------------|
| Ease of Use | ★★★★★ | ★★★ | ★★★ |
| Automation Support || ★★★★★ | ★★★★★ |
| Integration Capabilities || ★★★★ | ★★★★★ |
| Customization || ★★★ | ★★★★★ |
| Learning Curve | Minimal | Moderate | Moderate |
| Best For | Individual users | Automation/Scripts | Custom workflows |

## Next Steps

- [How it Works](how_it_works.md) - How glint masking works
- [Installation Guide](installation.md) - Get started with installation
- [Usage Guide](usage.md) - Learn how to use the tool
- [FAQs](faq.md) - Answers to common questions

## License

GlintMaskGenerator is released under
the [MIT license](https://raw.githubusercontent.com/tayden/GlintMaskGenerator/main/LICENSE.txt).

## Contribute

We welcome contributions! Please file bug reports, feature requests, or propose improvements using
our [GitHub Issue Tracker :material-github:](https://github.com/HakaiInstitute/GlintMaskGenerator/issues).

<div style="margin-top: 50px; overflow: hidden; display: flex; justify-content:center; gap:10px;">
<img alt="Hakai" src="./images/hakai_logo.png" width="30%" />
</div>
28 changes: 28 additions & 0 deletions docs/installation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Installation and Updating

The library is currently available for Python versions 3.9 through 3.12. Support for
future versions will be added when possible.

## GUI Tool

1. Go to the [releases page](https://github.com/HakaiInstitute/glint-mask-tools/releases)
2. Download the latest release file for your operating system.
3. Extract the compressed binary files from the gzipped archive.
4. This archive contains a file named GlintMaskGenerator-v*.\*.\*.exe that provides a GUI interface to the glint mask generation program.
5. You can copy these files to any location that is convenient for you.

## CLI Tool / Python Package

Installation of the CLI and Python tool are achieved using the Python package manager PIP.

### Installing

```bash
pip install glint-mask-tools
```

### Update

```bash
pip install --upgrade glint-mask-tools
```
2 changes: 2 additions & 0 deletions docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
mkdocs-material==9.5.47
mkdocstrings-python
183 changes: 183 additions & 0 deletions docs/usage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
# Usage

## General usage notes

### Accepted file types

- Supported file types are currently .jpg, .jpeg, .tif, .tiff, and .png (all are case-insensitive).

### Output files:

- Saved in the specified output directory
- Named as original filename + "_mask" suffix and maintain the same file type as the input file
- Example: `image1.jpg``image1_mask.jpg`
- When processing multi-band imagery (e.g., Micasense RedEdge or P4MS), masks will be generated for all sibling band
images.
- This caters to the expectations of SfM software like Agisoft Metashape.

### Understanding Pixel Thresholds

Pixel thresholds determine how the software identifies glint in your imagery. The thresholds are specified as decimal
values between 0.0 and 1.0, which are then applied to the full range of possible pixel values in your image.

#### How Thresholds Work

For example, in an 8-bit image (pixel values 0-255):

- A threshold of 0.5 means: pixel value > (0.5 × 255) = 127
- A threshold of 0.875 means: pixel value > (0.875 × 255) = 223

#### Multiple Band Behavior

When multiple bands are present (like in RGB images):

1. Each band is checked against its respective threshold
2. If ANY band exceeds its threshold, that pixel is marked as glint
3. The resulting masks are combined using a union operation

#### Example

For an RGB image with thresholds:

- Blue: 0.875 (triggers at values > 223)
- Green: 1.000 (never triggers)
- Red: 1.000 (never triggers)

A pixel will be marked as glint if its blue value exceeds 223, regardless of its red and green values.

## Interfaces

### GUI

The GUI version provides an intuitive interface for generating glint masks from imagery. Launch the application by
double-clicking the executable file on Windows, or running `./GlintMaskGenerator` from the terminal on Linux.

#### Main Options

1. **Imagery Type Selection**
- Choose the appropriate camera/sensor type for your imagery:
- RGB: Standard RGB camera imagery
- CIR: 4-band Color Infrared imagery
- P4MS: DJI Phantom 4 Multispectral camera imagery
- MicasenseRedEdge: Micasense RedEdge multispectral camera imagery

2. **Directory Selection**
- Image Directory: Select the input folder containing your imagery files using the "..." button
- Output Directory: Choose where the generated mask files will be saved

3. **Band Thresholds**
- Adjust thresholds for each available band using the sliders
- Range: 0.0 to 1.0 (higher values = less masking)
- Default values:
- Blue: 0.875
- Green: 1.000
- Red: 1.000
- Red Edge: 1.000 (when applicable)
- NIR: 1.000 (when applicable)
- Use the "Reset all" button to restore default values

4. **Processing Options**
- Pixel Buffer Radius: Adjusts the expansion of masked regions (default: 0)
- Max Workers: Controls the number of parallel processing threads (default: 4)

5. **Processing**
- Click "Run" to start generating masks

### CLI

For information about the parameters expected by the CLI, run glint-mask --help in a bash terminal or command line
interface. All the functionality of the CLI is documented there.

```
❯ glint-mask --help
Usage: glint-mask [OPTIONS] COMMAND [ARGS]...
╭─ Options ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ --install-completion Install completion for the current shell. │
│ --show-completion Show completion for the current shell, to copy it or customize the installation. │
│ --help Show this message and exit. │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
╭─ Commands ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ rgb-threshold Generate masks for glint regions in RGB imagery using Tom Bell's binning algorithm. │
│ cir-threshold Generate masks for glint regions in 4 Band CIR imagery using Tom Bell's binning algorithm. │
│ p4ms-threshold Generate masks for glint regions in multispectral imagery from the DJI camera using Tom Bell's algorithm on the Blue image band. │
│ micasense-threshold Generate masks for glint regions in multispectral imagery from the Micasense camera using Tom Bell's algorithm on the blue image band. │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
```

```
# Get addition parameters for one of the cameras/methods available
❯ glint-mask rgb-threshold --help
Usage: glint-mask rgb-threshold [OPTIONS] IMG_DIR OUT_DIR
Generate masks for glint regions in RGB imagery using Tom Bell's binning algorithm.
╭─ Arguments ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ * img_dir PATH The path to a named input image or directory containing images. If img_dir is a directory, all tif, jpg, jpeg, and png images in that directory will be processed. [default: None] [required] │
│ * out_dir PATH The path to send your out image including the file name and type. e.g. "/path/to/mask.png". out_dir must be a directory if img_dir is specified as a directory. [default: None] [required] │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
╭─ Options ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ --thresholds FLOAT The pixel band thresholds indicating glint. Domain for values is (0.0, 1.0). [default: 0.875, 1, 1, 1, 1] │
│ --pixel-buffer INTEGER The pixel distance to buffer out the mask. [default: 0] │
│ --max-workers INTEGER The maximum number of threads to use for processing. [default: 4] │
│ --help Show this message and exit. │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
```

#### CLI Examples

```bash
# Process RGB imagery directory with default parameters
# - Uses default thresholds (Blue: 0.875, Green: 1.0, Red: 1.0)
# - No pixel buffer
# - 4 worker threads
glint-mask rgb-threshold /path/to/dir/with/images/ /path/to/out_masks/dir/

# Process PhaseONE CIR imagery with custom settings
# - Specify custom thresholds with --thresholds
# - Add 2-pixel buffer with --pixel-buffer
# - Use 8 worker threads with --max-workers
glint-mask cir-threshold \
--thresholds 0.8,0.9,0.9,0.9 \
--pixel-buffer 2 \
--max-workers 8 \
/path/to/dir/with/images/ \
/path/to/out_masks/dir/

# Process DJI P4MS imagery with minimal masking
# - Higher thresholds mean less aggressive masking
# - Useful for scenes with minimal glint
glint-mask p4ms-threshold \
--thresholds 0.95,1.0,1.0,1.0,1.0 \
/path/to/dir/with/images/ \
/path/to/out_masks/dir/

# Process Micasense RedEdge imagery with aggressive masking
# - Lower thresholds mean more aggressive masking
# - Larger pixel buffer for broader masked areas
glint-mask micasense-threshold \
--thresholds 0.8,0.9,0.9,0.9,0.9 \
--pixel-buffer 5 \
/path/to/dir/with/images/ \
/path/to/out_masks/dir/
```

### Python Library

Installing the PyPi package allows integrating the mask generation workflow into existing python scripts with ease.

```py
from glint_mask_generator import MicasenseRedEdgeThresholdMasker

# Also available: P4MSThresholdMasker, RGBIntensityRatioMasker, RGBThresholdMasker

masker = MicasenseRedEdgeThresholdMasker(
img_dir="path/to/micasense/images/",
mask_dir="path/to/output/dir/",
thresholds=(0.875, 1, 1, 1, 1),
pixel_buffer=5
)
masker.process(max_workers=5, callback=print, err_callback=print)
```
Loading

0 comments on commit c1bf563

Please sign in to comment.