I had a student provide the following script, which is intended to take a chunk, align the cameras within it, duplicate the aligned chunk, disable the aligned cameras and then repeat until there are no more cameras to align. This used to work, but it has been a while since I ran it (I changed all the PhotoScan references to Metashape). The codeis run using "Run Script" and the following code is entered at the console:
mpkw = {
'accuracy': Metashape.Accuracy.LowestAccuracy,
'preselection': Metashape.Preselection.NoPreselection,
'keypoint_limit': 40000,
'tiepoint_limit': 4000
}
Metashape.app.document.iter_align(mpkw=mpkw)
The purpose of the problem section of code (lines 116-120) is adding the newly created chunk2 to the list of chunks in the doc. It did work before but now gives me the following error:
X:/projects/psplus_iter/msplus_iteralign.py in iter_align(doc, chunks, mpkw, ackw)
116
117 else:
--> 118 doc.addChunk(chunk2)
119 # doc.append(doc,chunk2)
120 chunk = chunk2
TypeError: addChunk() takes no arguments (1 given)
I tried the "doc.append" function with no luck. Can anyone suggest a solution?
"""
Metashape utility functions from the PSPlus package.
Example:
Metashape.app.document.iter_align(mpkw={'accuracy': Metashape.Accuracy.LowAccuracy,'preselection': Metashape.Preselection.NoPreselection,'keypoint_limit': 10000,'tiepoint_limit': 1000})
"""
import os
#
# Global variables
#
_msg = '[PSPlus]'
_ver = [int(v) for v in Metashape.app.version.split('.')]
#
# Helper functions
#
def _get_align_camera(chunk, inverse=False):
"""Get list of aligned cameras (obj) in chunk, or non-aligned if `inverse`=True."""
return [c for c in chunk.cameras if isinstance(c.center, Metashape.Vector) != inverse] # c.key
def _remove_camera(chunk, cam):
"""Remove a list of cameras (obj) from the chunk."""
return chunk.remove(cam)
#
# Main utility functions
#
def align_photos(chunk, mpkw=None, ackw=None, r=True, **kwargs):
# Check what to do
do_mp = r if r else kwargs.get('do_mp', r)
do_ac = r if r else kwargs.get('do_ac', kwargs.get('do_mp', r))
if not(do_mp or do_ac):
return r
# Inform and log
print('%s Running: align_photos for chunk `%s`' % (_msg, chunk.label))
# Function prep and defaults
mpkw = {} if mpkw is None else mpkw
ackw = {} if ackw is None else ackw
# Metashape functions
# 1 - Match photos
if do_mp and r:
r = chunk.matchPhotos(**mpkw)
# 2 - Align cameras
if do_ac and r:
r = chunk.alignCameras(**ackw)
return r
def iter_align_chunk(chunk, mpkw=None, ackw=None):
"""Align cameras in a chunk, return a chunk copy with unaligned cameras from input chunk."""
print('%s Running: iteralign_chunk for chunk `%s`' % (_msg, chunk.label))
align_photos(chunk, mpkw=mpkw, ackw=None)
chunk2 = chunk.copy()
chunk.remove(_get_align_camera(chunk, inverse=True))
chunk2.remove(_get_align_camera(chunk2))
return chunk2
def iter_align(doc, chunks=None, mpkw=None, ackw=None):
"""
Iteratively align cameras for each `chunks` in `doc`.
Example (requires version >= 1.1.0):
>>> # Run this script at start of session.
>>> # Load a document or add a chunk and cameras.
>>> mpkw = {
'accuracy': Metashape.Accuracy.LowAccuracy,
'preselection': Metashape.Preselection.NoPreselection,
'keypoint_limit': 10000,
'tiepoint_limit': 1000
}
>>> Metashape.app.document.iter_align(mpkw=mpkw)
:param doc: Metashape.Document instance. Automatically sent when called as an instance method.
:param chunks: List of document chunks. If None (default), then all chunks are used (optional).
:param mpkw: Dict of args and kwargs for Metashape.matchPhotos (optional).
:param ackw: Dict of args and kwargs for Metashape.alignCameras (optional).
:return:
"""
print('%s Running: iteralign for document `%s`' % (_msg, doc.path))
if chunks is None:
chunks = doc.chunks
for chunk in chunks:
n_iter = 1
c_label = chunk.label
print('%s Note: Starting iterations for chunk `%s`...' % (_msg, c_label))
while True:
chunk2 = iter_align_chunk(chunk, mpkw=mpkw, ackw=None)
chunk2.label = '%s-iter%i' % (c_label, n_iter)
if len(_get_align_camera(chunk)) == 0:
print('%s Note: chunk `%s` didn\'t align cameras.' % (_msg, chunk.label))
break
elif len(chunk2.cameras) == 0:
print('%s Note: Next iter chunk `%s` has no cameras to align.' % (_msg, chunk2.label))
break
else:
# doc.addChunk(chunk2)
doc.append(doc,chunk2)
chunk = chunk2
n_iter = n_iter +1
print('%s Note: Completed %i iteration(s) for chunk `%s`.' % (_msg, n_iter - 1, c_label))
print('%s Complete: iteralign for document `%s`' % (_msg, doc.path))
#
# Add functions to the Metashape namespace
#
if __name__ == '__main__':
# # Add functions to new menu # TODO add this and gui support for variables
# Metashape.app.addMenuItem('%s/%s' % (_msg, doc_get_info.__name__), doc_get_info)
# Adding to Metashape name space only works for verions >= 1.1.0
if _ver[0] >= 1 and _ver[1] >= 1:
# General functions added to Metashape name space
# Camera methods
# Chunk methods
Metashape.Chunk.get_align_camera = _get_align_camera
Metashape.Chunk.iter_align_chunk = iter_align_chunk
# Document methods
Metashape.Document.iter_align = iter_align