Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
3d15de4
[panorama] first tets of photo phase
MrClock8163 Aug 26, 2025
83e5af7
[panorama] fixes to measurement
MrClock8163 Aug 26, 2025
529b387
[panorama] added panorama annotation
MrClock8163 Aug 26, 2025
d6744c6
[panorama] small corrections
MrClock8163 Aug 26, 2025
32fcd63
[panorama] added overlap option to measurement
MrClock8163 Aug 26, 2025
fd07a39
[panorama] iterated on panorama measurement
MrClock8163 Aug 27, 2025
fc20ef0
[panorama] improvements and fixes to annotation
MrClock8163 Aug 27, 2025
2217e33
[panorama] improved image position generator
MrClock8163 Aug 31, 2025
807d72e
[panorama] added center coordinates to metadata writing
MrClock8163 Aug 31, 2025
f2993c5
[panorama] added handling for single rows/columns
MrClock8163 Aug 31, 2025
227774c
[panorama] changed metadata format to JSON
MrClock8163 Sep 1, 2025
dbd4e39
[code] added opencv optional dependency
MrClock8163 Sep 1, 2025
67065a9
[panorama] added new panorama processing
MrClock8163 Sep 1, 2025
3890f12
[panorama] added metadata schema
MrClock8163 Sep 1, 2025
068b4f1
[panorama] added camera offset estimation
MrClock8163 Sep 1, 2025
b32f275
[panorama] added progress reporting to processing
MrClock8163 Sep 1, 2025
75ea927
:rage: :gun:
MrClock8163 Sep 1, 2025
ba03c3f
[panorama] added font and thickness options to annotation
MrClock8163 Sep 1, 2025
1dca386
[panorama] added docstring to processing
MrClock8163 Sep 7, 2025
92d119d
[panorama] overhauled measurement
MrClock8163 Sep 7, 2025
e88a4ae
[panorama] added docs
MrClock8163 Sep 7, 2025
c260714
[panorama] added limit for scale factor
MrClock8163 Sep 8, 2025
03f370d
[panorama] cleaned up progress reporting
MrClock8163 Sep 8, 2025
35e23f6
[panorama] updated progress reporting in panorama processing
MrClock8163 Sep 9, 2025
7c5c5a0
[panorama] added basic image compensation and blending CLI options
MrClock8163 Sep 10, 2025
a504ee0
[panorama] added shift option
MrClock8163 Sep 12, 2025
b39894a
[panorama] added seam handling
MrClock8163 Sep 16, 2025
8a34bc5
[panorama] fixed mistake in whitebalance reset
MrClock8163 Sep 16, 2025
591667a
[panorama] restored overlap option for measurement
MrClock8163 Sep 16, 2025
9200ca2
[panorama] reintroduced uniform grid position option
MrClock8163 Sep 16, 2025
a09e347
[panorama] updated docs about image positions
MrClock8163 Sep 16, 2025
f19a280
[panorama] added stitching debug visualization and cleaned up typing
MrClock8163 Sep 18, 2025
2d16c79
[panorama] fixed missing usage info for processing
MrClock8163 Sep 18, 2025
8c2c425
[docs] added notes about extra dependencies
MrClock8163 Sep 20, 2025
78aa68e
[panorama] updated console feedback
MrClock8163 Sep 22, 2025
81eba3e
[panorama] fixed critical bug with single row captures
MrClock8163 Sep 23, 2025
bc2b0a8
[panorama] reworked processing and changed metadata fields
MrClock8163 Sep 23, 2025
d04b447
[panorama] simplified progress reporting
MrClock8163 Sep 23, 2025
06cfdf5
[panorama] adjusted max processing scale
MrClock8163 Sep 25, 2025
3a3c66d
[panorama] fixed GeoCOM letter casing in docs
MrClock8163 Sep 29, 2025
3b3f12e
[panorama] command help updated
MrClock8163 Oct 2, 2025
cc77563
Update CHANGELOG.md
MrClock8163 Oct 6, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
python-version: ${{ matrix.python-version }}

- name: Build and install package
run: python -m pip install .
run: python -m pip install .[all]

- name: Test with pytest
run: |
Expand All @@ -47,7 +47,7 @@ jobs:
python-version: 3.x

- name: Build and install package
run: python -m pip install .
run: python -m pip install .[all]

- name: Running ${{ matrix.tool }}
run: |
Expand Down
2 changes: 1 addition & 1 deletion .readthedocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ build:
pre_build:
- python -m pip install --upgrade pip
- python -m pip install --group documentation
- python -m pip install .
- python -m pip install .[all]

sphinx:
configuration: docs/conf.py
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ The project uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

### Added

- Added panorama capturing (`capture panorama`)
- Added panorama processing (`process panorama`)
- Added GeoCOM shutdown utility (`shutdown geocom`)
- Added GeoCOM startup utility (`startup geocom`)
- Added GSI Online DNA shutdown utility (`shutdown gsidna`)
Expand Down
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,11 @@ cd Instrumentman
python -m pip install .
```

Some commands require additional dependencies, that are not installed by
default with I-man. These are indicated in the documentations of the specific
commands.

## License

I-man is free and open source software, and it is distributed under the terms of the
[MIT License](https://opensource.org/license/mit).
I-man is free and open source software, and it is distributed under the terms
of the [MIT License](https://opensource.org/license/mit).
Binary file added docs/commands/panorama/image_positions.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 18 additions & 0 deletions docs/commands/panorama/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
:icon: material/panorama-variant-outline

Panorama
========

For documentation purposes it might be useful to have an image of the measured
area with the measured points annotated. Total stations with integrated cameras
usually have a panorama capture on-board program, but it provides to way to
annotate the recorded points.

The panorama commands provide a way to capture frames of a panorama, and
merge them together with optional point annotations.

.. toctree::
:maxdepth: 1

measure
process
68 changes: 68 additions & 0 deletions docs/commands/panorama/measure.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
Measuring
=========

To create a panorama image from different images taken from a common center
point, the orientatiobs of the images have to be known among other camera
properties. The necessary data can be derived from independent calibration and
screenshots during the on-board panorama program.

To simplify the process, this command can be used to capture images with the
necessary metadata automatically being recorded as reported by the instrument.

Requirements
------------

- GeoCOM capable robotic total station with overview camera and imaging license

Positions
---------

The program takes images in a region defined by a horizontal and vertical angle
range. Two convenience settings exists (in addition to the default), that
reduce the number of angle inputs needed for specific cases:

- region: horizontal and vertical range is required (this is the default)
- strip: 360 degree horizontal coverage with given vertical range
- sphere: complete spherical panorama

.. note::

The complete sphere panorama is not very practical, and more of a proof of
concept, as capturing the full view takes impractically long time.

If adaptive FoV is enabled for the position layout generation, images that are
taken at angles that deviate from the horizontal position are considered to
cover a wider horizontal angle area. To avoid taking unnecessary images, the
top and bottom rows have fewer images.

.. image:: image_positions.png

To reduce the parallax errors of close range objects caused by the camera
offset, it is possible to increase the overlap between images (effectively
reducing the motion between images), but this can significantly increase the
required number of images and time (e.g. full sphere panorama with 30%
overlap requires approximately 1500 images).

Examples
--------

.. code-block:: shell
:caption: Capturing panorama with interactive region definition and default settings

iman capture panorama COM1 metadata.json

.. code-block:: shell
:caption: Capturing full sphere panorama with custom file prefix

iman capture panorama --shape sphere --prefix panosphere_ COM1 metadata.json

.. code-block:: shell
:caption: Capturing predefined 360 panorama strip

iman capture panorama --strip strip --vertical 70-00-00 110-00-00 COM1 metadata.json

Usage
-----

.. click:: instrumentman.panorama:cli_measure
:prog: iman capture panorama
58 changes: 58 additions & 0 deletions docs/commands/panorama/process.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
Processing
==========

.. caution::
:class: warning

The panorama image processing requires extra dependencies.

- opencv-python

Install them manually, or install instrumentman with the 'panorama' extra:

.. code-block:: shell

python -m pip install instrumentman[panorama]

The processing command can be used to merge individual frames of a panorama
capture into a single image, and optionally annotate points on it.

The accuracy of the annotation is usually a few centimeters.

Requirements
------------

- Image metadata JSON file
- Images downloaded from the instrument

Examples
--------

.. code-block:: shell
:caption: Merging images

iman process panorama metadata.json merged_panorama.jpg panorama*.jpg


.. code-block:: shell
:caption: Merging images and annotating points

iman process panorama --annotate points.csv --fontsize 50 metadata.json merged_panorama.jpg panorama*.jpg

.. code-block:: shell
:caption: Merging full sphere panorama with downscaling to fit into OpenCV limits

iman process panorama --scale 2000 metadata.json merged_panorama.jpg panorama*.jpg

.. code-block:: text
:caption: Example points file for annotations (with the optional label column present)

P0001,1.0,1.0,0.0,BENCHMARK
P0002,1.0,2.0,1.0,BENCHMARK
P0003,1.0,2.0,3.0,TOPO

Usage
-----

.. click:: instrumentman.panorama:cli_calc
:prog: iman process panorama
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ Content
commands/targets/index
commands/sets/index
commands/inclination/index
commands/panorama/index
commands/protocoltest/index
commands/files/index
commands/data/index
Expand Down
1 change: 1 addition & 0 deletions docs/latexindex.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Applications
commands/targets/index
commands/sets/index
commands/inclination/index
commands/panorama/index
commands/protocoltest/index
commands/files/index
commands/data/index
Expand Down
7 changes: 7 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ dependencies = [
"toml ~= 0.10.2",
"PyYAML ~= 6.0.2",
"numpy ~= 2.0",
"pillow ~= 11.0",
"cloup ~= 3.0.7",
"click-extra ~= 5.0.2"
]
Expand Down Expand Up @@ -59,6 +60,12 @@ Changelog = "https://instrumentman.readthedocs.io/latest/changelog"
[project.scripts]
iman = "instrumentman:cli"

[project.optional-dependencies]
all = ["instrumentman[panorama]"]
panorama = [
"opencv-python~=4.8"
]

[dependency-groups]
testing = [
"pytest ~= 8.4.1"
Expand Down
7 changes: 5 additions & 2 deletions src/instrumentman/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from . import station
from . import protocoltest
from . import inclination
from . import panorama
from . import filetransfer
from . import jobs
from . import datatransfer
Expand Down Expand Up @@ -107,7 +108,7 @@ def cli(
)


@cli.group("measure") # type: ignore[misc]
@cli.group("measure", aliases=["capture"]) # type: ignore[misc]
def cli_measure() -> None:
"""Conduct measurements."""

Expand All @@ -117,7 +118,7 @@ def cli_convert() -> None:
"""Convert between various file formats."""


@cli.group("calculate", aliases=["calc"]) # type: ignore[misc]
@cli.group("calculate", aliases=["calc", "process"]) # type: ignore[misc]
def cli_calc() -> None:
"""Preform calculations from measurement results."""

Expand Down Expand Up @@ -173,9 +174,11 @@ def cli_startup() -> None:
cli_measure.add_command(setmeasurement.cli_measure)
cli_measure.add_command(setup.cli_measure)
cli_measure.add_command(inclination.cli_measure)
cli_measure.add_command(panorama.cli_measure)
cli_calc.add_command(setmeasurement.cli_calc)
cli_calc.add_command(inclination.cli_calc)
cli_calc.add_command(station.cli_calc)
cli_calc.add_command(panorama.cli_calc)
cli_test.add_command(protocoltest.cli_geocom)
cli_test.add_command(protocoltest.cli_gsidna)
cli_merge.add_command(setmeasurement.cli_merge)
Expand Down
Loading