Commit 79c105c4 authored by Andrey Filippov's avatar Andrey Filippov
Browse files

CLAUDE: undistortPxPy(): invert correction direction (getRDistByR)



The RECTILINEAR nadir pass multiplied sampling coordinates by getRByRDist()
(distorted->ideal), but sampling positions must be moved to where the ideal
ray lands in the distorted image - the FORWARD distortion getRDistByR(),
same direction as GeometryCorrection.getImageCoordinates(). The old code
ADDED the common radial distortion to the output instead of removing it.

Evidence (graveyard ref 1763232420_274928, flat constant-disparity terrain
where translation flow must be uniform for a true pinhole image):
- plain NADIR-MERGED edge/center flow ratio 0.965 (expected 0.954 from the
  calibration polynomial: ~4.8 px barrel at the edge),
- old RECTILINEAR 0.952 - worse than uncorrected,
- COLMAP self-calibrated f=1003/k1=-0.385 on the old rectilinear stack.

Co-authored-by: default avatarClaude <claude@elphel.com>
parent af0e34b9
Loading
Loading
Loading
Loading
+20 −10
Original line number Diff line number Diff line
@@ -11104,11 +11104,21 @@ java.lang.NullPointerException
    }
    /**
     * Undistort pixel coordinates in a pXpYD tile array in-place.
     * Converts distorted sensor coordinates to rectilinear (pinhole) coordinates
     * using the scene's radial distortion calibration (getRByRDist).
     * With Boson 640, the correction is &lt;1 px but eliminates the systematic
     * bowl effect in COLMAP reconstructions that use a PINHOLE camera model.
     * Convert a pXpYD tile array (in-place) so that rendering it produces a
     * RECTILINEAR (pinhole) output image.
     *
     * The tile coordinates are SAMPLING positions in the common (radially
     * distorted) virtual-camera space.  For output pixel u (the tile grid) to
     * show the content of the ideal pinhole ray through u, it must sample the
     * distorted image where that ray actually lands: rD = R * (Rdist/R), i.e.
     * apply the FORWARD distortion getRDistByR() - same direction as
     * GeometryCorrection.getImageCoordinates() (world -> distorted pixel).
     *
     * (The previous version used getRByRDist() - the inverse - which ADDED the
     * common radial distortion to the output instead of removing it: measured
     * edge/center translation-flow ratio 0.952 vs 0.965 of the non-undistorted
     * stack, and COLMAP self-calibrated k1=-0.38 on supposedly pinhole images.)
     *
     * @param pXpYD  tile array: each non-null element is {pX, pY, disparity}
     * @param gc     GeometryCorrection providing distortion model and pixel geometry
     */
@@ -11122,11 +11132,11 @@ java.lang.NullPointerException
    		if (tile == null) continue;
    		double pXc = tile[0] - cx;
    		double pYc = tile[1] - cy;
    		double rD_mm = Math.sqrt(pXc * pXc + pYc * pYc) * mmPerPix;
    		if (rD_mm > 0) {
    			double rND2R = gc.getRByRDist(rD_mm / distRad, false);
    			tile[0] = pXc * rND2R + cx;
    			tile[1] = pYc * rND2R + cy;
    		double rND_mm = Math.sqrt(pXc * pXc + pYc * pYc) * mmPerPix;
    		if (rND_mm > 0) {
    			double rD2RND = gc.getRDistByR(rND_mm / distRad);
    			tile[0] = pXc * rD2RND + cx;
    			tile[1] = pYc * rD2RND + cy;
    		}
    	}
    }