Difference between revisions of "Example Planar Image"

From BoofCV
Jump to navigationJump to search
m
 
(5 intermediate revisions by the same user not shown)
Line 1: Line 1:
The class Planar is used to store color images where each color or band is stored as an independent gray scale image. The advantage of using independent gray scale images for each band is that they can be easily processed by algorithms written for ImageGray.
The class Planar is used to store color images where each color or band is stored as an independent gray scale image. The advantage of using independent gray scale images for each band is that they can be easily processed by algorithms written for ImageGray.


In the example code below it is demonstrated how to convert Planar to and from BufferedImages, how to process each band independently, and how to access the pixel values.
In the example code below it is demonstrated how to convert Planar to and from BufferedImages, how to process each band independently, and how to access the pixel values.


Example File: [https://github.com/lessthanoptimal/BoofCV/blob/v0.23/examples/src/boofcv/examples/imageprocessing/ExamplePlanarImages.java ExamplePlanarImages.java]
Example File: [https://github.com/lessthanoptimal/BoofCV/blob/v0.40/examples/src/main/java/boofcv/examples/imageprocessing/ExamplePlanarImages.java ExamplePlanarImages.java]


Concepts:
Concepts:
Line 12: Line 12:
<syntaxhighlight lang="java">
<syntaxhighlight lang="java">
/**
/**
* <p>
  * {@link Planar} images are one way in which color images can be stored and manipulated inside
  * {@link Planar} images are one way in which color images can be stored and manipulated inside
  * of BoofCV. Inside of a Planar image each color band is stored as an independent {@link ImageGray}.
  * of BoofCV. Inside of a Planar image each color band is stored as an independent {@link ImageGray}.
  * This is unlike the more common interleaved format where color information is stored in adjacent bytes in
  * This is unlike the more common interleaved format where color information is stored in adjacent bytes in
  * the same image.
  * the same image.
* </p>
  *
  *
* <p>
  * The main advantage of {@link Planar} is the ease at which gray scale operations can be applied to each
  * The main advantage of {@link Planar} is the ease at which gray scale operations can be applied to each
  * band independently with no additional code. This is particularly useful in a library,
  * band independently with no additional code. This is particularly useful in a library,
  * such as BoofCV, which is heavily focused on gray scale image processing and computer vision. The are also
  * such as BoofCV, which is heavily focused on gray scale image processing and computer vision. The are also
  * situations for some scientific applications where processing each band independently makes more sense.
  * situations for some scientific applications where processing each band independently makes more sense.
* </p>
  *
  *
  * @author Peter Abeles
  * @author Peter Abeles
Line 38: Line 34:
public static void independent( BufferedImage input ) {
public static void independent( BufferedImage input ) {
// convert the BufferedImage into a Planar
// convert the BufferedImage into a Planar
Planar<GrayU8> image = ConvertBufferedImage.convertFromMulti(input,null,true,GrayU8.class);
Planar<GrayU8> image = ConvertBufferedImage.convertFromPlanar(input, null, true, GrayU8.class);


// declare the output blurred image
// declare the output blurred image
Planar<GrayU8> blurred = image.createSameShape();
Planar<GrayU8> blurred = image.createSameShape();
 
// Apply Gaussian blur to each band in the image
// Apply Gaussian blur to each band in the image
for( int i = 0; i < image.getNumBands(); i++ ) {
for (int i = 0; i < image.getNumBands(); i++) {
// note that the generalized version of BlurImageOps is not being used, but the type
// note that the generalized version of BlurImageOps is not being used, but the type
// specific version.
// specific version.
BlurImageOps.gaussian(image.getBand(i),blurred.getBand(i),-1,5,null);
BlurImageOps.gaussian(image.getBand(i), blurred.getBand(i), -1, 5, null);
}
}
 
// Declare the BufferedImage manually to ensure that the color bands have the same ordering on input
// Declare the BufferedImage manually to ensure that the color bands have the same ordering on input
// and output
// and output
BufferedImage output = new BufferedImage(image.width,image.height,input.getType());
var output = new BufferedImage(image.width, image.height, input.getType());
ConvertBufferedImage.convertTo(blurred, output,true);
ConvertBufferedImage.convertTo(blurred, output, true);


gui.addImage(input,"Input");
gui.addImage(input, "Input");
gui.addImage(output,"Gaussian Blur");
gui.addImage(output, "Gaussian Blur");
}
}


Line 62: Line 58:
* Values of pixels can be read and modified by accessing the internal {@link ImageGray}.
* Values of pixels can be read and modified by accessing the internal {@link ImageGray}.
*/
*/
public static void pixelAccess( BufferedImage input ) {
public static void pixelAccess( BufferedImage input ) {
// convert the BufferedImage into a Planar
// convert the BufferedImage into a Planar
Planar<GrayU8> image = ConvertBufferedImage.convertFromMulti(input,null,true,GrayU8.class);
Planar<GrayU8> image = ConvertBufferedImage.convertFromPlanar(input, null, true, GrayU8.class);


int x = 10, y = 10;
int x = 10, y = 10;


// to access a pixel you first access the gray image for the each band
// to access a pixel you first access the gray image for the each band
for( int i = 0; i < image.getNumBands(); i++ )
for (int i = 0; i < image.getNumBands(); i++)
System.out.println("Original "+i+" = "+image.getBand(i).get(x,y));
System.out.println("Original " + i + " = " + image.getBand(i).get(x, y));


// change the value in each band
// change the value in each band
for( int i = 0; i < image.getNumBands(); i++ )
for (int i = 0; i < image.getNumBands(); i++)
image.getBand(i).set(x, y, 100 + i);
image.getBand(i).set(x, y, 100 + i);


// to access a pixel you first access the gray image for the each band
// to access a pixel you first access the gray image for the each band
for( int i = 0; i < image.getNumBands(); i++ )
for (int i = 0; i < image.getNumBands(); i++)
System.out.println("Result  "+i+" = "+image.getBand(i).get(x,y));
System.out.println("Result  " + i + " = " + image.getBand(i).get(x, y));
}
}


/**
/**
* There is no real perfect way that everyone agrees on for converting color images into gray scale
* There is no real perfect way that everyone agrees on for converting color images into gray scale
* images. Two examples of how to convert a Planar image into a gray scale image are shown
* images. Two examples of how to convert a Planar image into a gray scale image are shown
* in this example.
* in this example.
*/
*/
public static void convertToGray( BufferedImage input ) {
public static void convertToGray( BufferedImage input ) {
// convert the BufferedImage into a Planar
// convert the BufferedImage into a Planar
Planar<GrayU8> image = ConvertBufferedImage.convertFromMulti(input,null,true,GrayU8.class);
Planar<GrayU8> image = ConvertBufferedImage.convertFromPlanar(input, null, true, GrayU8.class);


GrayU8 gray = new GrayU8( image.width,image.height);
var gray = new GrayU8(image.width, image.height);


// creates a gray scale image by averaging intensity value across pixels
// creates a gray scale image by averaging intensity value across pixels
GPixelMath.averageBand(image, gray);
ConvertImage.average(image, gray);
BufferedImage outputAve = ConvertBufferedImage.convertTo(gray,null);
BufferedImage outputAve = ConvertBufferedImage.convertTo(gray, null);
 
// convert to gray scale but weigh each color band based on how human vision works
ColorRgb.rgbToGray_Weighted(image, gray);
BufferedImage outputWeighted = ConvertBufferedImage.convertTo(gray, null);


// create an output image just from the first band
// create an output image just from the first band
BufferedImage outputBand0 = ConvertBufferedImage.convertTo(image.getBand(0),null);
BufferedImage outputBand0 = ConvertBufferedImage.convertTo(image.getBand(0), null);


gui.addImage(outputAve,"Gray Averaged");
gui.addImage(outputAve, "Gray Averaged");
gui.addImage(outputBand0,"Band 0");
gui.addImage(outputWeighted, "Gray Weighted");
gui.addImage(outputBand0, "Band 0");
}
}
public static void main( String args[] ) {
BufferedImage input = UtilImageIO.loadImage(UtilIO.pathExample("apartment_building_02.jpg"));


// Uncomment lines below to run each example
public static void main( String[] args ) {
BufferedImage input = UtilImageIO.loadImageNotNull(UtilIO.pathExample("apartment_building_02.jpg"));


ExamplePlanarImages.independent(input);
ExamplePlanarImages.independent(input);
Line 112: Line 111:
ExamplePlanarImages.convertToGray(input);
ExamplePlanarImages.convertToGray(input);


ShowImages.showWindow(gui,"Color Planar Image Examples",true);
ShowImages.showWindow(gui, "Color Planar Image Examples", true);
}
}
}
}
</syntaxhighlight>
</syntaxhighlight>

Latest revision as of 15:08, 17 January 2022

The class Planar is used to store color images where each color or band is stored as an independent gray scale image. The advantage of using independent gray scale images for each band is that they can be easily processed by algorithms written for ImageGray.

In the example code below it is demonstrated how to convert Planar to and from BufferedImages, how to process each band independently, and how to access the pixel values.

Example File: ExamplePlanarImages.java

Concepts:

  • Color image processing

Example Code

/**
 * {@link Planar} images are one way in which color images can be stored and manipulated inside
 * of BoofCV. Inside of a Planar image each color band is stored as an independent {@link ImageGray}.
 * This is unlike the more common interleaved format where color information is stored in adjacent bytes in
 * the same image.
 *
 * The main advantage of {@link Planar} is the ease at which gray scale operations can be applied to each
 * band independently with no additional code. This is particularly useful in a library,
 * such as BoofCV, which is heavily focused on gray scale image processing and computer vision. The are also
 * situations for some scientific applications where processing each band independently makes more sense.
 *
 * @author Peter Abeles
 */
public class ExamplePlanarImages {

	public static ListDisplayPanel gui = new ListDisplayPanel();

	/**
	 * Many operations designed to only work on {@link ImageGray} can be applied
	 * to a Planar image by feeding in each band one at a time.
	 */
	public static void independent( BufferedImage input ) {
		// convert the BufferedImage into a Planar
		Planar<GrayU8> image = ConvertBufferedImage.convertFromPlanar(input, null, true, GrayU8.class);

		// declare the output blurred image
		Planar<GrayU8> blurred = image.createSameShape();

		// Apply Gaussian blur to each band in the image
		for (int i = 0; i < image.getNumBands(); i++) {
			// note that the generalized version of BlurImageOps is not being used, but the type
			// specific version.
			BlurImageOps.gaussian(image.getBand(i), blurred.getBand(i), -1, 5, null);
		}

		// Declare the BufferedImage manually to ensure that the color bands have the same ordering on input
		// and output
		var output = new BufferedImage(image.width, image.height, input.getType());
		ConvertBufferedImage.convertTo(blurred, output, true);

		gui.addImage(input, "Input");
		gui.addImage(output, "Gaussian Blur");
	}

	/**
	 * Values of pixels can be read and modified by accessing the internal {@link ImageGray}.
	 */
	public static void pixelAccess( BufferedImage input ) {
		// convert the BufferedImage into a Planar
		Planar<GrayU8> image = ConvertBufferedImage.convertFromPlanar(input, null, true, GrayU8.class);

		int x = 10, y = 10;

		// to access a pixel you first access the gray image for the each band
		for (int i = 0; i < image.getNumBands(); i++)
			System.out.println("Original " + i + " = " + image.getBand(i).get(x, y));

		// change the value in each band
		for (int i = 0; i < image.getNumBands(); i++)
			image.getBand(i).set(x, y, 100 + i);

		// to access a pixel you first access the gray image for the each band
		for (int i = 0; i < image.getNumBands(); i++)
			System.out.println("Result   " + i + " = " + image.getBand(i).get(x, y));
	}

	/**
	 * There is no real perfect way that everyone agrees on for converting color images into gray scale
	 * images. Two examples of how to convert a Planar image into a gray scale image are shown
	 * in this example.
	 */
	public static void convertToGray( BufferedImage input ) {
		// convert the BufferedImage into a Planar
		Planar<GrayU8> image = ConvertBufferedImage.convertFromPlanar(input, null, true, GrayU8.class);

		var gray = new GrayU8(image.width, image.height);

		// creates a gray scale image by averaging intensity value across pixels
		ConvertImage.average(image, gray);
		BufferedImage outputAve = ConvertBufferedImage.convertTo(gray, null);

		// convert to gray scale but weigh each color band based on how human vision works
		ColorRgb.rgbToGray_Weighted(image, gray);
		BufferedImage outputWeighted = ConvertBufferedImage.convertTo(gray, null);

		// create an output image just from the first band
		BufferedImage outputBand0 = ConvertBufferedImage.convertTo(image.getBand(0), null);

		gui.addImage(outputAve, "Gray Averaged");
		gui.addImage(outputWeighted, "Gray Weighted");
		gui.addImage(outputBand0, "Band 0");
	}

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

		ExamplePlanarImages.independent(input);
		ExamplePlanarImages.pixelAccess(input);
		ExamplePlanarImages.convertToGray(input);

		ShowImages.showWindow(gui, "Color Planar Image Examples", true);
	}
}