Agisoft Metashape

Agisoft Metashape => Python and Java API => Topic started by: daxils on July 09, 2019, 02:31:50 PM

Title: Exporting object with camera as origin of the coordinate system
Post by: daxils on July 09, 2019, 02:31:50 PM
Hi,
I am trying to export a model I reconstructed in a way that when I import it in other software I get it positioned such that a specific camera is at point (0,0,0) and the mesh is positioned relative to that.

Right now what I can do is export the mesh but I get it positioned in a seemingly random point in space when I import it in blender (while the axis are positioned at point 0).

I can't seem to do this because I'm not sure whether the chunk's transform (chunk.transform.matrix) is actually the mesh's center of mass's position or something else. I am also not sure what the doc.chunk.cameras.transform is relative to.

The endgoal for me is to be able to import the model in let's say blender and have it positioned and oriented such that a specific camera is at point 0. So basically I'm trying to find the pose of the object in the camera's reference frame.

I hope that this was clear,  but if you have any questions please do ask me and I will try to clarify.
Title: Re: Exporting object with camera as origin of the coordinate system
Post by: Alexey Pasumansky on July 09, 2019, 02:57:09 PM
Hello daxils,

Do you think, if the script that applies the translation to the model would be sufficient, if it keeps current model scale and orientation (rotation), while the new origin point (0,0,0) is defined by the 3D point shape, marker or assigned to any aligned camera?
Title: Re: Exporting object with camera as origin of the coordinate system
Post by: daxils on July 09, 2019, 05:51:52 PM
Hello Alexey,

Thank you for your reply.

While I will indeed need to have the origin point at a specific location (camera's center), and to keep the scale, the orientation of the model needs to correspond to its relative rotation compared to the camera.

In other words, I need my model's frame of coordinates to be the camera.

Title: Re: Exporting object with camera as origin of the coordinate system
Post by: Alexey Pasumansky on July 10, 2019, 03:22:36 PM
Hello daxils,

Please check if the following script performs the desired operation. It moves the coordinate system origin to the center of the selected camera (only one camera should be selected) and transforms the orientation of the system, according to the camera orientation.

Code: [Select]
import Metashape

def CS_to_camera():

print("Script started...")
chunk = Metashape.app.document.chunk
if not chunk:
print("Empty project, script aborted")
return
selected = [camera for camera in chunk.cameras if camera.selected and camera.transform and (camera.type == Metashape.Camera.Type.Regular)]
if len(selected) != 1:
print("Select only one aligned camera to procees. Script aborted.")
return
camera = selected[0]
T = chunk.transform.matrix
origin = (-1) * camera.center

R = Metashape.Matrix().Rotation(camera.transform.rotation()*Metashape.Matrix().Diag([1,-1,1]))
origin = R.inv().mulp(origin)
chunk.transform.matrix = T.scale() * Metashape.Matrix().Translation(origin) * R.inv()

Metashape.app.update()


print("System set to " + camera.label + ". Script finished.")
return 1
CS_to_camera()

Metashape.app.addMenuItem("Custom menu/Coordinate system to camera", CS_to_camera)
Title: Re: Exporting object with camera as origin of the coordinate system
Post by: daxils on July 12, 2019, 11:05:12 AM
Thank you Alexey for taking the time to code this script.
Could you explain to me the reasoning behind Diag([1,-1,1])?
Title: Re: Exporting object with camera as origin of the coordinate system
Post by: daxils on July 12, 2019, 12:56:54 PM
I think I found the solution to my problem:

Intuitively, all you need to do is

Code: [Select]
chunk.transform.matrix = chunk.transform.matrix * camera.transform.inv()

However the results for me seemed like they were incoherent with what I expected.
It turned out that this puts the camera where the chunk was previously (and orients it correctly). So if I want it to be at the origin of the coordinates system, I just have to move the chunk to the point (0,0,0) first.

Code: [Select]
chunk.transform.translation = PhotoScan.Vector((0,0,0))


I just tried this and it works like a charm.

So here is the full script (utilizing your very nice touch of adding it as a  menu option) so that other users can find it later
Code: [Select]
import PhotoScan

def CS_to_camera():

print("Script started...")
chunk = PhotoScan.app.document.chunk
if not chunk:
print("Empty project, script aborted")
return
selected = [camera for camera in chunk.cameras if camera.selected and camera.transform]
if len(selected) != 1:
print("Select only one aligned camera to procees. Script aborted.")
return
camera = selected[0]

R = camera.transform

chunk.transform.translation = PhotoScan.Vector((0,0,0))
chunk.transform.matrix = chunk.transform.matrix * R.inv()

print("System set to " + camera.label + " coordinates. Script finished.")
return 1
CS_to_camera()
PhotoScan.app.addMenuItem("Custom menu/Coordinate system to camera", CS_to_camera)

Title: Re: Exporting object with camera as origin of the coordinate system
Post by: Alexey Pasumansky on July 12, 2019, 01:15:01 PM
Could you explain to me the reasoning behind Diag([1,-1,1])?

It was meant to invert the orientation of some axis of the newly assigned coordinate system.
Title: Re: Exporting object with camera as origin of the coordinate system
Post by: andyroo on August 09, 2019, 06:02:53 AM
I am trying to do the same I think - I have a model in a local coordinate system derived from scale bars on a calibration plate, and I am trying to get the model in the frame of reference of one camera (camera at origin and zero the pitch/roll/yaw).

I didn't have much luck with could only rotate the coordinate system to the camera orientation with Alexey's code, and I could only translate the coordinate system to the camera origin with daxils code (with minor tweak):
Code: [Select]
chunk.transform.translation = Metashape.Vector([0,0,0])But can't figure out how to integrate both!

Looking at the two different chunk.transform.matrices I can see that the T.scale() factor is changing the scale, but I'm unclear exactly what that's for - it looks like it makes the rotations work but breaks the translation? Sorry linear algebra and rotation matrices aren't my forte.  Any help is appreciated.

My code:
Code: [Select]
doc = Metashape.app.document
chunk = doc.chunk
camera = chunk.cameras[2]
#below moves coordinate system origin to camera origin, but doesn't rotate everything nicely:
R = camera.transform
chunk.transform.translation = Metashape.Vector([0,0,0])
chunk.transform.matrix = chunk.transform.matrix * R.inv()
#below (instead of 3 lines above) rotates coordinate system to camera pose, but doesn't translate properly
T = chunk.transform.matrix
origin = (-1) * camera.center
R = Metashape.Matrix().Rotation(camera.transform.rotation()*Metashape.Matrix().Diag([1,-1,1]))
origin = R.inv().mulp(origin)
chunk.transform.matrix = T.scale() * Metashape.Matrix().Translation(origin) * R.inv()
Title: Re: Exporting object with camera as origin of the coordinate system
Post by: andyroo on August 16, 2019, 04:40:53 AM
OK figured it out. If I get rid of  the T.scale() factor that I didn't understand, I love everything. final code below:

Code: [Select]
doc = Metashape.app.document
chunk = doc.chunk
camera = chunk.cameras[2]
#below rotates and translates everything to camera frame of reference
T = chunk.transform.matrix
origin = (-1) * camera.center
R = Metashape.Matrix().Rotation(camera.transform.rotation()*Metashape.Matrix().Diag([1,-1,1]))
origin = R.inv().mulp(origin)
chunk.transform.matrix = Metashape.Matrix().Translation(origin) * R.inv()

Andy