micasense / imageprocessing

MicaSense RedEdge and Altum image processing tutorials
https://www.micasense.com
MIT License
257 stars 152 forks source link

Properly georeference and warp images #141

Closed patrickcgray closed 3 years ago

patrickcgray commented 3 years ago

I realize this is a challenging procedure but I'm looking to properly georeference and warp my images after processing. Does anyone have resources for taking this approach? I have been flying some drone surveys over the ocean and need to properly map my images but the ocean surface is too variable to do typical SfM photogrammetry. I have all the information I think I need: lat, lon, altitude, yaw, pitch, and roll. I've even pulled out the exact GPS coords for the corners of the image and when I map those they're in the correct locations but I'm struggling to properly force the image to warp based on those GPS coords.

You can see my detailed code here https://gis.stackexchange.com/questions/379815/georeference-and-warp-a-drone-image-based-on-sensor-orientation-and-location and while this does put it in generally the correct location, this doesn't actually warp it into the proper shape.

Any suggestions for python based approaches to solving this? Is treating the corners as GCPs as I'm doing a feasible approach or should I try something else?

and-viceversa commented 3 years ago

This isn't really an issue for micasense/imageprocessing.

However I would give OpenDroneMap a try. I've had a lot of success there.

ODM processes the "thumbnail" RGB output from the MicaSense library very well. Currently, ODM doesn't play well with the tif band stack output. This is most likely a bug and I'm in the process of writing it up.

Here are some condensed workflows I'm currently using: Raw imagery > micasense/imageprocessing > RGB thumbnail > WebODM > orthomosaic Raw imagery > micasense/imageprocessing > tif stack > Agisoft Metashape > orthomosaic

Agisoft also lets you export individually corrected photos from the ortho, but does not correct each photo independently. I'm still looking for a way to do that as well...

Hope that helps.

John2397 commented 3 years ago

This might be a bit old but I believe I managed to georeference my picture knowing the 4 corner coordinates, although I did not test yet how accurate it is.

The code I used is from a book called Geoprocessing with Python ( Actual code here )

I'm pasting the code with a few extra comments:

# Script to add ground control points to a raster.

import os
import shutil
from osgeo import gdal, osr

# Don't forget to change the directory.
# Make a copy of the original image so we're leaving it alone and changing
# the new one. Try opening the original in a GIS. It doesn't have any
# SRS info and the upper left corner should have coordinates of 0,0.
os.chdir(r'D:\osgeopy-data\Utah')
shutil.copy('cache_no_gcp.tif', 'cache.tif')

# Open the copied image so we can add GCPs to it.
ds = gdal.Open('cache.tif', gdal.GA_Update)

# Create the SRS that the GCP coordinates use.
sr = osr.SpatialReference()
sr.SetWellKnownGeogCS('WGS84')

# Create the list of GCPs.
#The format is gdal.GCP(pixel_lat, pixel_lon, altitude (which is usually 0), pixel_width, height_width )
#For example, for the lower left corner, pixel_width=0, pixel_height=image_height
gcps = [gdal.GCP(-111.931075, 41.745836, 0, 1078, 648),
    gdal.GCP(-111.901655, 41.749269, 0, 3531, 295),
    gdal.GCP(-111.899180, 41.739882, 0, 3722, 1334),
    gdal.GCP(-111.930510, 41.728719, 0, 1102, 2548)]

# Add the GCPs to the raster
ds.SetGCPs(gcps, sr.ExportToWkt())
ds.SetProjection(sr.ExportToWkt())
ds = None

###############################################################################

# This time we'll use the driver to make a copy of the raster and then add
# a geotransform instead of GCPs. This still uses the sr and gcps variables
# from above.
old_ds = gdal.Open('cache_no_gcp.tif')
ds = old_ds.GetDriver().CreateCopy('cache2.tif', old_ds)
ds.SetProjection(sr.ExportToWkt())
ds.SetGeoTransform(gdal.GCPsToGeoTransform(gcps))
del ds, old_ds
and-viceversa commented 3 years ago

@John2397 Again, not specifically an issue for micasense/imageprocessing. Recommend closing this issue.

Four GPCs at the corners of an image don't really do much for you - other than a loose visualization. The number of GCPs is too few, and just matching up those coordinates to the image doesn't account for relief displacement, warping, etc. You need software capable of producing an orthomosaic. OP was having trouble with this due to structure from motion step over open water which can be difficult.

For those arriving from search, this script might point you in the right direction if you are using OpenDroneMap. https://github.com/OpenDroneMap/ODM/tree/master/contrib/orthorectify

poynting commented 3 years ago

@patrickcgray depending on the accuracy required, you may need a direct georeferencing solution, for example, the one Applanix has integrated with Altum:

https://micasense.com/portfolio/high-accuracy-direct-georeferencing-of-the-altum-multi-spectral-uav-camera-and-its-application-to-high-throughput-plant-phenotyping/

But overall, @and-viceversa is correct that this isn't a feature for this library, simply because some external information about the precise pose of each image is required for direct georeferencing. The pose information on the camera and on most drones isn't accurate enough for this type of direct projection application.

Feel free to email support at micasense with further questions on this.