Agisoft Metashape

Agisoft Metashape => Python and Java API => Topic started by: Yoann Courtois on October 31, 2019, 02:30:00 PM

Title: Fail to load calibration
Post by: Yoann Courtois on October 31, 2019, 02:30:00 PM
Hello !

I struggle with personal calibration loading. Here is my code :

Code: [Select]
chunk=Metashape.app.document.chunk

# importing cameras from only one sensor

my_sensor = chunk.sensors[0]
my_sensor.type = Metashape.Sensor.Type.Fisheye
my_sensor.user_calib = Metashape.Calibration()
my_sensor.calibration.load("my_path/my_calibration.xml", format='xml')
It return False ...

I've checked everything (file existence, sensor name, sensor type, etc.).
I've able to set my_sensor.fixed = True, but not able to load my calibration ...

Thanks for your help
Title: Re: Fail to load calibration
Post by: Alexey Pasumansky on October 31, 2019, 04:03:41 PM
Hello Yoann,

Please try the following:
Code: [Select]
my_sensor = chunk.sensors[0]
my_sensor.type = Metashape.Sensor.Type.Fisheye
my_calib = Metashape.Calibration()
my_calib.load("my_path/my_calibration.xml", format='xml')
my_sensor.user_calib = my_calib
also make sure that the calibration file that you are loading also has "fisheye" type.
Title: Re: Fail to load calibration
Post by: Yoann Courtois on October 31, 2019, 04:18:14 PM
It's indeed a fisheye type calibration file.
my_calib.load() return also False ...
Title: Re: Fail to load calibration
Post by: Alexey Pasumansky on October 31, 2019, 05:11:47 PM
Hello Yoann,

Which version of Metashape you are using?

You might need to use "format=Metashape.CalibrationFormatXML" instead of string parameter value.

However, are there any errors related to this operation?
Title: Re: Fail to load calibration
Post by: Yoann Courtois on October 31, 2019, 05:36:42 PM
Hello Alexey,

I'm currently using Metashape 1.5.0, but regarding change log, nothing changed until 1.5.5.
I'm gonna upgrade on 1.6.0 when it will be released, but most of my code will need changes at that point !

Trying "format=Metashape.CalibrationFormatXML" return me an AttributeError: module 'Metashape' has no attribute 'CalibrationFormatXML'
Title: Re: Fail to load calibration
Post by: Alexey Pasumansky on October 31, 2019, 06:56:39 PM
Hello Yoann,

I'm not observing issues with the following code in 1.5.5:
Code: [Select]
n [4]: my_sensor = chunk.sensors[0]
my_sensor.type = Metashape.Sensor.Type.Frame
my_calib = Metashape.Calibration()
my_calib.load(path, format="xml")
my_sensor.user_calib = my_calib
The calibration data is loaded to the Initial values for the sensor.
Title: Re: Fail to load calibration
Post by: Yoann Courtois on November 04, 2019, 11:58:01 AM
Ok, after some debug and retry, I guess some old code meddled in my work.
This code indeed works well in 1.5.0 too.

Thanks for your help.
Regards
Title: Re: Fail to load calibration
Post by: Yoann Courtois on April 14, 2021, 05:02:58 PM
Dear Alexey,

We recently updated to 1.7.1 version, but we face up to a new problem about calibration import.
We use following code :

Code: [Select]
precalibation = Metashape.Calibration()
precalibation.load(path="mycalib.xml", format=Metashape.CalibrationFormatXML)

But we got a RunTimeError :

Code: [Select]
RuntimeError: Can't load calibration
Nevertheless, our variable "precalibation" has got mycalib.xml parameters... So why have we got this error ? That's strange...

Regards
Title: Re: Fail to load calibration
Post by: Alexey Pasumansky on April 14, 2021, 05:55:54 PM
Hello Yoann,

Can you post here the contents of the XML file or attach it to the reply?
Title: Re: Fail to load calibration
Post by: Yoann Courtois on April 14, 2021, 06:12:44 PM
Hello Alexey,

Here it is !
Title: Re: Fail to load calibration
Post by: Alexey Pasumansky on April 14, 2021, 07:00:26 PM
Hello Yoann,

It seems that API doesn't yet support Fisheye calibration import. It will be fixed in the next 1.7.3 update.
Title: Re: Fail to load calibration
Post by: Yoann Courtois on April 15, 2021, 03:51:48 PM
Actually, after some more tests, the calibration import works !

We managed to catch the RunTimeError exception and then we were able to set our sensor.user_calib with our imported calibration.
It looks the exception doesn't affect the import.

Let me know if it could be fixed one day so that we could removed the exception catch.

Regards
Title: Re: Fail to load calibration
Post by: mihapajo123 on May 10, 2021, 09:01:07 PM
Hello i need help :)

I'm interested in how to write in the script that I'm using a fisheye camera and that I already have the internal parameters given. These internal parameters, it would make sense to always ask me when I run the script.

Thank you very much for your help




MY SKRIPT:


import Metashape
import time, math, os, glob

TYPES = ["DNG", "JPG", "JPEG", "TIF", "TIFF"] #supported file types/extensions

def calc_reprojection(chunk):
   point_cloud = chunk.point_cloud
   points = point_cloud.points
   npoints = len(points)
   projections = chunk.point_cloud.projections
   err_sum = 0
   num = 0
   maxe = 0

   point_ids = [-1] * len(point_cloud.tracks)
   #point_errors = dict()
   for point_id in range(0, npoints):
      point_ids[points[point_id].track_id] = point_id

   for camera in chunk.cameras:
      if not camera.transform:
         continue
      for proj in projections[camera]:
         track_id = proj.track_id
         point_id = point_ids[track_id]
         if point_id < 0:
            continue
         point = points[point_id]
         if not point.valid:
            continue
         error = camera.error(point.coord, proj.coord).norm() ** 2
         err_sum += error
         num += 1
         #if point_id not in point_errors.keys():
         #   point_errors[point_id] = [error]
         #else:
         #   point_errors[point_id].append(error)
         #if error > maxe: maxe = error
           
   reproj = math.sqrt(err_sum / num)
   return (reproj) #return (sigma, point_errors, maxe)

def autoprocess():

   #project_path = "D:/Project/project.psx"
   project_path = Metashape.app.getSaveFileName("Specify project save filename:", filter = "Metashape Project (*.psx)")
   if not project_path:
      Metashape.app.messageBox("Invalid project path")
      return 0
   image_folder_path = Metashape.app.getExistingDirectory("Specify the folder with images:")
   if not image_folder_path:
      Metashape.app.messageBox("Invalid image folder path")
      return 0
   reference_path = Metashape.app.getOpenFileName("Specify reference file with targes:", filter = "CSV files (*.txt *.csv)")
   if not reference_path:
      Metashape.app.messageBox("Invalid reference file path")
      return 0
     
   doc = Metashape.Document()
   doc.save(project_path)
   doc = Metashape.app.document #open the same project in applicaiton GUI
   doc.open(project_path)
   
   chunk = doc.addChunk()
   chunk.crs = Metashape.CoordinateSystem('LOCAL_CS["Local Coordinates (m)",LOCAL_DATUM["Local Datum",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]]]') #set crs to local coordinates (m)
   
   image_list = [photo for photo in glob.iglob(image_folder_path + "\\*.*", recursive = False) if os.path.isfile(photo) and os.path.splitext(photo)[1][1:].upper() in TYPES]
   chunk.addPhotos(image_list) #add images
   doc.save()
   
   
   #align photos
   chunk.matchPhotos(downscale = 4, generic_preselection = True, keypoint_limit = 50000, tiepoint_limit = 4000, guided_matching = True)   #we recommend downscale = 1, guided_matchinf = False
   chunk.alignCameras(adaptive_fitting = False) #we recommend adaptive_fitting = False
   doc.save()
   
   #gradual selection Reconstruction uncertainty
   #criterion = True
   #n = 0
   #while criterion:
   #   n += 1
   #   TARGET_PERCENT = 50
    #
   #   f = Metashape.PointCloud.Filter()
   #   f.init(chunk, criterion = Metashape.PointCloud.Filter.ReconstructionUncertainty)
   #   list_values = f.values
   #   list_values_valid = list()
   #   for i in range(len(list_values)):
   #      if points.valid:
   #         list_values_valid.append(list_values)
   #   list_values_valid.sort()
   #   target = int(len(list_values_valid) * TARGET_PERCENT / 100)
   #   threshold = list_values_valid[target]
   #   if threshold < 50:
   #      f.selectPoints(threshold)
   #      f.removePoints(threshold)
   #   else:
   #      f.selectPoints(50)
   #      f.removePoints(50)
   #   chunk.optimizeCameras(fit_f = True, fit_cx = True, fit_cy = True, fit_k1 = True, fit_k2 = True, fit_k3 = True, fit_p1 = True, fit_p2 = True, fit_b1 = True, fit_b2 = True, fit_corrections = False, tiepoint_covariance = True)
   #   
   #   reproj =  calc_reprojection(chunk)
   #   if (float(chunk.meta['OptimizeCameras/sigma0']) >= 1) or (reproj >= 3.0):
   #      criterion = True
   #   else:
   #      criterion = False
   #   if (threshold <= 10) and (n > 2):
   #      criterion = False
   #doc.save()
   #
   ##gradual selection Projection accuracy
   #criterion = True
   #n = 0
   #while criterion:
   #   n += 1
   #   TARGET_PERCENT = 50
    #
   #   f = Metashape.PointCloud.Filter()
   #   f.init(chunk, criterion = Metashape.PointCloud.Filter.ProjectionAccuracy)
   #   list_values = f.values
   #   list_values_valid = list()
   #   for i in range(len(list_values)):
   #      if points.valid:
   #         list_values_valid.append(list_values)
   #   list_values_valid.sort()
   #   target = int(len(list_values_valid) * TARGET_PERCENT / 100)
   #   threshold = list_values_valid[target]
   #   if threshold < 2:
   #      f.selectPoints(2)
   #      f.removePoints(2)
   #   elif threshold < 3:
   #      f.selectPoints(threshold)
   #      f.removePoints(threshold)
   #   else:
   #      f.selectPoints(3)
   #      f.removePoints(3)
   #   chunk.optimizeCameras(fit_f = True, fit_cx = True, fit_cy = True, fit_k1 = True, fit_k2 = True, fit_k3 = True, fit_p1 = True, fit_p2 = True, fit_b1 = True, fit_b2 = True, fit_corrections = False, tiepoint_covariance = True)
   #   
   #   if (threshold <= 2) and (n > 2):
   #      criterion = False
   #doc.save()
   #
   ##modify tie point accuracy
   #
   #chunk.tiepoint_accuracy = 0.1
   #criterion = True
   #n = 0
   #while criterion:
   #   n += 1
   #   chunk.optimizeCameras(fit_f = True, fit_cx = True, fit_cy = True, fit_k1 = True, fit_k2 = True, fit_k3 = True, fit_p1 = True, fit_p2 = True, fit_b1 = True, fit_b2 = True, fit_corrections = False, tiepoint_covariance = True)
   #   reproj =  calc_reprojection(chunk)
   #   if (float(chunk.meta['OptimizeCameras/sigma0']) >= 1) or (reproj >= 3.0):
   #      criterion = True
   #   else:
   #      criterion = False
   #   if (n > 5):
   #      criterion = False
   #doc.save()

   ####

   #detect markers
   chunk.detectMarkers(target_type = Metashape.CircularTarget12bit, tolerance = 50)
   chunk.importReference(reference_path, format = Metashape.ReferenceFormatCSV, columns = "nxyz", delimiter = ",") #import coordinates from file, delimiter = "comma"
   chunk.marker_location_accuracy = Metashape.Vector([0.002, 0.002, 0.002])
   chunk.optimizeCameras(fit_f = True, fit_cx = True, fit_cy = True, fit_k1 = True, fit_k2 = True, fit_k3 = True, fit_k4 = True, fit_p1 = True, fit_p2 = True, fit_b1 = True, fit_b2 = True, fit_corrections = False, tiepoint_covariance = True) #we recommend fit_corrections = False
   chunk.updateTransform()
   doc.save()
   
   ###add scalebars???
   
   ##gradual selection Reprojction Error
   #criterion = True
   #n = 0
   #while criterion:
   #   n += 1
   #   TARGET_PERCENT = 90
    #
   #   f = Metashape.PointCloud.Filter()
   #   f.init(chunk, criterion = Metashape.PointCloud.Filter.ReprojectionError)
   #   list_values = f.values
   #   list_values_valid = list()
   #   for i in range(len(list_values)):
   #      if points.valid:
   #         list_values_valid.append(list_values)
   #   list_values_valid.sort()
   #   target = int(len(list_values_valid) * TARGET_PERCENT / 100)
   #   threshold = list_values_valid[target]
   #   if threshold >= 3:
   #      f.selectPoints(threshold)
   #      f.removePoints(threshold)
   #   else:
   #      f.selectPoints(3)
   #      f.removePoints(3)
   #   chunk.optimizeCameras(fit_f = True, fit_cx = True, fit_cy = True, fit_k1 = True, fit_k2 = True, fit_k3 = True, fit_p1 = True, fit_p2 = True, fit_b1 = True, fit_b2 = True, fit_corrections = False, tiepoint_covariance = True)
   #   
   #   reproj =  calc_reprojection(chunk)
   #   if (float(chunk.meta['OptimizeCameras/sigma0']) >= 1) or (reproj >= 3.0):
   #      criterion = True
   #   else:
   #      criterion = False
   #   if (threshold < 3) and (n > 3):
   #      criterion = False
   #doc.save()
   ####
   
   chunk.resetRegion()
   #build dense cloud
   chunk.buildDepthMaps(downscale = 4, filter_mode = Metashape.AggressiveFiltering)
   doc.save()
   chunk.buildDenseCloud(point_colors = True, point_confidence = True)
   doc.save()
   
   ##build mesh
   #chunk.depth_maps = None
   #chunk.buildDepthMaps(downscale = 4, filter_mode = Metashape.MildFiltering)
   #doc.save()
   #chunk.buildModel(surface_type = Metashape.Arbitrary, source_data = Metashape.DataSource.DenseCloudData, face_count = Metashape.HighFaceCount, vertex_colors = True)
   #doc.save()
   #
   ##build texture
   #chunk.buildUV(mapping_mode = Metashape.GenericMapping, texture_size = 8192)
   #chunk.buildTexture(blending_mode = Metashape.MosaicBlending, texture_size = 8192, fill_holes = True, ghosting_filter = True, texture_type = Metashape.Model.TextureType.DiffuseMap)
   #doc.save()
   
   #export
   export_base_path = os.path.dirname(doc.path)
   try:
      os.mkdir(export_base_path + "/REZULTATI")
   except:
      print("Can't create directory")
      return 0
   
   if chunk.dense_cloud:
      chunk.exportPoints(path = export_base_path + "/REZULTATI/1_OBLAK_TOCK.las", format = Metashape.PointsFormatLAS, source_data = Metashape.DataSource.DenseCloudData, save_colors = True)
   
   #if chunk.model:
   #   chunk.exportModel(path = export_base_path + "/REZULTATI/2_3D_MODEL.obj", format = Metashape.ModelFormatOBJ, texture_format = Metashape.ImageFormatJPEG, save_texture = True, save_uv = True, save_normals = True, save_colors = True)
   
   chunk.exportReport(path = export_base_path + "/REZULTATI/3_Fotogrametrično_poročilo.pdf")
   
   #undistort
   #for camera in chunk.cameras:
   #   image = camera.image()
   #   calib = camera.sensor.calibration
   #   undist = image.undistort(calib, center_principal_point = True, square_pixels = True)
   #   label = camera.label
   #   undist.save(export_base_path + "/REZULTATI/" + camera.label + os.path.basename(camera.photo.path)[-4:])
   
   print("ODLIČNO, BREZ NAPAK JE OBDELALO FOTOGRAMETRIČNO OBDELAVO!!")
   Metashape.app.messageBox("ODLIČNO, BREZ NAPAK JE OBDELALO FOTOGRAMETRIČNO OBDELAVO!!")
   return 1
   
   
autoprocess()
Title: Re: Fail to load calibration
Post by: Yoann Courtois on May 10, 2021, 09:49:54 PM
Hi mihapajo123,

To set your camera as a fisheye lens, you should use the following code :

Code: [Select]
sensor.type = Metashape.Sensor.Type.Fisheye
To apply your personnal internal parameters, use this :

Code: [Select]
personal_param = Metashape.Calibration()
personal_param.load(path=my_path)
sensor.user_calib = personal_param

Regards
Title: Re: Fail to load calibration
Post by: mihapajo123 on May 11, 2021, 07:57:07 AM
WELCOME,

LET ME KNOW THIS ERROR ATTACHED IN THE PICTURE. Is it possible for you to enter the code parameters into my code, since I am not skilled in javascript programming. Are you more proficient in javascript programming? If you had I would have some questions for you.
Title: Re: Fail to load calibration
Post by: Alexey Pasumansky on May 12, 2021, 04:58:08 PM
Hello mihapajo123,

If you require to switch all the cameras to Fisheye mode, then you should do it in the following way after the images have been loaded to the chunk:

Code: [Select]
for sensor in chunk.sensors:
    sensor.type = Metashape.Sensor.Type.Fisheye