avatarDan Carlson

Summary

The web content provides guidance on using Python to automate workflows in Agisoft Metashape, enhancing efficiency and accuracy for tasks such as standardizing settings, aligning images, and batch processing projects.

Abstract

The article titled "Use Python to Streamline Your Agisoft Metashape Workflow: Part I" outlines the benefits of automating repetitive tasks in Agisoft Metashape using Python. It emphasizes the importance of automation to avoid errors and save time, particularly when processing large datasets overnight. The Python API is highlighted as a powerful tool included in the Professional version of Metashape, which allows users to script the application of consistent settings across multiple projects, automatically save projects after each processing step, and handle tasks like image alignment and camera optimization with ease. The article also references educational resources such as user manuals, tutorials, and an Open File Report by the USGS to help users familiarize themselves with the software's GUI and processing workflows. A step-by-step guide is provided for scripting the alignment of images, including code snippets and instructions on running the script within Metashape. The article concludes by encouraging readers to apply the demonstrated Python automation techniques to improve their Metashape workflow efficiency.

Opinions

  • The author, Aleena Rayamajhi, advocates for the use of the Metashape Python API to streamline workflows, noting that manual processing steps are prone to human error and can be time-consuming.
  • There is an emphasis on the Python API's ability to ensure consistent and replicable processing by applying the same settings, which is crucial for accuracy and reliability in photogrammetry projects.
  • The author suggests that the Python API provides peace of mind by automatically saving the project after each step, preventing data loss in case of unexpected interruptions like power outages.
  • The article suggests that scripting workflows can significantly enhance efficiency, particularly for users who process multiple projects or large datasets, by enabling batch processing.
  • The author recommends additional educational materials for users who are new to Metashape, highlighting the importance of a solid understanding of the software's GUI and processing workflows before attempting to script with Python.
  • The guide provided is designed to be easy to follow, targeting users who may not be familiar with Python scripting but are keen to automate their Metashape workflows.

Use Python to Streamline Your Agisoft Metashape Workflow: Part I

Standardize settings, align images, and batch process projects

The sparse point cloud after camera alignment in Agisoft Metashape

Use Python to enhance efficiency, accuracy, customization, and scalability of your Metashape workflow

Agisoft Metashape provides the software tools to create high resolution drone orthomosaics and/or detailed 3D point clouds and mesh models, making it ideal for a wide range of users. Like most modern software packages, the intuitive layout of the Metashape graphical user interface (GUI) makes it sufficient for most users. Aleena Rayamajhi wrote a comprehensive post that can get you started using the standard GUI.

After getting familiar with the GUI you should notice that many of the processing steps are repetitive. Repetitive tasks should be automated. You may also notice that a mistake during processing, like setting the wrong tie point or key point limit, can lead to incorrect results and a lot of wasted time.

The Professional version of Metashape includes a Python API that can be used to streamline your workflow. If you don’t use it already, you should! Using the Metashape Python API will streamline your workflow, allowing you to batch process multiple projects. A scripted workflow also ensures consistent and replicable processing by applying the same settings.

The Python API allows you to automatically save your project after each step, providing peace of mind. Processing large sets of images can take time. It’s not uncommon for processing steps to run overnight, even with a beefy computer. When using the GUI, you must save your project manually after each processing step is completed. Saving manually is usually not a problem until your computer loses power in the early morning hours, before you wake up to manually save your project. The Python API allows you to save your project automatically after each step is completed, ensuring that all the time invested in processing your imagery is not lost.

In this post, you will learn how to harness the power of Metashape’s Python API to automate the initial alignment step of the workflow.

Before proceeding, read the user manuals and make sure that you’ve configured Metashape properly for your computer. If you’re new to Metashape I recommend reading the Agisoft tutorials and watching some YouTube videos.

I also highly recommend reading the USGS Open File Report on Processing Coastal Imagery in Agisoft Metashape. This Open File Report provides a comprehensive description of the GUI environment and the processing workflow for drone aerial imagery of coastal environments. Some of the settings may not apply to other use cases (like turntables or multi-camera rigs) but the configuration of GPU acceleration, writing log files, default views, etc. should apply to all users.

Scripted Alignment in 3 Easy Steps

Aligning images in Metashape using python is as easy as 1, 2, 3!

Understanding Chunks

Metashape documents use ‘Chunks’ to group cameras, tie points, reference data, and other information. Documents and Chunks are also objects in the Python API with attributes that can be set/retrieved, as illustrated below.

doc = Metashape.app.document
for chunk in doc.chunks:
  if chunk.label == 'chunk1':
    # do stuff

The name that you assign to a chunk will be stored as chunk.label and should, therefore, make sense.

A new Metashape project with the chunk renamed ‘run1’

Since this is the first run in this project, let’s call the chunk ‘run1.’ Open Metashape, right click on ‘Chunk 1’ in the Workspace Panel, click ‘Rename’, enter ‘run1’ and press ‘Enter.’

Adding photos to ‘run1’

Next, right click on ‘run1’ and select Add →Add Photos. Navigate to the directory that contains the photos that you want to process, select the appropriate photos and then click ‘Open.’

After adding photos to the chunk ‘run1’ save your project. You will need to specify the path to your project and the project file name in your python code so use a naming convention that makes sense and is easy to code. In this example I saved my project using the following convention, which uses the project creation date and a text descriptor:

'20230828_mcourse.psx'
# datestring_descriptor.psx
# yyyymmdd_descriptor.psx

In this case, I used the four-digit year, two-digit month, and two-digit day (zero-padded as necessary) and the descriptor ‘mcourse’ for Metashape Course.

My Metashape project, with 45 images added to the chunk ‘run1’, and saved as ‘20230828_mcourse.psx’

I am using images from a DJI Phantom 3 drone in this example. Metashape automatically extracts the GPS positions of each image, which are stored in the EXIF data. Depending on your camera and use case, the reference data for your images may be stored separately. If so, load image positions in the ‘Reference’ window before proceeding. The camera and lens parameters are also usually stored in the EXIF data. If the camera and lens parameters are not stored in your images EXIF data, add this information before proceeding. To do so, navigate to Tools →Camera Calibration. Otherwise, save your project and proceed to the code.

The Python Code

The python code below allows you to set the parameters used to align images. The parameters below are equivalent to the following settings in the GUI:

  • Match_accuracy = 1 → High accuracy
  • gen_pre = True → Generic preselection enabled
  • ref_pre = True → Reference preselection enabled
  • mask_filt = True and mask_tie = True → Apply Masks to Tie Points (under the Advanced alignment settings)
  • key_lim = 60,000 → Key point limit = 60k (Advanced settings)
  • tie_lim = 0 → Tie point limit = 0 (Advanced settings)

The code also allows you to perform the camera optimization step after the initial alignment is completed. To disable camera optimization set ‘optimus = False

Note the following:

  • The project path/name expects a list, allowing multiple projects to be processed
  • Similarly, the chunk labels ‘clbls’ also expects a list so multiple chunks can be processed in each project.
  • The project is saved after each processing step is completed.
  • If enabled, the current chunk is duplicated before camera optimization.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import Metashape

# Alignment parameters
match_accuracy = 1 # matching accuracy (upscaling/downscaling)
gen_pre = True # generic preselection 
ref_pre = True # reference preselection
mask_filt = True # Filter points by mask
mask_tie = True # Apply masks to tie points
filter_stationary = False # Exclude stationary tie points
key_lim = 60000 # Key point limit
tie_lim = 0 # Tie point limit
keep_key = False # Keep key points
match_reset = False # Reset current matches

min_point_proj = 2 # Minimum number of point projections
distort_adapt_fit = False # Adaptive fitting of distortion coefficients

# Camera interior/exterior orientations and lens distortion options
optimus = True
opt_correct_fit = True # Enable optimization of additional corrections
opt_adapt_fit = True # Enable adaptive fitting of distortion coefficients
tie_cov = True # Estimate tie point covariance

def copy_new_chunk(chunk, old_label, new_label):
    new_chunk = chunk.copy()
    clbl_i = str("".join([old_label,new_label]))
    new_chunk.label = clbl_i
    return clbl_i

def find_chunk(doc, label):
    if type(doc) != Metashape.Document:
       print("Not a valid MetaShape file!")
       return False
    if type(label) != str:
       print("Please provide a string as input!")
       return False
    for chunk in doc.chunks:
       if chunk.label == label:
          print(f"Chunk {label} was found.")
          return(chunk)
    print(f"Chunk {label} was not found!")
    return None

def align_images(chunk, match_accuracy,  gen_pre,  ref_pre,  mask_filt,  mask_tie,  filter_stationary,  key_lim,  tie_lim, keep_key, match_reset):
    chunk.matchPhotos(downscale = match_accuracy, 
    generic_preselection = gen_pre, 
    reference_preselection = ref_pre, 
    filter_mask = mask_filt, 
    mask_tiepoints = mask_tie, 
    filter_stationary_points = filter_stationary, 
    keypoint_limit = key_lim, 
    tiepoint_limit = tie_lim, 
    keep_keypoints = keep_key, 
    reset_matches = match_reset
    )
    
    chunk.alignCameras(min_image = min_point_proj,
    adaptive_fitting = distort_adapt_fit)

# Main body of program 
# path and file name of your Metashape project. The loop expects a list of projects
Projs = ["/data2/metashape_course/20230828_mcourse.psx"
]

# chunk(s) to process within a project - list
clbls = [                                                                      
        "run1", 
        ]
doc = Metashape.app.document
    # project loop
for proj in Projs:
    doc.open(proj)
    proj_name = proj.split("/")[len(proj.split("/"))-1]
    proj_path = "/".join(proj.split("/")[:-1])
    for clbl in clbls:
        for chunk in doc.chunks:   
            if chunk.label != clbl:
                continue
            print("")
            print("Now processing project <", proj_name, ">...")
            # find chunk by name
            chunk = find_chunk(doc, clbl)
            # sets selected chunk as active
            doc.chunk = chunk
            align_images(chunk, match_accuracy,  gen_pre,  ref_pre,  mask_filt,  mask_tie,  filter_stationary,  key_lim,  tie_lim, keep_key, match_reset)
            doc.save() # save after alignment
            if optimus:
                oc_clbl = copy_new_chunk(chunk,clbl,"-OC") # copy to new chunk before proceeding
                chunk = find_chunk(doc, oc_clbl)
                doc.chunk = chunk
                chunk.optimizeCameras(tiepoint_covariance=tie_cov,fit_f=True,fit_cx=True,fit_cy=True,fit_b1=True,fit_b2=True,fit_k1=True,fit_k2=True,fit_k3=True,fit_k4=True,fit_p1=True,fit_p2=True,adaptive_fitting=opt_adapt
                doc.save()

Running the Code in Metashape

  1. To run the code in Metashape, copy it into your python or text editor and save it as ‘metashape_align.py’
  2. Change the path to your project in the Projs variable (Projs expects a list)
  3. Open Metashape and navigate to Tools → Run Script
  4. In the window that opens, select the script ‘metashape_align.py’ and in the ‘Arguments’ dialog box enter ‘-r’
  5. Click ‘Ok’
In Tools -> Run Script enter the path of your python code and add the argument -r

If everything works correctly then Metashape will start to align your images!

Alignment in progress

Depending on the size of your project and the quality/overlap of your images you should eventually see something like the following screenshot.

Success!

Wrapping Up

Now you should be able to automate image alignment in Agisoft Metashape using python.

Python
Drones
Python Programming
Computer Science
Science
Recommended from ReadMedium