Agisoft Metashape

Agisoft Metashape => Python and Java API => Topic started by: geo_enth3 on June 14, 2022, 11:08:46 AM

Title: Help with OrthoProjection.transform() and .matrix()
Post by: geo_enth3 on June 14, 2022, 11:08:46 AM

When researching about transforming Orthophotos (2D) to realworld coordinates I stumbled over the OrthoProjection class which should contain the information I need (i.e. the transformation matrix to transform the derived orthophoto (of a vertical surface) into the crs of the chunk). However, I do not fully understand how to use this function. The "source" and "target" parameter must be both of type (Orthoprojection) which confuses me. Maybe you can give an example on how to use this function.

I would also appreciate information on the defintion of the OrthoProjection.matrix() . Which transformation is this matrix defining exactly. I so far had no luck retrieving meaningful results by applying this matrix in my project. Maybe because I am misinterpreting it.

Any help is very much appreciated


Title: Re: Help with OrthoProjection.transform() and .matrix()
Post by: Alexey Pasumansky on June 14, 2022, 07:42:05 PM
Hello geo_enth,

Please see an example of script below (via GUI) that allows to generate the orthomosaic in local coordinates using Planar mode with predefined view options.

3x3 projection matrix defines the projection plane.

Code: [Select]
import Metashape
from PySide2 import QtCore, QtGui, QtWidgets

class BuilOrthoLocal(QtWidgets.QDialog):

def __init__ (self, parent):
QtWidgets.QDialog.__init__(self, parent)
self.setWindowTitle("Build Ortho&DEM in Local Coordinates")

self.txtView = QtWidgets.QLabel()
self.txtView.setText("Projection plane:")

self.boxView = QtWidgets.QComboBox()
for element in ["FrontXZ", "BackXZ", "LeftYZ", "RightYZ", "TopXY", "BottomXY", "CurrentView"]:

self.btnQuit = QtWidgets.QPushButton("Close")
#self.btnQuit.setFixedSize(90, 50)
self.btnP1 = QtWidgets.QPushButton("Build Ortho&&DEM")
#self.btnP1.setFixedSize(90, 50)

layout = QtWidgets.QGridLayout()
layout.addWidget(self.txtView, 0, 0, QtCore.Qt.AlignRight)
layout.addWidget(self.boxView, 0, 1, QtCore.Qt.AlignLeft)
layout.addWidget(self.btnP1, 1, 0)
layout.addWidget(self.btnQuit, 1, 1)

proc_build_ortho = lambda: self.build_ortho()
QtCore.QObject.connect(self.btnP1, QtCore.SIGNAL("clicked()"), proc_build_ortho)
QtCore.QObject.connect(self.btnQuit, QtCore.SIGNAL("clicked()"), self, QtCore.SLOT("reject()"))

def build_ortho(self):

doc =
chunk = doc.chunk
if not chunk:
print("Empty project. Script aborted")
return 0
if not chunk.model:
print("No mesh model, can't build orthomosaic. Script aborted.")
return 0
if not len([camera for camera in chunk.cameras if (camera.transform and camera.type == Metashape.Camera.Type.Regular)]):
print("No aligned cameras, can't build orthomosaic. Script aborted.")
return 0

print("Script started...")

PROJECTIONS = {"TopXY": Metashape.Matrix([[1, 0, 0], [0, 1, 0], [0, 0, 1]]),
"BottomXY": Metashape.Matrix([[1, 0, 0], [0, -1, 0], [0, 0, -1]]),
"FrontXZ": Metashape.Matrix([[1, 0, 0], [0, 0, 1], [0, -1, 0]]),
"BackXZ": Metashape.Matrix([[-1, 0, 0], [0, 0, 1], [0, 1, 0]]),
"LeftYZ": Metashape.Matrix([[0, -1, 0], [0, 0, 1], [-1, 0, 0]]),
"RightYZ": Metashape.Matrix([[0, 1, 0], [0, 0, 1], [1, 0, 0]]),

Rot = Metashape.Matrix.Rotation(PROJECTIONS[self.boxView.currentText()])

T = chunk.transform.matrix
lf =[-1000000, -1000000, 0])))

proj = Metashape.OrthoProjection() =
proj.type = Metashape.OrthoProjection.Type.Planar
proj.matrix = Rot * Metashape.Matrix.Rotation(lf.rotation())
chunk.orthomosaic = None
chunk.buildOrthomosaic(surface_data = Metashape.DataSource.ModelData, blending_mode = Metashape.BlendingMode.MosaicBlending, cull_faces = True, projection = proj)
chunk.elevation = None
chunk.buildDem(source_data = Metashape.DataSource.ModelData, interpolation = Metashape.EnabledInterpolation, projection = proj)
chunk.orthomosaic.label = "Orthomosaic " + self.boxView.currentText()
chunk.elevation.label = "DEM " + self.boxView.currentText()

print("Script finished")
return 1

def build_ortho_local():

global app
app = QtWidgets.QApplication.instance()
parent = app.activeWindow()
dlg = BuilOrthoLocal(parent)"Custom menu/Build Ortho&&DEM in Local Coordinates", build_ortho_local)
Title: Re: Help with OrthoProjection.transform() and .matrix()
Post by: geo_enth3 on June 21, 2022, 12:33:07 PM
Dear Alexey,

thank you very much for your help and the code! That looks very promising, however, I still have some troubles as the results are not as expected. Using the "current view" option, for example, does not deliver a correct orthomosaic but it is arbitrarily oriented and not according to "current view" (please see screenshots).

Also the measured coordinates do not match the expected coordinates. I understand most parts of the code, I am only having trouble understanding what the following code is doing exactly:

Code: [Select]
lf =[-1000000, -1000000, 0])))
proj.matrix = Rot * Metashape.Matrix.Rotation(lf.rotation())

But this code is definetely already going into the right direction so I think a little bit more counselling will resolve our problem. Thank you very much again!

PS: if needed I can of course also share my  project (with a testing chunk)
Title: Re: Help with OrthoProjection.transform() and .matrix()
Post by: Alexey Pasumansky on June 21, 2022, 02:49:06 PM
Hello geo_enth,

It works on my side for the projects referenced in local coordinates. So if you can share the project with the camera alignment, thumbnails and rough mesh, it should be sufficient for testing purposes.
Title: Re: Help with OrthoProjection.transform() and .matrix()
Post by: geo_enth3 on June 21, 2022, 03:17:25 PM
Hello Alexey,

ah now I see, I overread this in your initial post. My project is not in local coordinates but it uses a higher order reference system (EPSG:: 31256). What would need to be changed in this case?


Title: Re: Help with OrthoProjection.transform() and .matrix()
Post by: Corensia on September 06, 2022, 10:09:43 AM
+1 Bump

It would be very helpful to know how to apply this to data that uses a coordinate system or at least retains scale.