Example Key Point Based Deformation

From BoofCV
Jump to navigationJump to search

This example shows you key points can be used to deform an image. Here it is used to make it appear as if a wooden man is waving.

Example Code:

Concepts:

  • Image Deformation

Example Code

/**
 * Demonstration on how to use a key point based image deformation. A static image will be modified in real time
 * to make it appear as if the 'man' is waving. These deformation algorithms specify keypoints which match between
 * two images. When the pixel coordinate is moved the pixels are distorted such that they minimize an error function.
 *
 * @author Peter Abeles
 */
public class ExamplePointDeformKeyPoints {
	public static void main( String[] args ) {
		BufferedImage orig = UtilImageIO.loadImageNotNull(UtilIO.pathExample("standard/man_mls.jpg"));
		var bufferedOut = new BufferedImage(orig.getWidth(), orig.getHeight(), BufferedImage.TYPE_INT_RGB);

		Planar<GrayF32> input = ConvertBufferedImage.convertFrom(orig, true, ImageType.pl(3, GrayF32.class));
		Planar<GrayF32> output = input.createSameShape();

		var src = new ArrayList<Point2D_F32>();
		var dst = new ArrayList<Point2D_F32>();

		src.add(new Point2D_F32(64, 241));
		src.add(new Point2D_F32(266, 119));
		src.add(new Point2D_F32(265, 240));
		src.add(new Point2D_F32(208, 410));
		src.add(new Point2D_F32(181, 536));
		src.add(new Point2D_F32(335, 409));
		src.add(new Point2D_F32(375, 531));
		src.add(new Point2D_F32(473, 238));

		for (Point2D_F32 p : src) {
			dst.add(p.copy());
		}

		var config = new ConfigDeformPointMLS();
		PointDeformKeyPoints deform = FactoryDistort.deformMls(config);
		deform.setImageShape(input.width, input.height);


		ImageDistort<Planar<GrayF32>, Planar<GrayF32>> distorter =
				FactoryDistort.distort(true, InterpolationType.BILINEAR,
						BorderType.ZERO, input.getImageType(), input.getImageType());

		deform.setImageShape(input.width, input.height);
		deform.setSource(src);
		deform.setDestination(dst);

		ConvertBufferedImage.convertTo(output, bufferedOut, true);
		ImagePanel panel = ShowImages.showWindow(bufferedOut, "Point Based Distortion Animation", true);

		int count = 0;
		while (true) {
			// specify new locations of key points
			double theta = count++*Math.PI/30;
			dst.get(7).y = (float)(238 + Math.sin(theta)*30);       // right arm
			dst.get(0).y = (float)(241 - Math.sin(theta*2.0)*20);   // left arm
			dst.get(1).x = (float)(266 + Math.sin(theta*0.25)*10);  // head

			// tell the deformation algorithm that destination points have changed
			deform.setDestination(dst);
			// Tell the distorter that the model has changed. If cached is set to false you can ignore this step
			distorter.setModel(new PointToPixelTransform_F32(deform));
			// distort the image
			distorter.apply(input, output);
			// Show the results
			ConvertBufferedImage.convertTo(output, bufferedOut, true);
			panel.repaint();

			BoofMiscOps.sleep(30);
		}
	}
}