(German version below)
An automated solution for detection and location of Ground Control Points build with QR codes.
Wie should a human, when creating photogrammetry, search for GCPs in images and georeference them manually? With QR codes we have multiple possibilities to automate that process.
QR codes of sufficient size can be placed on the ground. The QR code then represents its position. To achieve this multiple solutions are possible:
- the QR code represents a OSM node and holds a OSM Node ID
- the QR has its own coordinates encoded
- the QR code has a number encoded that acts as an ID that later can be used to map to coordinates.
- Take photos
- Our python script automatically searches for QR codes and creates a GCP table that can be used for e.g. OpenDroneMap
- ???
- Profit
This workflow currently is just an idea that has not been thought out fully
- Create a node with WorkInProgress tag in the region of the final position on OSM
- Create QR code with OSM Node ID and QR code generator
- Lay out QR code (paint, print, pave, plant trees/flowers, etc.)
- Measure the geolocation of the upper left marker with the best possible accuracy
- Adjust position in OSM and remove WorkInProgess tag
A QR code with a fixed size of 25x25 pixels will be used. This code can hold 32 characters of data.
The center of the upper left position marker will be used as reference point. A QR code contains three position markers. The upper left one is the one "in the middle".
https://osm.to/<type indicator><payload>
The <type indicator>
can consist of the following values:
n/
, or empty:<payload>
represents an OSM Node ID in Base64w/
:<payload>
represents an OSM Way ID in Base64a/
:<payload>
represents an OSM Area Id in Base64r/
:<payload>
represents an OSM Relation ID in Base64g/
:<payload>
represents coordinates in OSM short link quad tiles formatgcp/
<payload>
represents the UUID of the Ground Control Point that was attached as tag to an OSM Objectl/
:<payload>
represents a (locally defined) ID, which during analysis is linked with coordinates
An alternative url format is: gcp://<type indicator><payload>
The <type indicator>
can consist of the following values in this case:
osm/n/
, or empty:<payload>
represents an OSM Node ID in Base64osm/w/
:<payload>
represents an OSM Way ID in Base64osm/a/
:<payload>
represents an OSM Area Id in Base64osm/r/
:<payload>
represents an OSM Relation ID in Base64osm/g/
:<payload>
represents coordinates in OSM short link quad tiles formatosm/gcp/
<payload>
represents the UUID of the Ground Control Point that was attached as tag to an OSM Objectl/
:<payload>
represents a (locally defined) ID, which during analysis is linked with coordinates
Way, Area and Relation are not used as GroundControlPoints but instead can be used to reference other OSM objects.
The prefix up to type indicator
is 15 characters long.
This way 15 characters (or 17 for Node IDs) remain for the actual payload.
OSM IDs are 64-bit integers, which in Base64 are 11 characters long.
With 15 character quad tiles one could achieve an accuracy of 0.3 mm around at the equator.
To avoid wasting space the OSM IDs are formatted in Base64 with a character set which is inspired by the OSM short link format.
The character set is ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_~
, with A
representing zero, B
one, and so on.
The number 64 will be represented as BA
, 65 as BB
and so on.
virtualenv -p python3 venv
source venv/bin/activate
pip3 install -r requirements.txt
`python3 -m unittest
python3 main.py -f <filepath>
Eine automatisierte Lösung zur Erkennung und Verortung von GroundControlPoints.
Gebaut mit QR-Codes und Openstreetmap
Warum muss man als Mensch nach einer Photogrammetrieaufnahme selber die GCP auf den Bildern suchen und georeferenzieren?
Wir haben mit QR-Codes vielfältige Möglichkeiten geschaffen, diesen Prozess zu automatisieren.
Ein QR-Code wird in ausreichender Größe auf dem Boden ausgebracht. Dabei repräsentiert der QR-Code immer seine Position. Dafür gibt es verschiedene Möglichkeiten:
- Ein OSM Node. Der QR-Code enthält eine OSM Node ID
- Eine festgelegte Koordiante. Der QR-Code enthält direkt die Koordiante
- Eine Nummer. Der QR-Code ist nummeriert und kann im Nachhinein einer Position zugeordnet werden
- Bilder aufnehmen
- Das Python Skript sucht automatisiert auf den Bildern nach QR-Codes und erzeugt eine GCP-Tabelle
- Nichts mehr, das wars schon :D
Dieser Workflow ist eine Idee, noch nicht zuende gedacht und sollte noch nicht angewendet werden!!
- Einen Node mit WorkInProgress Tag auf der ungefähren Position erzeugen
- Mit der OSM Node-ID und dem QR-Code Generator einen QR-Code erzeugen
- Den QR-Code ausbringen (malen, drucken, pflastern, Blumen säen, usw)
- Die Mitte des oberen linken größen Markers möglichst genau einmessen
- In OSM die Position korrigieren und das WorkInProgress Tag entfernen
Es wird ein QR-Code mit fester Größe von 25x25 Pixeln genutzt. Dieser kann als Daten 32 Zeichen aufnehmen.
Als Referenzpunkt wird die Mitte des großen Positionmarkers oben links genutzt. (Es gibt davon drei Stück, es ist der "mittlere")
https://osm.to/<type indicator><payload>
Der <type indicator>
kann folgende Wert haben:
n/
, bzw keiner:<payload>
stellt eine OSM Node ID zur Basis 64 darw/
:<payload>
stellt eine OSM Way ID zur Basis 64 dara/
:<payload>
stellt eine OSM Area ID zur Basis 64 darr/
:<payload>
stellt eine OSM Relation ID zur Basis 64 darg/
:<payload>
stellt eine Koordiante im OSM Shortlink quadtiles formatgcp/
<payload>
stellt die UUID des Ground Control Points dar, welcher an einem OSM Objekt als Tag hinterlegt wurdel/
:<payload>
stellt eine (nur lokal definierte) ID da, welche bei der Auswertung mit einer Koordinate verbunden werden muss
Ein alternatives URL-Format ist auch: gcp://<type indicator><payload>
Der <type indicator>
kann in diesem Fall folgende Wert haben:
osm/n/
, bzw keiner:<payload>
stellt eine OSM Node ID zur Basis 64 darosm/w/
:<payload>
stellt eine OSM Way ID zur Basis 64 darosm/a/
:<payload>
stellt eine OSM Area ID zur Basis 64 darosm/r/
:<payload>
stellt eine OSM Relation ID zur Basis 64 darosm/g/
:<payload>
stellt eine Koordiante im OSM Shortlink quadtiles formatosm/gcp/
<payload>
stellt die UUID des Ground Control Points dar, welcher an einem OSM Objekt als Tag hinterlegt wurdel/
:<payload>
stellt eine (nur lokal definierte) ID da, welche bei der Auswertung mit einer Koordinate verbunden werden muss
Die Way, Area und Relation werden nicht als GroundControlPoints genutzt, sondern können benutzt werden, andere OSM Objekte zu referenzieren.
Der Prefix bis vor den type indicator
braucht 15 Zeichen. Somit bleiben noch 15 (bzw 17 für Node IDs) Zeichen für die Payload.
OSM IDs sind 64 Bit Integer, welche zur Basis 64 maximal 11 Zeichen brauchen.
Mit 15 Zeichen Quadtiles kommt man auf eine Genauigkeit von 0.3mm am Äquator.
Um die OSM IDs möglichst platzsparend darzustellen, wird diese zur Basis 64 dargestellt, wobei der Zeichensatz an das OSM Shortlink-Format angelehnt ist. (Das Shortlink-Format nutzt hingegen eine binäre Kodierung wie base64).
Der Zeichensatz ist ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_~
, wobei A
die Null, B
die Eins, usw repräsentiert. Die Zahl 64 wird als BA
und die 65 als BB
dargestellt.
virtualenv -p python3 venv
source venv/bin/activate
pip3 install -r requirements.txt
Siehe pyzbar Dokumentation
python3 main.py -f <filepath>