This project uses a deep learning pipeline to automatically digitize handwritten annotations from scanned map images. It performs two main tasks:
- Image Segmentation: Identifies and extracts pixel masks for handwritten boundaries and text using a fine-tuned U-Net model.
- Optical Character Recognition (OCR): Recognizes the text within the extracted masks using a fine-tuned TrOCR model.
The final output is a GeoPackage file containing georeferenced polygons of the detected features, with the recognized text included as metadata.
This project uses Conda for environment management and is designed to be run in an ephemeral cloud environment.
This setup was developed and tested on a Paperspace Gradient Notebook. The setup.sh script and environment configuration are tailored for this platform. While it may work in other Debian-based Linux environments with a suitable GPU, adjustments might be necessary.
-
Clone the Repository:
git clone https://github.com/owhonda-moses/map-digitization cd maps-cv -
Run the Setup Script: This script will install Miniconda (if not present) and build the project's Conda environment from the
environment.ymlfile using Mamba for speed.bash setup.sh
The installation will take several minutes the first time it is run.
-
Activate the Environment: After setup is complete, you must activate the Conda environment in your terminal.
conda init conda activate map-cv
The project is designed to be run in a sequential workflow. All scripts should be run from the root of the repository after activating the Conda environment.
%%{init: {"themeVariables": {"fontSize": "10px", "fontFamily": "Arial", "padding": 2}, "flowchart": {"defaultRenderer": "elk"}} }%%
flowchart TD
A@{ shape: rect, label: "Start" } -->
B@{ shape: rect, label: "Run src/draft_mask.py (optional)" } -->
C@{ shape: rect, label: "Refine mask for ground truth (manual)" } -->
D@{ shape: rect, label: "Run src/create_ocr_dataset.py" } -->
E@{ shape: rect, label: "Edit metadata.csv with text labels (manual)" }
E --> F@{ shape: rect, label: "Run src/train_segmentation.py" }
E --> G@{ shape: rect, label: "Run src/train_ocr.py" }
subgraph Training
F --> H@{ shape: rect, label: "Segmentation Model" }
G --> I@{ shape: rect, label: "OCR Model" }
end
H & I --> J@{ shape: rect, label: "Run src/process_map.py" }
J --> K@{ shape: rect, label: "Run src/verify_output.py" }
K --> L@{ shape: rect, label: "View final outputs" }
-
Run
src/draft_mask.py: This optional step createsdraft_mask.pngindata/input/to serve as a starting point for your manual masks. -
Refine Draft: This step requires a layer-based image editor like GIMP or Photoshop.
- Open the original
stockton_1.png. - Import the
draft_mask.pngas a new layer. - Manually correct the draft by painting with pure white for features and pure black for background.
- Export two separate files to
data/input/:boundaries_mask.pngandtext_mask.png.
- Open the original
-
Run
src/create_ocr_dataset.py: This script uses yourtext_mask.pngto generate image snippets and saves them indata/ocr_data/images/. -
Populate
metadata.csv: Create a text file atdata/ocr_data/metadata.csv. It must contain two columns,file_nameandtext, with the correct label for each image snippet generated in the previous step.Example
metadata.csvformat:file_name,text images/image_0.png,"W/1098" images/image_1.png,"96/0999"
-
Train Models: Run
src/train_segmentation.pyandsrc/train_ocr.py. -
Run Inference: Run
src/process_map.pyto generate the finalGeoPackage. -
Verify Output: Run
src/verify_output.pyto create a final annotated image.
All executable scripts are located in the src/ directory.
draft_mask.py: A utility to programmatically generate a draft mask for manual refinement.create_ocr_dataset.py: Extracts text image snippets from the ground truth text mask to prepare data for OCR training.train_segmentation.py: Trains the fine-tuned U-Net segmentation model.train_ocr.py: Fine-tunes the TrOCR model for handwriting recognition.process_map.py: The main inference script that runs the full pipeline on a source image to generate the final GeoPackage.verify_output.py: A utility to programmatically verify the final geospatial output by creating an annotated image.
The manual steps in this project, (creating the image masks and the metadata.csv file) are necessary to produce ground truth data because we implement supervised learning which relies on this ground truth to train the models.
-
Segmentation Masks: The black-and-white masks created with GIMP act as a perfect, pixel-level answer key for the U-Net model. By comparing its predictions to this ground truth, the model learns the visual features of what constitutes a boundary or text.
-
Metadata CSV: This file is the answer key for the TrOCR model. It provides the exact, correct text for each cropped text image, allowing the model to learn the association between image pixels with specific characters.
Relying on high-quality ground truth is critical as the entire training process is derived from a single source image, and due to the limited data the manually created masks and text labels represent the complete and authoritative definition of the features to be learned. Any inaccuracies in this single ground truth will be directly learned and repeated by the models.
- Single-Source Training Data: This is the primary limitation. Both the segmentation and OCR models were trained on data derived from a single map. This restricts their ability to generalize to new maps with different wear, tear, or handwriting.
- Fixed Georeferencing: The Ground Control Points (GCPs) are hardcoded in
src/process_map.pyfor the specific map sheetNZ 3616. The system cannot automatically georeference a different map. - Static Post-processing: The contour merging logic in
process_map.pyuses a fixed kernel size, which is tuned for the current image. It may perform sub-optimally on text with significantly different character spacing.
- Expand the Dataset: The most impactful improvement would be to acquire and annotate more maps. Training on a larger and more diverse dataset is the only way to significantly improve the generalization and accuracy of both the segmentation and OCR models.
- Hyperparameter Tuning: Conduct a systematic search for optimal training settings (e.g learning rate, class weights) to maximize model performance.
- Automated Georeferencing: Implement a feature to automatically detect grid lines and corner coordinates from the map image itself, allowing the system to process any map sheet without hardcoded values.
- Quantitative Evaluation: Establish a dedicated test set of annotated maps and implement a formal evaluation pipeline that calculates key metrics (e.g Intersection Over Union for segmentation, Character Error Rate for OCR) to objectively benchmark model performance.