/** * Clipps and scales the input iamge as neccisary * @param input Input image. Typically larger than output * @param output Output image */ public void massage( T input , T output ) { if( clip ) { T inputAdjusted = clipInput(input, output); // configure a simple change in scale for both axises transform.a11 = input.width / (float) output.width; transform.a22 = input.height / (float) output.height; // this change is automatically reflected in the distortion class. It is configured to cache nothing distort.apply(inputAdjusted, output); } else { // scale each axis independently. It will have the whole image but it will be distorted transform.a11 = input.width / (float) output.width; transform.a22 = input.height / (float) output.height; distort.apply(input, output); } }
@Override public void setModel(PixelTransform2_F32 dstToSrc) { layerDistort.setModel(dstToSrc); }
/** * Creates an {@link ImageDistort} for rectifying an image given its radial distortion and * rectification matrix. * * @param param Intrinsic parameters. * @param rectify Transform for rectifying the image. * @param imageType Type of single band image the transform is to be applied to. * @return ImageDistort for rectifying the image. */ public static <T extends ImageBase> ImageDistort<T,T> rectifyImage(CameraPinholeRadial param, DenseMatrix64F rectify , BorderType borderType, ImageType<T> imageType) { boolean skip = borderType == BorderType.SKIP; if( skip ) { borderType = BorderType.EXTENDED; } InterpolatePixel<T> interp = FactoryInterpolation.createPixel(0,255, InterpolationType.BILINEAR,borderType,imageType); // only compute the transform once ImageDistort<T,T> ret = FactoryDistort.distort(true, interp, imageType); ret.setRenderAll(!skip); Point2Transform2_F32 transform = transformRectToPixel_F32(param, rectify); ret.setModel(new PointToPixelTransform_F32(transform)); return ret; }
/** * Applies a pixel transform to a single band image. More flexible but order to use function. * * @deprecated As of v0.19. Use {@link FDistort} instead * * @param input Input (source) image. * @param output Where the result of transforming the image image is written to. * @param renderAll true it renders all pixels, even ones outside the input image. * @param transform The transform that is being applied to the image * @param interp Interpolation algorithm. */ public static <Input extends ImageGray<Input>,Output extends ImageGray<Output>> void distortSingle(Input input, Output output, boolean renderAll, PixelTransform2_F32 transform, InterpolatePixelS<Input> interp) { Class<Output> inputType = (Class<Output>)input.getClass(); ImageDistort<Input,Output> distorter = FactoryDistort.distortSB(false, interp, inputType); distorter.setRenderAll(renderAll); distorter.setModel(transform); distorter.apply(input,output); }
/** * Provides recent images from all the cameras (should be time and lighting synchronized) and renders them * into an equirectangular image. The images must be in the same order that the cameras were added. * * @param cameraImages List of camera images */ public void render( List<T> cameraImages ) { if( cameraImages.size() != cameras.size()) throw new IllegalArgumentException("Input camera image count doesn't equal the expected number"); // avoid divide by zero errors by initializing it to a small non-zero value GImageMiscOps.fill(weightImage,1e-4); GImageMiscOps.fill(averageImage,0); for (int i = 0; i < cameras.size(); i++) { Camera c = cameras.get(i); T cameraImage = cameraImages.get(i); distort.setModel(c.equiToCamera); distort.apply(cameraImage,cameraRendered); /// sum up the total weight for each pixel PixelMath.add(weightImage,c.mask,weightImage); // apply the weight for this image to the rendered image GPixelMath.multiply(c.mask,cameraRendered,workImage); // add the result to the average image GPixelMath.add(workImage, averageImage, averageImage); } // comput the final output by dividing GPixelMath.divide(averageImage,weightImage,averageImage); }
@Override public void setRenderAll(boolean renderAll) { layerDistort.setRenderAll(renderAll); }
@Override public PixelTransform2_F32 getModel() { return layerDistort.getModel(); } }
@Override public boolean getRenderAll() { return layerDistort.getRenderAll(); }
/** * Provides recent images from all the cameras (should be time and lighting synchronized) and renders them * into an equirectangular image. The images must be in the same order that the cameras were added. * * @param cameraImages List of camera images */ public void render( List<T> cameraImages ) { if( cameraImages.size() != cameras.size()) throw new IllegalArgumentException("Input camera image count doesn't equal the expected number"); // avoid divide by zero errors by initializing it to a small non-zero value GImageMiscOps.fill(weightImage,1e-4); GImageMiscOps.fill(averageImage,0); for (int i = 0; i < cameras.size(); i++) { Camera c = cameras.get(i); T cameraImage = cameraImages.get(i); distort.setModel(c.equiToCamera); distort.apply(cameraImage,cameraRendered); /// sum up the total weight for each pixel PixelMath.add(weightImage,c.mask,weightImage); // apply the weight for this image to the rendered image GPixelMath.multiply(c.mask,cameraRendered,workImage); // add the result to the average image GPixelMath.add(workImage, averageImage, averageImage); } // comput the final output by dividing GPixelMath.divide(averageImage,weightImage,averageImage); }
/** * Applies a pixel transform to a single band image. Easier to use function. * * @deprecated As of v0.19. Use {@link FDistort} instead * * @param input Input (source) image. * @param output Where the result of transforming the image image is written to. * @param transform The transform that is being applied to the image * @param interpType Which type of pixel interpolation should be used. BILINEAR is in general recommended * @param borderType Specifies how to handle image borders. */ public static <Input extends ImageGray<Input>,Output extends ImageGray<Output>> void distortSingle(Input input, Output output, PixelTransform2_F32 transform, InterpolationType interpType, BorderType borderType) { boolean skip = borderType == BorderType.SKIP; if( skip ) borderType = BorderType.EXTENDED; Class<Input> inputType = (Class<Input>)input.getClass(); Class<Output> outputType = (Class<Output>)input.getClass(); InterpolatePixelS<Input> interp = FactoryInterpolation.createPixelS(0, 255, interpType, borderType, inputType); ImageDistort<Input,Output> distorter = FactoryDistort.distortSB(false, interp, outputType); distorter.setRenderAll(!skip); distorter.setModel(transform); distorter.apply(input,output); }
FactoryInterpolation.createPixel(0, 255, InterpolationType.BILINEAR,borderType, imageType); distortImage = FactoryDistort.distort(true, interp, imageType); distortImage.setRenderAll(true);
@Override public void process(ImageBase input) { if( removeDistortion == null ) return; removeDistortion.apply(input,undistorted); ConvertBitmap.boofToBitmap(undistorted, bitmap, bitmapTmp); } }
@Override public void processImage(int sourceID, long frameID, BufferedImage buffered, ImageBase input) { synchronized (imageLock) { // create a copy of the input image for output purposes if (buffEqui.getWidth() != buffered.getWidth() || buffEqui.getHeight() != buffered.getHeight()) { buffEqui = new BufferedImage(buffered.getWidth(), buffered.getHeight(), BufferedImage.TYPE_INT_BGR); panelEqui.setPreferredSize(new Dimension(buffered.getWidth(), buffered.getHeight())); panelEqui.setImageUI(buffEqui); distorter.setEquirectangularShape(input.width, input.height); distortImage.setModel(distorter); } buffEqui.createGraphics().drawImage(buffered, 0, 0, null); equi.setTo((T)input); rerenderPinhole(); } }
private void addUndistorted(final String name, final Point2Transform2_F32 model) { // Set up image distort InterpolatePixel<T> interp = FactoryInterpolation. createPixel(0,255,InterpolationType.BILINEAR, BorderType.ZERO, undist.getImageType()); ImageDistort<T,T> undistorter = FactoryDistort.distort(false, interp, undist.getImageType()); undistorter.setModel(new PointToPixelTransform_F32(model)); undistorter.apply(dist,undist); final BufferedImage out = ConvertBufferedImage.convertTo(undist,null,true); // Add this rectified image SwingUtilities.invokeLater(new Runnable() { public void run() { gui.addItem(new ImagePanel(out), name); }}); }
/** * Creates an {@link ImageDistort} for rectifying an image given its radial distortion and * rectification matrix. * * @param param Intrinsic parameters. * @param rectify Transform for rectifying the image. * @param imageType Type of single band image the transform is to be applied to. * @return ImageDistort for rectifying the image. */ public static <T extends ImageBase<T>> ImageDistort<T,T> rectifyImage(CameraPinholeRadial param, FMatrixRMaj rectify , BorderType borderType, ImageType<T> imageType) { boolean skip = borderType == BorderType.SKIP; if( skip ) { borderType = BorderType.EXTENDED; } InterpolatePixel<T> interp = FactoryInterpolation.createPixel(0,255, InterpolationType.BILINEAR,borderType,imageType); // only compute the transform once ImageDistort<T,T> ret = FactoryDistort.distort(true, interp, imageType); ret.setRenderAll(!skip); Point2Transform2_F32 transform = transformRectToPixel(param, rectify); ret.setModel(new PointToPixelTransform_F32(transform)); return ret; }
FactoryInterpolation.createPixel(0, 255, InterpolationType.BILINEAR,borderType, imageType); distortImage = FactoryDistort.distort(true, interp, imageType); distortImage.setRenderAll(true);
private void renderCameraModel() { undistorter.apply(dist,undist); if( out != null && (out.getWidth() != undist.width || out.getHeight() != undist.height )) { out = new BufferedImage(undist.width, undist.height, out.getType()); } out = ConvertBufferedImage.convertTo(undist,out,true); gui.setImageUI(out); }
@Override public void processImage(int sourceID, long frameID, BufferedImage buffered, ImageBase input) { synchronized (imageLock) { // create a copy of the input image for output purposes if (buffFisheye.getWidth() != buffered.getWidth() || buffFisheye.getHeight() != buffered.getHeight()) { buffFisheye = new BufferedImage(buffered.getWidth(), buffered.getHeight(), BufferedImage.TYPE_INT_BGR); panelFisheye.setPreferredSize(new Dimension(buffered.getWidth(),buffered.getHeight())); panelFisheye.setImageUI(buffFisheye); distortImage.setModel(new PointToPixelTransform_F32(distorter)); } buffFisheye.createGraphics().drawImage(buffered, 0, 0, null); fisheye.setTo((T)input); rerenderPinhole(); } }
/** * Applies the distortion. */ public void apply() { // see if the distortion class needs to be created again if( distorter == null ) { Class typeOut = output.getImageType().getImageClass(); switch( input.getImageType().getFamily() ) { case GRAY: distorter = FactoryDistort.distortSB(cached, (InterpolatePixelS)interp, typeOut); break; case PLANAR: distorter = FactoryDistort.distortPL(cached, (InterpolatePixelS)interp, typeOut); break; case INTERLEAVED: distorter = FactoryDistort.distortIL(cached, (InterpolatePixelMB) interp, output.getImageType()); break; default: throw new IllegalArgumentException("Unsupported image type"); } } distorter.setModel(outputToInput); distorter.apply(input,output); } }
distort.setModel(new PointToPixelTransform_F32(undistToDist)); distort.setRenderAll(!skip );