PINGMapper icon indicating copy to clipboard operation
PINGMapper copied to clipboard

Rectification with heading

Open CameronBodine opened this issue 1 year ago • 16 comments

Is your feature request related to a problem? Please describe. A vessel conducting a straight transect in open water may need to nose into the current in order to maintain positioning on the transect. This can result in scans which are not perpendicular to the transect. Since PM uses COG based on a smoothed trackline, the resulting pings are mislocated.

Describe the solution you'd like Option to georectify sonar mosaics from vessel heading rather then COG.

Describe alternatives you've considered NA

Additional context NA

CameronBodine avatar Jun 10 '24 17:06 CameronBodine

TEST

Tried rectification with COG (left) and heading (right). Since pings are rectified from their waterfall version (essentially rubber sheeting), rectification with heading has minimal effect. The rectification needs to be done for each ping independently, then mosaiced into a final image.

image

CameronBodine avatar Jun 10 '24 17:06 CameronBodine

Success!

Image

But very slow... I have ideas.

CameronBodine avatar Jan 27 '25 19:01 CameronBodine

Constructing sparse arrays may be the fastest. https://docs.scipy.org/doc/scipy/reference/generated/scipy.sparse.coo_matrix.html

CameronBodine avatar Feb 02 '25 12:02 CameronBodine

Implemented sparse arrays. Much faster. However, the NearestNDInterpolator is very slow. I did manage to get a mask using convex hull which works decent for masking interpolation output. Additionally, the whole process is very memory intensive. Likely need a numpy memory mapping approach.

CameronBodine avatar Feb 04 '25 19:02 CameronBodine

Check out gdal.grid:

gdal.Grid(output_raster, point_shp, zfield="elevation", 
          outputSRS='EPSG:4326', # Replace with your desired CRS
          format="GTiff", algorithm="invdist:power=2", 
          width=100, height=100) # Adjust dimensions as needed

https://gis.stackexchange.com/questions/254330/python-gdal-grid-correct-use

CameronBodine avatar Feb 12 '25 09:02 CameronBodine

Masking interpolated grid can be done by:

  • Fitting smoothed trackline
  • Fitting smoothed range extent
  • Create polygon from smoothed track and range lines

CameronBodine avatar Feb 12 '25 09:02 CameronBodine

For memory issues, will need to write each chunks x, y coords to a file for each chunk.

  • [x] The function that calculates each pings coords in parallel needs to process on a chunk basis, then iterate each chunk's pings.

CameronBodine avatar Feb 12 '25 09:02 CameronBodine

Fixed the excessive memory usage issue with c1f9785d0e32039d28925680b6981a4407126969. It is not necessary to write any intermediate data files.

Tried gdal.Grid but the process was very slow. An implementation example is in c1f9785d0e32039d28925680b6981a4407126969 but has been commented out.

Interpolation continues to be the slowest part of the process..

CameronBodine avatar Feb 13 '25 18:02 CameronBodine

Making progress:

Image

On the inner bend, there appears to be 3 crab pots in the rubbersheeting approach where there should only be 1.

Image

That is because during the range extent calculation during trackline smoothing, overlapping (crossing) pings are identified and reoriented so they do not cross.

https://github.com/CameronBodine/PINGMapper/blob/7a09faf4960b7053a6f9f3d359b7db74e2e42330/pingmapper/class_rectObj.py#L676-L702

This approach is intentional and helps fix rectification errors while rubbersheeting (image overlapping on itself) BUT has an impact on features imaged.

Rectification with heading is still slower than rubbersheeting. Things that help include:

  • Decreasing the chunk size, thus decreasing number of pixels to interpolate for each chunk.
  • Filtering out bends.

CameronBodine avatar Feb 13 '25 20:02 CameronBodine

SRC

  • [x] Added functionality to export slant range corrected imagery with da0b6cc6f121e35574e88e3239e5ba87f13655d6

Masking w/ Coverage

Trying to clip or mask the interpolated raster to the coverage of the pings has been difficult. The goal is essentially to constrain the interpolation between pings, but not beyond them, so that their aren't strange interpolation anomalies around the interpolation, as shown below:

Image

The problem is particularly noticeable on the left which is the maximum range extent.

I have tried creating a mask using the trackline and the maximum ping extent. Essentially construct a polygon from the min and max coordinates for each ping. This approach was implemented in 6bdeeba72cb6f68c187fcac2bd13ebb94d0e1e13 but did not always work. Since the maximum range coordinate are not in "order" and cross each other, the resulting mask polygon can be misshapen, resulting in a mask, in this case, where the corner is chopped off:

Image

Masking w/ Interpolation Distance Mask

It occurred to me that the distance mask used to mask the interpolation could be used, it just needed to be dilated. I did not try scipy.binary_erosion, but it may be viable. I did quickly find this solution which worked really well! Implemented in 79bfc11973518b793f97bb2f208469a92ab72346 resulting in:

Image

There may be a tiny bit of edge effect on the left, but negligible. But along the track and the top and bottom are perfect! Doesn't seem to slow either. That's a win!

Now to test on the terrible recording...

CameronBodine avatar Feb 14 '25 09:02 CameronBodine

Drumroll please...! And:

Image

whelp...

CameronBodine avatar Feb 14 '25 15:02 CameronBodine

Examining the mosaic, there are strange across track artifacts. It looks like pixel coordinates are not aligning.

Image

Image

There is some sort of precision error when calculating coordinates. It could stem from a few sources:

  • Range calculations
  • Heading precision
  • Projecting Humminbird coords to UTM
  • others?

CameronBodine avatar Feb 14 '25 16:02 CameronBodine

Speed corrected sonogram for reference:

Image

CameronBodine avatar Feb 14 '25 16:02 CameronBodine

Smoothing the heading made a huge difference (f1b9d59f9dbbede266e829b80f2cd46798236bf8)

Image

CameronBodine avatar Feb 14 '25 16:02 CameronBodine

Settled on the best results after adjusting earth radius to match wgs 1984 and making sure pixel coordinates are rounded rather then directly converted to int. Rubber sheeting on left and heading on right:

Image

Image

Image

CameronBodine avatar Feb 14 '25 18:02 CameronBodine

Linear interpolator with griddata is faster and produces better results.

Image

The remaining noise that was present in the NDNeighbors approach have been reconciled with this approach. Nearest Neighbors was producing many of the artifacts. Likely IDW would not have produces this issue.

Still need to work out issues with heading smoothing.

CameronBodine avatar Feb 17 '25 18:02 CameronBodine