Agisoft Metashape
Agisoft Metashape => Python and Java API => Topic started by: Yoann Courtois on October 31, 2019, 02:30:00 PM
-
Hello !
I struggle with personal calibration loading. Here is my code :
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
-
Hello Yoann,
Please try the following:
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.
-
It's indeed a fisheye type calibration file.
my_calib.load() return also False ...
-
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?
-
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'
-
Hello Yoann,
I'm not observing issues with the following code in 1.5.5:
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.
-
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
-
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 :
precalibation = Metashape.Calibration()
precalibation.load(path="mycalib.xml", format=Metashape.CalibrationFormatXML)
But we got a RunTimeError :
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
-
Hello Yoann,
Can you post here the contents of the XML file or attach it to the reply?
-
Hello Alexey,
Here it is !
-
Hello Yoann,
It seems that API doesn't yet support Fisheye calibration import. It will be fixed in the next 1.7.3 update.
-
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
-
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()
-
Hi mihapajo123,
To set your camera as a fisheye lens, you should use the following code :
sensor.type = Metashape.Sensor.Type.Fisheye
To apply your personnal internal parameters, use this :
personal_param = Metashape.Calibration()
personal_param.load(path=my_path)
sensor.user_calib = personal_param
Regards
-
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.
-
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:
for sensor in chunk.sensors:
sensor.type = Metashape.Sensor.Type.Fisheye