Agisoft Metashape

Agisoft Metashape => Python and Java API => Topic started by: LFSantosgeo on May 10, 2018, 11:26:59 PM

Title: Height Above Ground
Post by: LFSantosgeo on May 10, 2018, 11:26:59 PM
Hello!

Is there a way to access the estimated(calculated) height above ground through Python (if already available after alignment)?

Thanks!
Luiz Fernando


Title: Re: Height Above Ground
Post by: Alexey Pasumansky on May 13, 2018, 02:07:58 PM
Hello Luiz,

I can suggest the following:
- for each aligned camera calculate the distance from estimated camera center to every valid tie point that has projections on this photo,
- calculate average value for each camera,
- calculate average value among the cameras.
Title: Re: Height Above Ground
Post by: Erik Holmlund on May 14, 2018, 12:04:21 PM
Hi Alexey,
Might I chime in and say that this would only work on entirely vertical images, as oblique images can give tie points that are very far away from the camera.

This could be fixed quite easily however, by adding something along these lines:

Code: [Select]
# 'distance' is the distance from the tie point to the camera, where distance[2] is the Z value.
# 'threshold' defines how horizontally distant the tie point can be.

if distance.norm() / distance[2] < threshold:
    # Include this distance in the averaging

This threshold could be figured out with some trial and error, or just maths and angles.
Title: Re: Height Above Ground
Post by: Alexey Pasumansky on May 14, 2018, 12:14:00 PM
Hello Erik,

Sure, for more accurate results it may be reasonable to cut off the outliers. I think it may be also good to take into consideration the tie points with the certain number of projections (like 4-5, for example).

Alternative method could be height field mesh surface generation from the sparse cloud (with low polygon count) and then checking the altitude value for the vertices of the mesh surface.
Title: Re: Height Above Ground
Post by: Erik Holmlund on May 14, 2018, 01:01:13 PM
Hi again,
I tried a more brute-force approach which seems to do the trick for me. This code measures distances for each camera to every point in the sparse cloud, and gets relative heights from the ten horizontally closest points. It takes forever to run, but it worked well when I tested it.

Code: [Select]
import PhotoScan
chunk = PhotoScan.app.document.chunk

# Function to transform coordinates to used crs
def transformed(vector):
return chunk.crs.project(chunk.transform.matrix.mulp(vector))

camera_heights = {}

for camera in chunk.cameras:
cam_pos = transformed(camera.center)


# Iterate through every point in the sparse cloud, and measure their distances to the camera.
        heights = {}
for point in chunk.point_cloud.points:
point_pos = transformed(point.coord[:3])

distance = cam_pos - point_pos
xy_distance = distance[:2].norm()  # To be used later for sorting

heights[xy_distance] = distance[2]

# Sort a list of keys (xy distances)
keys = list(heights.keys())
keys.sort()

# Mean of ten points with the lowest xy distances.
h_mean = sum([heights[k] for k in keys[:10]]) / 10

camera_heights[camera.label] = h_mean

# 'break' could be added here to test the loop.


for k, v in camera_heights.items():
print(k, v)

A suggested addition is to actually save the results in a csv or something, since this is a quite lengthy process. Hope it helps!
Title: Re: Height Above Ground
Post by: LFSantosgeo on May 16, 2018, 07:33:27 PM
Thank you Alexey and Erik! I'll give a try on your thoughts... And I'll post it here.