Difference between revisions of "Example Key Point Based Deformation"

From BoofCV
Jump to navigationJump to search
(Created page with "<center> File:Example_point_based_deformation_man.mp4|border|600px|Waving man created using this example. Control points are moved around to create the appearance of waving....")
 
m
 
(4 intermediate revisions by the same user not shown)
Line 6: Line 6:


Example Code:
Example Code:
* [https://github.com/lessthanoptimal/BoofCV/blob/v0.28/examples/src/main/java/boofcv/examples/imageprocessing/ExamplePointDeformKeyPoints.java ExamplePointDeformKeyPoints.java]
* [https://github.com/lessthanoptimal/BoofCV/blob/v0.40/examples/src/main/java/boofcv/examples/imageprocessing/ExamplePointDeformKeyPoints.java ExamplePointDeformKeyPoints.java]


Concepts:
Concepts:
* Image Deformation
* Image Deformation
Relevant Applets:
* [[Applet Dense Optical Flow| Dense Optical Flow]]


= Example Code =
= Example Code =
Line 25: Line 22:
  */
  */
public class ExamplePointDeformKeyPoints {
public class ExamplePointDeformKeyPoints {
public static void main(String[] args) {
public static void main( String[] args ) {
BufferedImage orig = UtilImageIO.loadImage(UtilIO.pathExample("standard/man_mls.jpg"));
BufferedImage orig = UtilImageIO.loadImageNotNull(UtilIO.pathExample("standard/man_mls.jpg"));
BufferedImage bufferedOut = new BufferedImage(orig.getWidth(),orig.getHeight(),BufferedImage.TYPE_INT_RGB);
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> input = ConvertBufferedImage.convertFrom(orig, true, ImageType.pl(3, GrayF32.class));
Planar<GrayF32> output = input.createSameShape();
Planar<GrayF32> output = input.createSameShape();


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


src.add(new Point2D_F32(64, 241));
src.add(new Point2D_F32(64, 241));
Line 44: Line 41:
src.add(new Point2D_F32(473, 238));
src.add(new Point2D_F32(473, 238));


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


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




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


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


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


int count = 0;
int count = 0;
while( true ) {
while (true) {
// specify new locations of key points
// specify new locations of key points
double theta = count++*Math.PI/30;
double theta = count++*Math.PI/30;
Line 75: Line 72:
deform.setDestination(dst);
deform.setDestination(dst);
// Tell the distorter that the model has changed. If cached is set to false you can ignore this step
// 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));
distorter.setModel(new PointToPixelTransform_F32(deform));
// distort the image
// distort the image
distorter.apply(input, output);
distorter.apply(input, output);
Line 84: Line 81:
BoofMiscOps.sleep(30);
BoofMiscOps.sleep(30);
}
}
}
}
}
}
</syntaxhighlight>
</syntaxhighlight>

Latest revision as of 16:09, 17 January 2022

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);
		}
	}
}