public static <O extends CameraPinhole, D extends CameraPinhole>
	Point2Transform2_F64 transformChangeModel(AdjustmentType type,
											  O paramOriginal,
											  D paramDesired,
											  boolean desiredToOriginal,
											  D paramMod)
	{
		LensDistortionNarrowFOV original = LensDistortionFactory.narrow(paramOriginal);
		LensDistortionNarrowFOV desired = LensDistortionFactory.narrow(paramDesired);

		Point2Transform2_F64 ori_p_to_n = original.undistort_F64(true, false);
		Point2Transform2_F64 des_n_to_p = desired.distort_F64(false, true);

		Point2Transform2_F64 ori_to_des = new SequencePoint2Transform2_F64(ori_p_to_n,des_n_to_p);

		Point2D_F64 work = new Point2D_F64();
		RectangleLength2D_F64 bound;
		if( type == AdjustmentType.FULL_VIEW ) {
			bound = DistortImageOps.boundBox_F64(paramOriginal.width, paramOriginal.height,
					new PointToPixelTransform_F64(ori_to_des),work);
		} else if( type == AdjustmentType.EXPAND) {
			bound = LensDistortionOps_F64.boundBoxInside(paramOriginal.width, paramOriginal.height,
					new PointToPixelTransform_F64(ori_to_des),work);
			// ensure there are no strips of black
			LensDistortionOps_F64.roundInside(bound);
		} else if( type == AdjustmentType.CENTER) {
			bound = LensDistortionOps_F64.centerBoxInside(paramOriginal.width, paramOriginal.height,
					new PointToPixelTransform_F64(ori_to_des),work);
		} else if( type == AdjustmentType.NONE ) {
			bound = new RectangleLength2D_F64(0,0,paramDesired.width, paramDesired.height);
		} else {
			throw new IllegalArgumentException("Unsupported type "+type);
		}

		double scaleX = bound.width/paramDesired.width;
		double scaleY = bound.height/paramDesired.height;

		double scale;

		if( type == AdjustmentType.FULL_VIEW ) {
			scale = Math.max(scaleX, scaleY);
		} else if( type == AdjustmentType.EXPAND) {
			scale = Math.min(scaleX, scaleY);
		} else if( type == AdjustmentType.CENTER) {
			scale = Math.max(scaleX, scaleY);
		} else {
			scale = 1.0;
		}

		double deltaX = (bound.x0 + (scaleX-scale)*paramDesired.width/ 2.0 );
		double deltaY = (bound.y0 + (scaleY-scale)*paramDesired.height/ 2.0 );

		// adjustment matrix
		DMatrixRMaj A = new DMatrixRMaj(3,3,true,scale,0,deltaX,0,scale,deltaY,0,0,1);
		DMatrixRMaj A_inv = new DMatrixRMaj(3, 3);
		if (!CommonOps_DDRM.invert(A, A_inv)) {
			throw new RuntimeException("Failed to invert adjustment matrix.  Probably bad.");
		}

		if( paramMod != null ) {
			PerspectiveOps.adjustIntrinsic(paramDesired, A_inv, paramMod);
		}

		if( desiredToOriginal ) {
			Point2Transform2_F64 des_p_to_n = desired.undistort_F64(true, false);
			Point2Transform2_F64 ori_n_to_p = original.distort_F64(false, true);
			PointTransformHomography_F64 adjust = new PointTransformHomography_F64(A);
			return new SequencePoint2Transform2_F64(adjust,des_p_to_n,ori_n_to_p);
		} else {
			PointTransformHomography_F64 adjust = new PointTransformHomography_F64(A_inv);
			return new SequencePoint2Transform2_F64(ori_to_des, adjust);
		}
	}
public static < O extends CameraPinhole , D extends CameraPinhole > Point2Transform2_F64 transformChangeModel ( AdjustmentType type , O paramOriginal , D paramDesired , boolean desiredToOriginal , D paramMod ) { LensDistortionNarrowFOV original = LensDistortionFactory . narrow ( paramOriginal ) ; LensDistortionNarrowFOV desired = LensDistortionFactory . narrow ( paramDesired ) ; Point2Transform2_F64 ori_p_to_n = original . undistort_F64 ( true , false ) ; Point2Transform2_F64 des_n_to_p = desired . distort_F64 ( false , true ) ; Point2Transform2_F64 ori_to_des = new SequencePoint2Transform2_F64 ( ori_p_to_n , des_n_to_p ) ; Point2D_F64 work = new Point2D_F64 ( ) ; RectangleLength2D_F64 bound ; if ( type == AdjustmentType . FULL_VIEW ) { bound = DistortImageOps . boundBox_F64 ( paramOriginal . width , paramOriginal . height , new PointToPixelTransform_F64 ( ori_to_des ) , work ) ; } else if ( type == AdjustmentType . EXPAND ) { bound = LensDistortionOps_F64 . boundBoxInside ( paramOriginal . width , paramOriginal . height , new PointToPixelTransform_F64 ( ori_to_des ) , work ) ; LensDistortionOps_F64 . roundInside ( bound ) ; } else if ( type == AdjustmentType . CENTER ) { bound = LensDistortionOps_F64 . centerBoxInside ( paramOriginal . width , paramOriginal . height , new PointToPixelTransform_F64 ( ori_to_des ) , work ) ; } else if ( type == AdjustmentType . NONE ) { bound = new RectangleLength2D_F64 ( 0 , 0 , paramDesired . width , paramDesired . height ) ; } else { throw new IllegalArgumentException ( "Unsupported type " + type ) ; } double scaleX = bound . width / paramDesired . width ; double scaleY = bound . height / paramDesired . height ; double scale ; if ( type == AdjustmentType . FULL_VIEW ) { scale = Math . max ( scaleX , scaleY ) ; } else if ( type == AdjustmentType . EXPAND ) { scale = Math . min ( scaleX , scaleY ) ; } else if ( type == AdjustmentType . CENTER ) { scale = Math . max ( scaleX , scaleY ) ; } else { scale = 1.0 ; } double deltaX = ( bound . x0 + ( scaleX - scale ) * paramDesired . width / 2.0 ) ; double deltaY = ( bound . y0 + ( scaleY - scale ) * paramDesired . height / 2.0 ) ; DMatrixRMaj A = new DMatrixRMaj ( 3 , 3 , true , scale , 0 , deltaX , 0 , scale , deltaY , 0 , 0 , 1 ) ; DMatrixRMaj A_inv = new DMatrixRMaj ( 3 , 3 ) ; if ( ! CommonOps_DDRM . invert ( A , A_inv ) ) { throw new RuntimeException ( "Failed to invert adjustment matrix.  Probably bad." ) ; } if ( paramMod != null ) { PerspectiveOps . adjustIntrinsic ( paramDesired , A_inv , paramMod ) ; } if ( desiredToOriginal ) { Point2Transform2_F64 des_p_to_n = desired . undistort_F64 ( true , false ) ; Point2Transform2_F64 ori_n_to_p = original . distort_F64 ( false , true ) ; PointTransformHomography_F64 adjust = new PointTransformHomography_F64 ( A ) ; return new SequencePoint2Transform2_F64 ( adjust , des_p_to_n , ori_n_to_p ) ; } else { PointTransformHomography_F64 adjust = new PointTransformHomography_F64 ( A_inv ) ; return new SequencePoint2Transform2_F64 ( ori_to_des , adjust ) ; } }
Creates a {@link Point2Transform2_F32} for converting pixels from original camera model into a new synthetic
model.  The scaling of the image can be adjusted to ensure certain visibility requirements.

@param type The type of adjustment it will apply to the transform
@param paramOriginal Camera model for the current image
@param paramDesired Desired camera model for the distorted image
@param desiredToOriginal If true then the transform's input is assumed to be pixels in the desired
image and the output will be in original image, if false then the reverse transform
is returned.
@param paramMod The modified camera model to meet the requested visibility requirements.  Null if you don't want it.
@return The requested transform