@Override public void setCalibration (CameraPinholeRadial param ) { CameraPinhole undistorted = new CameraPinhole(param); this.undoRadial = LensDistortionOps.changeCameraModel( AdjustmentType.FULL_VIEW, BorderType.ZERO, param, undistorted,null, ImageType.single(GrayF32.class)); this.remove_p_to_p = LensDistortionOps_F32.transformChangeModel(AdjustmentType.FULL_VIEW, param, undistorted, false,null); undoRadialDistortion(distorted); }
public void setDistorted (CameraPinholeRadial param , DenseMatrix64F rect ) { if( rect == null ) { this.undoRadial = LensDistortionOps.imageRemoveDistortion( AdjustmentType.FULL_VIEW, BorderType.ZERO, param, null, ImageType.single(GrayF32.class)); this.remove_p_to_p = LensDistortionOps.transform_F32(AdjustmentType.FULL_VIEW, param, null, false); } else { this.undoRadial = RectifyImageOps.rectifyImage(param, rect, BorderType.ZERO, ImageType.single(GrayF32.class)); this.remove_p_to_p = RectifyImageOps.transformPixelToRect_F32(param, rect); } }
boolean undistortedToDistorted) Point2Transform2_F32 remove_p_to_p = transformPoint(param).undistort_F32(true, true); new PointToPixelTransform_F32(remove_p_to_p)); } else if( type == AdjustmentType.EXPAND) { bound = LensDistortionOps.boundBoxInside(param.width, param.height, new PointToPixelTransform_F32(remove_p_to_p)); LensDistortionOps.roundInside(bound); } else { throw new IllegalArgumentException("Unsupported type "+type); return adjustmentTransform_F32(param, paramAdj, undistortedToDistorted, remove_p_to_p, A);
boolean undistortedToDistorted) Point2Transform2_F64 remove_p_to_p = transformPoint(param).undistort_F64(true, true); new PointToPixelTransform_F64(remove_p_to_p)); } else if( type == AdjustmentType.EXPAND) { bound = LensDistortionOps.boundBoxInside(param.width, param.height, new PointToPixelTransform_F64(remove_p_to_p)); LensDistortionOps.roundInside(bound); } else { throw new IllegalArgumentException("If you don't want to adjust the view just call transformPoint()"); return adjustmentTransform_F64(param, paramAdj, undistortedToDistorted, remove_p_to_p, A);
case EXPAND: case FULL_VIEW: undistToDist = transform_F32(type, param, paramAdj, true); break; undistToDist = transformPoint(param).distort_F32(true, true); break;
/** * <p> * Creates a transform that applies rectification to unrectified distorted pixels. * </p> * * @param param Intrinsic parameters. Not modified. * @param rectify Transform for rectifying the image. Not modified. * @return Transform from unrectified to rectified pixels */ public static Point2Transform2_F32 transformPixelToRect_F32(CameraPinholeRadial param, DenseMatrix64F rectify) { Point2Transform2_F32 remove_p_to_p = transformPoint(param).undistort_F32(true, true); PointTransformHomography_F32 rectifyPixel = new PointTransformHomography_F32(rectify); return new SequencePoint2Transform2_F32(remove_p_to_p,rectifyPixel); }
/** * <p> * Adjust the rectification such that only pixels which overlap the original left image can be seen. For use with * calibrated stereo images having a known baseline. Image processing is easier since only the "true" image pixels * are visible, but information along the image border has been discarded. The rectification matrices are * overwritten with adjusted values on output. * </p> * * @param paramLeft Intrinsic parameters for left camera. Not modified. * @param rectifyLeft Rectification matrix for left image. Input and Output. Modified. * @param rectifyRight Rectification matrix for right image. Input and Output. Modified. * @param rectifyK Rectification calibration matrix. Input and Output. Modified. */ public static void allInsideLeft(CameraPinholeRadial paramLeft, DenseMatrix64F rectifyLeft, DenseMatrix64F rectifyRight, DenseMatrix64F rectifyK) { // need to take in account the order in which image distort will remove rectification later on paramLeft = new CameraPinholeRadial(paramLeft); Point2Transform2_F32 tranLeft = transformPixelToRect_F32(paramLeft, rectifyLeft); RectangleLength2D_F32 bound = LensDistortionOps.boundBoxInside(paramLeft.width, paramLeft.height, new PointToPixelTransform_F32(tranLeft)); LensDistortionOps.roundInside(bound); double scaleX = paramLeft.width/(double)bound.width; double scaleY = paramLeft.height/(double)bound.height; double scale = Math.max(scaleX, scaleY); adjustCalibrated(rectifyLeft, rectifyRight, rectifyK, bound, scale); }
@Override public void initialize(int imageWidth, int imageHeight, int sensorOrientation) { paintBorder.setColor(Color.BLACK); paintBorder.setStyle(Paint.Style.STROKE); paintBorder.setStrokeWidth(3*cameraToDisplayDensity); paintInside.setColor(Color.RED); paintInside.setStyle(Paint.Style.STROKE); paintInside.setStrokeWidth(2*cameraToDisplayDensity); double fov[] = cameraNominalFov(); CameraPinholeRadial intrinsic = MiscUtil.checkThenInventIntrinsic(app,imageWidth,imageHeight,fov[0],fov[1]); LensDistortionNarrowFOV distort = LensDistortionOps.narrow(intrinsic); detector.configure(distort, intrinsic.width, intrinsic.height, true); numDetected = 0; }
/** * <p> * Adjust the rectification such that only pixels which overlap the original left image can be seen. For use with * uncalibrated images with unknown baselines. Image processing is easier since only the "true" image pixels * are visible, but information along the image border has been discarded. The rectification matrices are * overwritten with adjusted values on output. * </p> * * @param imageWidth Width of left image. * @param imageHeight Height of left image. * @param rectifyLeft Rectification matrix for left image. Input and Output. Modified. * @param rectifyRight Rectification matrix for right image. Input and Output. Modified. */ public static void allInsideLeft( int imageWidth,int imageHeight, DenseMatrix64F rectifyLeft, DenseMatrix64F rectifyRight ) { Point2Transform2_F32 tranLeft = new PointTransformHomography_F32(rectifyLeft); RectangleLength2D_F32 bound = LensDistortionOps.boundBoxInside(imageWidth, imageHeight, new PointToPixelTransform_F32(tranLeft)); double scaleX = imageWidth/(double)bound.width; double scaleY = imageHeight/(double)bound.height; double scale = Math.max(scaleX, scaleY); adjustUncalibrated(rectifyLeft, rectifyRight, bound, scale); }
@Override public void initialize(int imageWidth, int imageHeight, int sensorOrientation) { undistorted = imageType.createImage(imageWidth,imageHeight); CameraPinholeRadial intrinsic = app.preference.lookup( imageWidth,imageHeight); if( intrinsic != null ) { // define the transform. Cache the results for quick rendering later on CameraPinhole desired = new CameraPinhole(); desired.set(intrinsic); Point2Transform2_F32 fullView = LensDistortionOps.transformChangeModel_F32(AdjustmentType.FULL_VIEW, intrinsic,desired,false,null); InterpolatePixelS<GrayU8> interp = FactoryInterpolation. bilinearPixelS(GrayU8.class, BorderType.ZERO); // for some reason not caching is faster on a low end phone. Maybe it has to do with CPU memory // cache misses when looking up a point? removeDistortion = FactoryDistort.distort(false,interp,imageType); removeDistortion.setModel(new PointToPixelTransform_F32(fullView)); } }
/** * <p> * Convenient function for converting from normalized image coordinates to the original image pixel coordinate. * If speed is a concern then {@link PinholeNtoP_F32} should be used instead. * </p> * * @param param Intrinsic camera parameters * @param x X-coordinate of normalized. * @param y Y-coordinate of normalized. * @param pixel Optional storage for output. If null a new instance will be declared. * @return pixel image coordinate */ public static Point2D_F32 convertNormToPixel(CameraPinholeRadial param , float x , float y , Point2D_F32 pixel ) { if( pixel == null ) pixel = new Point2D_F32(); Point2Transform2_F32 normToPixel = LensDistortionOps.transformPoint(param).distort_F32(false, true); normToPixel.compute(x,y,pixel); return pixel; }
@Override public void initialize(int imageWidth, int imageHeight, int sensorOrientation) { // sanity check requirements if( imageWidth == 0 || imageHeight == 0 ) throw new RuntimeException("BUG! Called with zero width and height"); if( lookupIntrinsics() == null ) { Toast.makeText(FiducialSquareActivity.this, "Calibrate camera for better results!", Toast.LENGTH_LONG).show(); } // the adjustment requires knowing what the camera's resolution is. The camera // must be initialized at this point paintTextVideo.setTextSize(30*cameraToDisplayDensity); paintTextBorder.setTextSize(30*cameraToDisplayDensity); paintTextBorder.setStrokeWidth(3*cameraToDisplayDensity); paintLine0.setStrokeWidth(4f*cameraToDisplayDensity); paintLine1.setStrokeWidth(4f*cameraToDisplayDensity); paintLine2.setStrokeWidth(4f*cameraToDisplayDensity); paintLine3.setStrokeWidth(4f*cameraToDisplayDensity); double fov[] = cameraNominalFov(); intrinsic = MiscUtil.checkThenInventIntrinsic(app,imageWidth,imageHeight,fov[0],fov[1]); detector.setLensDistortion(LensDistortionOps.narrow(intrinsic),imageWidth,imageHeight); }
ImageDistort<GrayF32, GrayF32> undistorter = LensDistortionOps.changeCameraModel( AdjustmentType.EXPAND, BorderType.EXTENDED, intrinsic, new CameraPinhole(intrinsic), paramUndist, ImageType.single(GrayF32.class));
/** * <p> * Creates a transform that applies rectification to unrectified distorted pixels. * </p> * * @param param Intrinsic parameters. Not modified. * @param rectify Transform for rectifying the image. Not modified. * @return Transform from distorted pixel to rectified pixels */ public static Point2Transform2_F64 transformPixelToRect_F64(CameraPinholeRadial param, DenseMatrix64F rectify) { Point2Transform2_F64 remove_p_to_p = transformPoint(param).undistort_F64(true, true); PointTransformHomography_F64 rectifyDistort = new PointTransformHomography_F64(rectify); return new SequencePoint2Transform2_F64(remove_p_to_p,rectifyDistort); }
/** * Convert a set of associated point features from pixel coordinates into normalized image coordinates. */ public List<AssociatedPair> convertToNormalizedCoordinates() { Point2Transform2_F64 tran = LensDistortionOps.narrow(intrinsic).undistort_F64(true,false); List<AssociatedPair> calibratedFeatures = new ArrayList<>(); FastQueue<AssociatedIndex> matches = associate.getMatches(); for( AssociatedIndex a : matches.toList() ) { Point2D_F64 p1 = locationSrc.get( a.src ); Point2D_F64 p2 = locationDst.get( a.dst ); AssociatedPair c = new AssociatedPair(); tran.compute(p1.x, p1.y, c.p1); tran.compute(p2.x, p2.y, c.p2); calibratedFeatures.add(c); } return calibratedFeatures; }
ImageDistort<GrayF32, GrayF32> undistorter = LensDistortionOps.changeCameraModel( AdjustmentType.EXPAND, BorderType.EXTENDED, intrinsic, new CameraPinhole(intrinsic), paramUndist, ImageType.single(GrayF32.class));
/** * <p> * Convenient function for converting from normalized image coordinates to the original image pixel coordinate. * If speed is a concern then {@link PinholeNtoP_F64} should be used instead. * </p> * * @param param Intrinsic camera parameters * @param x X-coordinate of normalized. * @param y Y-coordinate of normalized. * @param pixel Optional storage for output. If null a new instance will be declared. * @return pixel image coordinate */ public static Point2D_F64 convertNormToPixel(CameraPinholeRadial param , double x , double y , Point2D_F64 pixel ) { if( pixel == null ) pixel = new Point2D_F64(); Point2Transform2_F64 normToPixel = LensDistortionOps.transformPoint(param).distort_F64(false,true); normToPixel.compute(x,y,pixel); return pixel; }
/** * <p> * Convenient function for converting from original image pixel coordinate to normalized< image coordinates. * If speed is a concern then {@link PinholePtoN_F64} should be used instead. * </p> * * NOTE: norm and pixel can be the same instance. * * @param param Intrinsic camera parameters * @param pixel Pixel coordinate * @param norm Optional storage for output. If null a new instance will be declared. * @return normalized image coordinate */ public static Point2D_F64 convertPixelToNorm(CameraPinholeRadial param , Point2D_F64 pixel , Point2D_F64 norm ) { if( norm == null ) norm = new Point2D_F64(); Point2Transform2_F64 pixelToNorm = LensDistortionOps.transformPoint(param).distort_F64(true, false); pixelToNorm.compute(pixel.x,pixel.y,norm); return norm; }
/** * <p> * Convenient function for converting from original image pixel coordinate to normalized< image coordinates. * If speed is a concern then {@link PinholePtoN_F32} should be used instead. * </p> * * NOTE: norm and pixel can be the same instance. * * @param param Intrinsic camera parameters * @param pixel Pixel coordinate * @param norm Optional storage for output. If null a new instance will be declared. * @return normalized image coordinate */ public static Point2D_F32 convertPixelToNorm(CameraPinholeRadial param , Point2D_F32 pixel , Point2D_F32 norm ) { if( norm == null ) norm = new Point2D_F32(); Point2Transform2_F32 pixelToNorm = LensDistortionOps.transformPoint(param).distort_F32(true, false); pixelToNorm.compute(pixel.x,pixel.y,norm); return norm; }
/** * <p> * Creates a transform that goes from rectified to original distorted pixel coordinates. * Rectification includes removal of lens distortion. Used for rendering rectified images. * </p> * * @param param Intrinsic parameters. * @param rectify Transform for rectifying the image. * @return Transform from rectified to unrectified pixels */ public static Point2Transform2_F64 transformRectToPixel_F64(CameraPinholeRadial param, DenseMatrix64F rectify) { Point2Transform2_F64 add_p_to_p = transformPoint(param).distort_F64(true, true); DenseMatrix64F rectifyInv = new DenseMatrix64F(3,3); CommonOps.invert(rectify,rectifyInv); PointTransformHomography_F64 removeRect = new PointTransformHomography_F64(rectifyInv); return new SequencePoint2Transform2_F64(removeRect,add_p_to_p); }