/** * Adjust bound to ensure the entire image is contained inside, otherwise there might be single * pixel wide black regions */ public static void roundInside(Rectangle2D_F32 bound) { float x0 = (float) Math.ceil(bound.tl_x); float y0 = (float) Math.ceil(bound.tl_y); float x1 = (float) Math.floor(bound.tl_x + bound.width); float y1 = (float) Math.floor(bound.tl_y + bound.height); bound.tl_x = x0; bound.tl_y = y0; bound.width = x1 - x0; bound.height = y1 - y0; }
/** * Adjusts the view such that each pixel has a correspondence to the original image while * maximizing the view area. In other words no black regions which can cause problems for some * image processing algorithms. * * <p>The original image coordinate system is maintained even if the intrinsic parameter flipY is * true. * * @param param Intrinsic camera parameters. * @param paramAdj If not null, the new camera parameters are stored here. * @return New transform that adjusts the view and removes lens distortion.. */ public static PointTransform_F32 allInside( IntrinsicParameters param, IntrinsicParameters paramAdj) { RemoveRadialPtoP_F32 removeDistort = new RemoveRadialPtoP_F32(); AddRadialPtoP_F32 addDistort = new AddRadialPtoP_F32(); removeDistort.set(param.fx, param.fy, param.skew, param.cx, param.cy, param.radial); addDistort.set(param.fx, param.fy, param.skew, param.cx, param.cy, param.radial); Rectangle2D_F32 bound = LensDistortionOps.boundBoxInside( param.width, param.height, new PointToPixelTransform_F32(removeDistort)); // ensure there are no strips of black LensDistortionOps.roundInside(bound); double scaleX = bound.width / param.width; double scaleY = bound.height / param.height; double scale = Math.min(scaleX, scaleY); // translation and shift over so that the small axis is in the middle double deltaX = bound.tl_x + (scaleX - scale) * param.width / 2.0; double deltaY = bound.tl_y + (scaleY - scale) * param.height / 2.0; // adjustment matrix DenseMatrix64F A = new DenseMatrix64F(3, 3, true, scale, 0, deltaX, 0, scale, deltaY, 0, 0, 1); PointTransform_F32 tranAdj = PerspectiveOps.adjustIntrinsic_F32(addDistort, false, param, A, paramAdj); if (param.flipY) { PointTransform_F32 flip = new FlipVertical_F32(param.height); return new SequencePointTransform_F32(flip, tranAdj, flip); } else return tranAdj; }
/** * Transforms the view such that the entire original image is visible after lens distortion has * been removed. The appropriate {@link PointTransform_F32} is returned and a new set of intrinsic * camera parameters for the "virtual" camera that is associated with the returned transformed. * * <p>The original image coordinate system is maintained even if the intrinsic parameter flipY is * true. * * @param param Intrinsic camera parameters. * @param paramAdj If not null, the new camera parameters are stored here. * @return New transform that adjusts the view and removes lens distortion.. */ public static PointTransform_F32 fullView( IntrinsicParameters param, IntrinsicParameters paramAdj) { RemoveRadialPtoP_F32 removeDistort = new RemoveRadialPtoP_F32(); AddRadialPtoP_F32 addDistort = new AddRadialPtoP_F32(); removeDistort.set(param.fx, param.fy, param.skew, param.cx, param.cy, param.radial); addDistort.set(param.fx, param.fy, param.skew, param.cx, param.cy, param.radial); Rectangle2D_F32 bound = DistortImageOps.boundBox_F32( param.width, param.height, new PointToPixelTransform_F32(removeDistort)); double scaleX = bound.width / param.width; double scaleY = bound.height / param.height; double scale = Math.max(scaleX, scaleY); // translation double deltaX = bound.tl_x; double deltaY = bound.tl_y; // adjustment matrix DenseMatrix64F A = new DenseMatrix64F(3, 3, true, scale, 0, deltaX, 0, scale, deltaY, 0, 0, 1); PointTransform_F32 tranAdj = PerspectiveOps.adjustIntrinsic_F32(addDistort, false, param, A, paramAdj); if (param.flipY) { PointTransform_F32 flip = new FlipVertical_F32(param.height); return new SequencePointTransform_F32(flip, tranAdj, flip); } else return tranAdj; }