Difference between revisions of "Example Convolution"

From BoofCV
Jump to navigationJump to search
m
m
 
(7 intermediate revisions by the same user not shown)
Line 2: Line 2:


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


Concepts:
Concepts:
* Convolution
* Convolution
* Spacial filtering
* Spacial filtering
Relevant Examples:
* [[Example_Image_Blur|Image Blur]]


= Example Code =
= Example Code =
Line 18: Line 21:
public class ExampleConvolution {
public class ExampleConvolution {


public static void main(String[] args) {
private static final ListDisplayPanel panel = new ListDisplayPanel();
BufferedImage image = UtilImageIO.loadImage(UtilIO.pathExample("sunflowers.jpg"));


ImageUInt8 gray = ConvertBufferedImage.convertFromSingle(image, null, ImageUInt8.class);
public static void main( String[] args ) {
BufferedImage image = UtilImageIO.loadImageNotNull(UtilIO.pathExample("sunflowers.jpg"));
 
GrayU8 gray = ConvertBufferedImage.convertFromSingle(image, null, GrayU8.class);


convolve1D(gray);
convolve1D(gray);
convolve2D(gray);
convolve2D(gray);
normalize2D(gray);
normalize2D(gray);
ShowImages.showWindow(panel, "Convolution Examples", true);
}
}


Line 31: Line 38:
* Convolves a 1D kernel horizontally and vertically
* Convolves a 1D kernel horizontally and vertically
*/
*/
private static void convolve1D(ImageUInt8 gray) {
private static void convolve1D( GrayU8 gray ) {
ImageBorder<ImageUInt8> border = FactoryImageBorder.single(gray, BorderType.EXTENDED);
var kernel = new Kernel1D_S32(2);
Kernel1D_I32 kernel = new Kernel1D_I32(2);
kernel.offset = 1; // specify the kernel's origin
kernel.offset = 1; // specify the kernel's origin
kernel.data[0] = 1;
kernel.data[0] = 1;
kernel.data[1] = -1;
kernel.data[1] = -1;


ImageSInt16 output = new ImageSInt16(gray.width,gray.height);
var output = new GrayS16(gray.width, gray.height);


GConvolveImageOps.horizontal(kernel, gray, output, border);
GConvolveImageOps.horizontal(kernel, gray, output, BorderType.EXTENDED);
ShowImages.showWindow(VisualizeImageData.standard(output, null), "1D Horizontal");
panel.addImage(VisualizeImageData.standard(output, null), "1D Horizontal");


GConvolveImageOps.vertical(kernel, gray, output, border);
GConvolveImageOps.vertical(kernel, gray, output, BorderType.EXTENDED);
ShowImages.showWindow(VisualizeImageData.standard(output, null), "1D Vertical");
panel.addImage(VisualizeImageData.standard(output, null), "1D Vertical");
}
}


Line 50: Line 56:
* Convolves a 2D kernel
* Convolves a 2D kernel
*/
*/
private static void convolve2D(ImageUInt8 gray) {
private static void convolve2D( GrayU8 gray ) {
// By default 2D kernels will be centered around width/2
// By default 2D kernels will be centered around width/2
Kernel2D_I32 kernel = new Kernel2D_I32(3);
var kernel = new Kernel2D_S32(3);
kernel.set(1,0,2);
kernel.set(1, 0, 2);
kernel.set(2,1,2);
kernel.set(2, 1, 2);
kernel.set(0,1,-2);
kernel.set(0, 1, -2);
kernel.set(1,2,-2);
kernel.set(1, 2, -2);


// Output needs to handle the increased domain after convolution. Can't be 8bit
// Output needs to handle the increased domain after convolution. Can't be 8bit
ImageSInt16 output = new ImageSInt16(gray.width,gray.height);
var output = new GrayS16(gray.width, gray.height);
ImageBorder<ImageUInt8> border = FactoryImageBorder.single(gray, BorderType.EXTENDED);


GConvolveImageOps.convolve(kernel, gray, output, border);
GConvolveImageOps.convolve(kernel, gray, output, BorderType.EXTENDED);
ShowImages.showWindow(VisualizeImageData.standard(output, null), "2D Kernel");
panel.addImage(VisualizeImageData.standard(output, null), "2D Kernel");
}
}


/**
/**
* Convolves a 2D normalized kernel. This kernel is divided by its sum after computation.
* Convolves a 2D normalized kernel. This kernel is divided by its sum after computation.
*/
*/
private static void normalize2D(ImageUInt8 gray) {
private static void normalize2D( GrayU8 gray ) {
// Create a Gaussian kernel with radius of 3
// Create a Gaussian kernel with radius of 3
Kernel2D_I32 kernel = FactoryKernelGaussian.gaussian2D(ImageUInt8.class, -1, 3);
Kernel2D_S32 kernel = FactoryKernelGaussian.gaussian2D(GrayU8.class, -1, 3);
// Note that there is a more efficient way to compute this convolution since it is a separable kernel
// Note that there is a more efficient way to compute this convolution since it is a separable kernel
// just use BlurImageOps instead.
// just use BlurImageOps instead.


// Since it's normalized it can be saved inside an 8bit image
// Since it's normalized it can be saved inside an 8bit image
ImageUInt8 output = new ImageUInt8(gray.width,gray.height);
var output = new GrayU8(gray.width, gray.height);


GConvolveImageOps.convolveNormalized(kernel, gray, output);
GConvolveImageOps.convolveNormalized(kernel, gray, output);
ShowImages.showWindow(VisualizeImageData.standard(output, null), "2D Normalized Kernel");
panel.addImage(VisualizeImageData.standard(output, null), "2D Normalized Kernel");
}
}
}
}
</syntaxhighlight>
</syntaxhighlight>

Latest revision as of 14:59, 17 January 2022

Example of how to convolve 1D and 2D convolution kernels across an image. Besides providing the kernel, how the border is handled needs to be specified. A normalized kernel will renormalize the

Example Code:

Concepts:

  • Convolution
  • Spacial filtering

Relevant Examples:

Example Code

/**
 * Several examples demonstrating convolution.
 *
 * @author Peter Abeles
 */
public class ExampleConvolution {

	private static final ListDisplayPanel panel = new ListDisplayPanel();

	public static void main( String[] args ) {
		BufferedImage image = UtilImageIO.loadImageNotNull(UtilIO.pathExample("sunflowers.jpg"));

		GrayU8 gray = ConvertBufferedImage.convertFromSingle(image, null, GrayU8.class);

		convolve1D(gray);
		convolve2D(gray);
		normalize2D(gray);

		ShowImages.showWindow(panel, "Convolution Examples", true);
	}

	/**
	 * Convolves a 1D kernel horizontally and vertically
	 */
	private static void convolve1D( GrayU8 gray ) {
		var kernel = new Kernel1D_S32(2);
		kernel.offset = 1; // specify the kernel's origin
		kernel.data[0] = 1;
		kernel.data[1] = -1;

		var output = new GrayS16(gray.width, gray.height);

		GConvolveImageOps.horizontal(kernel, gray, output, BorderType.EXTENDED);
		panel.addImage(VisualizeImageData.standard(output, null), "1D Horizontal");

		GConvolveImageOps.vertical(kernel, gray, output, BorderType.EXTENDED);
		panel.addImage(VisualizeImageData.standard(output, null), "1D Vertical");
	}

	/**
	 * Convolves a 2D kernel
	 */
	private static void convolve2D( GrayU8 gray ) {
		// By default 2D kernels will be centered around width/2
		var kernel = new Kernel2D_S32(3);
		kernel.set(1, 0, 2);
		kernel.set(2, 1, 2);
		kernel.set(0, 1, -2);
		kernel.set(1, 2, -2);

		// Output needs to handle the increased domain after convolution. Can't be 8bit
		var output = new GrayS16(gray.width, gray.height);

		GConvolveImageOps.convolve(kernel, gray, output, BorderType.EXTENDED);
		panel.addImage(VisualizeImageData.standard(output, null), "2D Kernel");
	}

	/**
	 * Convolves a 2D normalized kernel. This kernel is divided by its sum after computation.
	 */
	private static void normalize2D( GrayU8 gray ) {
		// Create a Gaussian kernel with radius of 3
		Kernel2D_S32 kernel = FactoryKernelGaussian.gaussian2D(GrayU8.class, -1, 3);
		// Note that there is a more efficient way to compute this convolution since it is a separable kernel
		// just use BlurImageOps instead.

		// Since it's normalized it can be saved inside an 8bit image
		var output = new GrayU8(gray.width, gray.height);

		GConvolveImageOps.convolveNormalized(kernel, gray, output);
		panel.addImage(VisualizeImageData.standard(output, null), "2D Normalized Kernel");
	}
}