Forum

Author Topic: Script to Copy Region from One Project to Other Projects  (Read 3786 times)

matt07lx

  • Newbie
  • *
  • Posts: 30
    • View Profile
Script to Copy Region from One Project to Other Projects
« on: April 09, 2024, 06:27:01 PM »
Hi All,

I'm attempting to create a python script that will copy the reconstruction region from one project and export it to a new script that will then apply the same region to other projects. My projects all use the same projected coordinate system, and are located in the same geographic space, so this should work in theory. I'm aware from other posts that the region's coordinates use the chunk's internal system, and that these need to be converted to geocentric, then projected to the proper CRS. When applying them to a new project, this process needs to be done in reverse. When I run the script within the same project it works perfectly. I can save the new script, change the region, then reset it using the new script. However, when I try to apply the new script to a different project in the same location, using the same CRS, it creates a region that is incorrect. Does anyone know where I'm going wrong?

Script to capture the original region:
Code: [Select]
import Metashape, os, glob

doc = Metashape.app.document
chunk = doc.chunk
region = chunk.region
center = chunk.region.center
rot = chunk.region.rot
size = chunk.region.size
crs = chunk.crs
T = chunk.transform.matrix

#File name must include *.py extension
file = Metashape.app.getSaveFileName("Save Script as")

print("Local Bounding Region Coordinates:")
print("Center: ",center)
print("Rotation: ",rot)
print("Size: ",size)

#Now convert them to the project CRS
#center and size are Metashape.Vector
#rotation is Metashape.Matrix - this needs to be broken into three vectors to be converted
#All are changed to strings to write to the new script file
center_CRS = chunk.crs.project(T.mulp(center)) # vector with point coordinates in CRS
center_CRS = str([center_CRS[0],center_CRS[1],center_CRS[2]])
size_CRS = chunk.crs.project(T.mulp(size)) # vector with point coordinates in CRS
size_CRS = str([size_CRS[0],size_CRS[1],size_CRS[2]])
rot1_CRS = chunk.crs.project(T.mulp(Metashape.Vector([rot[0,0], rot[0,1], rot[0,2]]))) # vector with point coordinates in CRS
rot1_CRS = str([rot1_CRS[0],rot1_CRS[1],rot1_CRS[2]])
rot2_CRS = chunk.crs.project(T.mulp(Metashape.Vector([rot[1,0], rot[1,1], rot[1,2]]))) # vector with point coordinates in CRS
rot2_CRS = str([rot2_CRS[0],rot2_CRS[1],rot2_CRS[2]])
rot3_CRS = chunk.crs.project(T.mulp(Metashape.Vector([rot[2,0], rot[2,1], rot[2,2]]))) # vector with point coordinates in CRS
rot3_CRS = str([rot3_CRS[0],rot3_CRS[1],rot3_CRS[2]])
#rot_CRS = Metashape.Matrix([rot1_CRS,rot2_CRS,rot3_CRS])
#the three elements to create region are now in the CRS
print("Bounding Region Coordinates in CRS")
print("Center: ",center_CRS)
print("Rotation: ",rot1_CRS,"\n",rot2_CRS,"\n",rot3_CRS)
print("Size: ",size_CRS)

content = ("import Metashape, os, glob\ndoc = Metashape.app.document\nchunk = doc.chunk\nregion = chunk.region\nT = chunk.transform.matrix\n\n#import the region coordinates in CRS\ncenter_CRS = Metashape.Vector(%s)\nsize_CRS = Metashape.Vector(%s)\nrot1_CRS = Metashape.Vector(%s)\nrot2_CRS = Metashape.Vector(%s)\nrot3_CRS = Metashape.Vector(%s)\n\n#But now we'd have to convert these back to the local chunk coordinates\ncrs = chunk.crs\nbb_center = T.inv().mulp(crs.unproject(center_CRS))\nbb_size = T.inv().mulp(crs.unproject(size_CRS))\nbb_rot1 = T.inv().mulp(crs.unproject(rot1_CRS))\nbb_rot2 = T.inv().mulp(crs.unproject(rot2_CRS))\nbb_rot3 = T.inv().mulp(crs.unproject(rot3_CRS))\nbb_rot = Metashape.Matrix([bb_rot1,bb_rot2,bb_rot3])\n\n#assign the new coordinates to the bounding box in other projects\nchunk.region.center = bb_center\nchunk.region.rot = bb_rot\nchunk.region.size = bb_size\n" % (center_CRS, size_CRS, rot1_CRS,rot2_CRS, rot3_CRS))

with open(path, 'w') as file:
  file.writelines(content)

print("Script exported to: ",path)

Example of a new script output by the above:
Code: [Select]
import Metashape, os, glob
doc = Metashape.app.document
chunk = doc.chunk
region = chunk.region
T = chunk.transform.matrix
crs = chunk.crs

#import the region coordinates in CRS
center_CRS = Metashape.Vector([2326260.9766565366, 4694783.921291048, 383.9612362860649])
size_CRS = Metashape.Vector([2326255.3612297955, 4694784.090214137, 381.2784408229167])
rot1_CRS = Metashape.Vector([2326260.9183688844, 4694785.530955884, 385.6499192495625])
rot2_CRS = Metashape.Vector([2326260.3992965193, 4694785.620727421, 385.6765585270715])
rot3_CRS = Metashape.Vector([2326260.636379602, 4694785.3316533305, 386.04862309706607])

#But now we'd have to convert these back to the local chunk coordinates
bb_center = T.inv().mulp(crs.unproject(center_CRS))
bb_size = T.inv().mulp(crs.unproject(size_CRS))
bb_rot1 = T.inv().mulp(crs.unproject(rot1_CRS))
bb_rot2 = T.inv().mulp(crs.unproject(rot2_CRS))
bb_rot3 = T.inv().mulp(crs.unproject(rot3_CRS))
bb_rot = Metashape.Matrix([bb_rot1,bb_rot2,bb_rot3])

#assign the new coordinates to the bounding box in other projects
chunk.region.center = bb_center
chunk.region.rot = bb_rot
chunk.region.size = bb_size

Paulo

  • Hero Member
  • *****
  • Posts: 1380
    • View Profile
Re: Script to Copy Region from One Project to Other Projects
« Reply #1 on: April 09, 2024, 06:47:57 PM »
Hello Matt,

at first glance, the CRS_size parameter is wrongly calculated:
Code: [Select]
size_CRS = chunk.crs.project(T.mulp(size)) # vector with point coordinates in CRSshould be changed to:
Code: [Select]
size_CRS = T.scale()*size # BB box size in real world CRS
Try and see if it can work...
Best Regards,
Paul Pelletier,
Surveyor

matt07lx

  • Newbie
  • *
  • Posts: 30
    • View Profile
Re: Script to Copy Region from One Project to Other Projects
« Reply #2 on: April 09, 2024, 07:07:14 PM »
Hi Paulo,

Thanks for the suggestion. I tried this and now the region disappears entirely when I apply to the same project or a new one. Any other ideas?

Paulo

  • Hero Member
  • *****
  • Posts: 1380
    • View Profile
Re: Script to Copy Region from One Project to Other Projects
« Reply #3 on: April 10, 2024, 01:56:06 AM »
Ok Jake.

then when you go back from CRS to internal you should  change:
Code: [Select]
bb_size = T.inv().mulp(crs.unproject(size_CRS))with:
Code: [Select]
bb_size = T.inv.scale() * size_CRS
Best Regards,
Paul Pelletier,
Surveyor

matt07lx

  • Newbie
  • *
  • Posts: 30
    • View Profile
Re: Script to Copy Region from One Project to Other Projects
« Reply #4 on: April 10, 2024, 09:51:08 PM »
Hi Paul,

Thanks again - I appreciate your ideas. Unfortunately, while that resolved the issue with the size, it didn't change the final result. There was clearly something wrong with the chunk transform matrix, but I couldn't figure it out. In the end, I found this script for copying the region from one chunk to another: https://github.com/agisoft-llc/metashape-scripts/blob/master/src/copy_bounding_box_dialog.py. I was able to adapt it to my needs. It takes a different approach and doesn't require converting the coordinates at all.