Forum

Author Topic: Problem with iterative chunk alignment  (Read 3586 times)

lefsky

  • Guest
Problem with iterative chunk alignment
« on: August 23, 2019, 06:49:36 PM »
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

Alexey Pasumansky

  • Agisoft Technical Support
  • Hero Member
  • *****
  • Posts: 15168
    • View Profile
Re: Problem with iterative chunk alignment
« Reply #1 on: August 26, 2019, 03:27:22 PM »
Hello lefsky,

In the version 1.5 you should use the following code to duplicate the chunk:

Code: [Select]
chunk2 = chunk.copy()It will automatically add the source chunk's copy to the current document.
Best regards,
Alexey Pasumansky,
Agisoft LLC

Endure1

  • Newbie
  • *
  • Posts: 3
    • View Profile
Re: Problem with iterative chunk alignment
« Reply #2 on: April 11, 2020, 08:57:18 PM »
Hi lefsky,
If the goal is to realign images until all the cameras are aligned, you can use the lines of code below for a much simpler way that keeps all the images in the original chunk.

Code: [Select]
    realign_list = list()
    for camera in chunk.cameras:
          if not camera.transform:
                realign_list.append(camera)
    chunk.alignCameras(cameras = realign_list)