boofcv.gui.binary.VisualizeBinaryData Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of boofcv-swing Show documentation
Show all versions of boofcv-swing Show documentation
BoofCV is an open source Java library for real-time computer vision and robotics applications.
/*
* Copyright (c) 2022, Peter Abeles. All Rights Reserved.
*
* This file is part of BoofCV (http://boofcv.org).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package boofcv.gui.binary;
import boofcv.alg.feature.detect.edge.EdgeContour;
import boofcv.alg.feature.detect.edge.EdgeSegment;
import boofcv.alg.filter.binary.Contour;
import boofcv.gui.BoofSwingUtil;
import boofcv.struct.image.GrayS32;
import boofcv.struct.image.GrayU8;
import georegression.struct.point.Point2D_I32;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.awt.geom.Line2D;
import java.awt.image.*;
import java.util.List;
import java.util.Random;
/**
* Operations for visualizing binary images and related data structures.
*
* @author Peter Abeles
*/
public class VisualizeBinaryData {
public static BufferedImage renderContours( List edges,
@Nullable int[] colors,
int width, int height,
@Nullable BufferedImage out ) {
if (out == null) {
out = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
} else {
Graphics2D g2 = out.createGraphics();
g2.setColor(Color.BLACK);
g2.fillRect(0, 0, width, height);
}
colors = checkColors(colors, edges.size());
for (int i = 0; i < edges.size(); i++) {
EdgeContour e = edges.get(i);
int color = colors[i];
for (EdgeSegment s : e.segments) {
for (Point2D_I32 p : s.points) {
out.setRGB(p.x, p.y, color);
}
}
}
return out;
}
/**
* Draws contours. Internal and external contours are different user specified colors.
*
* @param contours List of contours
* @param colorExternal RGB color
* @param colorInternal RGB color
* @param width Image width
* @param height Image height
* @param out (Optional) storage for output image
* @return Rendered contours
*/
public static BufferedImage renderContours( List contours, int colorExternal, int colorInternal,
int width, int height, @Nullable BufferedImage out ) {
if (out == null) {
out = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
} else {
Graphics2D g2 = out.createGraphics();
g2.setColor(Color.BLACK);
g2.fillRect(0, 0, width, height);
}
for (Contour c : contours) {
for (Point2D_I32 p : c.external) {
out.setRGB(p.x, p.y, colorExternal);
}
for (List l : c.internal) {
for (Point2D_I32 p : l) {
out.setRGB(p.x, p.y, colorInternal);
}
}
}
return out;
}
/**
* Draws contours. Internal and external contours are different user specified colors.
*
* @param contours List of contours
* @param colorExternal (Optional) Array of RGB colors for each external contour
* @param colorInternal RGB color
* @param width Image width
* @param height Image height
* @param out (Optional) storage for output image
* @return Rendered contours
*/
public static BufferedImage renderContours( List contours,
@Nullable int[] colorExternal, int colorInternal,
int width, int height, @Nullable BufferedImage out ) {
if (out == null) {
out = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
} else {
Graphics2D g2 = out.createGraphics();
g2.setColor(Color.BLACK);
g2.fillRect(0, 0, width, height);
}
colorExternal = checkColors(colorExternal, contours.size());
int index = 0;
for (Contour c : contours) {
int color = colorExternal[index++];
for (Point2D_I32 p : c.external) {
out.setRGB(p.x, p.y, color);
}
for (List l : c.internal) {
for (Point2D_I32 p : l) {
out.setRGB(p.x, p.y, colorInternal);
}
}
}
return out;
}
/**
* Renders only the external contours. Each contour is individually colored as specified by 'colors'
*
* @param contours (Input) List of contours
* @param colors (Input) List of RGB colors for each element in contours. If null then random colors will be used.
* @param out (Output) Where the contours are rendered.
*/
public static void render( List contours, int[] colors, BufferedImage out ) {
colors = checkColors(colors, contours.size());
for (int i = 0; i < contours.size(); i++) {
Contour c = contours.get(i);
int color = colors[i];
for (Point2D_I32 p : c.external) {
out.setRGB(p.x, p.y, color);
}
}
}
public static int[] checkColors( @Nullable int[] colors, int size ) {
if (colors == null) {
colors = new int[size];
Random rand = new Random(123);
for (int i = 0; i < size; i++) {
colors[i] = rand.nextInt();
}
}
return colors;
}
public static BufferedImage render( List contours, Color color, BufferedImage out ) {
for (Contour c : contours) {
for (Point2D_I32 p : c.external) {
out.setRGB(p.x, p.y, color.getRGB());
}
}
return out;
}
public static void render( List> contours, boolean loops,
Color color, double stroke, double scale, Graphics2D g2 ) {
BoofSwingUtil.antialiasing(g2);
Line2D.Double l = new Line2D.Double();
g2.setStroke(new BasicStroke(Math.max(1, (float)(stroke*scale))));
g2.setColor(color);
for (List c : contours) {
if (loops)
renderLoop(scale, g2, l, c);
else
renderLine(scale, g2, l, c);
}
if (scale > 4) {
Color before = g2.getColor();
g2.setStroke(new BasicStroke(1));
g2.setColor(Color.LIGHT_GRAY);
for (List c : contours) {
if (loops)
renderLoop(scale, g2, l, c);
else
renderLine(scale, g2, l, c);
}
g2.setColor(before);
}
}
public static void render( List contours, @Nullable Color internal, @Nullable Color external,
double stroke, double scale, Graphics2D g2 ) {
g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Line2D.Double l = new Line2D.Double();
g2.setStroke(new BasicStroke(Math.max(1, (float)(stroke*scale))));
for (Contour c : contours) {
if (external != null) {
g2.setColor(external);
renderLoop(scale, g2, l, c.external);
}
if (internal != null) {
g2.setColor(internal);
for (List inner : c.internal) {
renderLoop(scale, g2, l, inner);
}
}
}
if (scale > 4) {
Color before = g2.getColor();
g2.setStroke(new BasicStroke(1));
g2.setColor(Color.LIGHT_GRAY);
for (Contour c : contours) {
if (external != null) {
renderLoop(scale, g2, l, c.external);
}
if (internal != null) {
for (List inner : c.internal) {
renderLoop(scale, g2, l, inner);
}
}
}
g2.setColor(before);
}
}
private static void renderLoop( double scale, Graphics2D g2, Line2D.Double l, List list ) {
for (int i = 0, j = list.size() - 1; i < list.size(); j = i, i++) {
Point2D_I32 p0 = list.get(i);
Point2D_I32 p1 = list.get(j);
// draw it in the middle
l.setLine((p0.x + 0.5)*scale, (p0.y + 0.5)*scale, (p1.x + 0.5)*scale, (p1.y + 0.5)*scale);
g2.draw(l);
}
}
private static void renderLine( double scale, Graphics2D g2, Line2D.Double l, List list ) {
for (int i = 1, j = 0; i < list.size(); j = i, i++) {
Point2D_I32 p0 = list.get(i);
Point2D_I32 p1 = list.get(j);
// draw it in the middle
l.setLine((p0.x + 0.5)*scale, (p0.y + 0.5)*scale, (p1.x + 0.5)*scale, (p1.y + 0.5)*scale);
g2.draw(l);
}
}
public static BufferedImage renderLabeled( GrayS32 labelImage, int[] colors, @Nullable BufferedImage out ) {
if (out == null) {
out = new BufferedImage(labelImage.getWidth(), labelImage.getHeight(), BufferedImage.TYPE_INT_RGB);
}
WritableRaster raster = out.getRaster();
DataBuffer buffer = raster.getDataBuffer();
try {
if (buffer.getDataType() == DataBuffer.TYPE_INT) {
renderLabeled(labelImage, colors, (DataBufferInt)buffer);
} else {
_renderLabeled(labelImage, out, colors);
}
// hack so that it knows the image has been modified
out.setRGB(0, 0, out.getRGB(0, 0));
} catch (SecurityException e) {
_renderLabeled(labelImage, out, colors);
}
return out;
}
/**
* Renders a labeled image where label=0 is assumed to be the background and is always set to black. All
* other labels are assigned a random color.
*
* @param labelImage Labeled image with background having a value of 0
* @param numRegions Number of labeled in the image, excluding the background.
* @param out Output image. If null a new image is declared
* @return Colorized labeled image
*/
public static BufferedImage renderLabeledBG( GrayS32 labelImage, int numRegions, @Nullable BufferedImage out ) {
int[] colors = new int[numRegions + 1];
Random rand = new Random(123);
for (int i = 0; i < colors.length; i++) {
colors[i] = rand.nextInt();
}
colors[0] = 0;
return renderLabeled(labelImage, colors, out);
}
/**
* Renders a labeled where each region is assigned a random color.
*
* @param labelImage Labeled image with labels from 0 to numRegions-1
* @param numRegions Number of labeled in the image
* @param out Output image. If null a new image is declared
* @return Colorized labeled image
*/
public static BufferedImage renderLabeled( GrayS32 labelImage, int numRegions, @Nullable BufferedImage out ) {
int[] colors = new int[numRegions];
Random rand = new Random(123);
for (int i = 0; i < colors.length; i++) {
colors[i] = rand.nextInt();
}
return renderLabeled(labelImage, colors, out);
}
private static void _renderLabeled( GrayS32 labelImage, BufferedImage out, int[] colors ) {
int w = labelImage.getWidth();
int h = labelImage.getHeight();
for (int y = 0; y < h; y++) {
int indexSrc = labelImage.startIndex + y*labelImage.stride;
for (int x = 0; x < w; x++) {
int rgb = colors[labelImage.data[indexSrc++]];
out.setRGB(x, y, rgb);
}
}
}
private static void renderLabeled( GrayS32 labelImage, int[] colors, DataBufferInt buffer ) {
int rasterIndex = 0;
int[] data = buffer.getData();
int w = labelImage.getWidth();
int h = labelImage.getHeight();
for (int y = 0; y < h; y++) {
int indexSrc = labelImage.startIndex + y*labelImage.stride;
for (int x = 0; x < w; x++) {
data[rasterIndex++] = colors[labelImage.data[indexSrc++]];
}
}
}
/**
* Renders a binary image. 0 = black and 1 = white.
*
* @param binaryImage (Input) Input binary image.
* @param invert (Input) if true it will invert the image on output
* @param out (Output) optional storage for output image
* @return Output rendered binary image
*/
public static BufferedImage renderBinary( GrayU8 binaryImage, boolean invert, @Nullable BufferedImage out ) {
if (out == null || (out.getWidth() != binaryImage.width || out.getHeight() != binaryImage.height)) {
out = new BufferedImage(binaryImage.getWidth(), binaryImage.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
}
try {
WritableRaster raster = out.getRaster();
DataBuffer buffer = raster.getDataBuffer();
if (buffer.getDataType() == DataBuffer.TYPE_BYTE) {
_renderBinary(binaryImage, invert, (DataBufferByte)buffer, raster);
} else if (buffer.getDataType() == DataBuffer.TYPE_INT) {
_renderBinary(binaryImage, invert, (DataBufferInt)buffer);
} else {
_renderBinary(binaryImage, invert, out);
}
} catch (SecurityException e) {
_renderBinary(binaryImage, invert, out);
}
// hack so that it knows the buffer has been modified
out.setRGB(0, 0, out.getRGB(0, 0));
return out;
}
private static void _renderBinary( GrayU8 binaryImage, boolean invert, BufferedImage out ) {
int w = binaryImage.getWidth();
int h = binaryImage.getHeight();
if (invert) {
for (int y = 0; y < h; y++) {
int indexSrc = binaryImage.startIndex + y*binaryImage.stride;
for (int x = 0; x < w; x++) {
int rgb = binaryImage.data[indexSrc++] != 0 ? 0 : 0x00FFFFFF;
out.setRGB(x, y, rgb);
}
}
} else {
for (int y = 0; y < h; y++) {
int indexSrc = binaryImage.startIndex + y*binaryImage.stride;
for (int x = 0; x < w; x++) {
int rgb = binaryImage.data[indexSrc++] != 0 ? 0x00FFFFFF : 0;
out.setRGB(x, y, rgb);
}
}
}
}
private static void _renderBinary( GrayU8 binaryImage, boolean invert,
DataBufferByte buffer, WritableRaster raster ) {
int rasterIndex = 0;
byte[] data = buffer.getData();
int w = binaryImage.getWidth();
int h = binaryImage.getHeight();
int numBands = raster.getNumBands();
if (numBands == 1) {
if (invert) {
for (int y = 0; y < h; y++) {
int indexSrc = binaryImage.startIndex + y*binaryImage.stride;
for (int x = 0; x < w; x++) {
data[rasterIndex++] = (byte)(binaryImage.data[indexSrc++] == 0 ? 255 : 0);
}
}
} else {
for (int y = 0; y < h; y++) {
int indexSrc = binaryImage.startIndex + y*binaryImage.stride;
for (int x = 0; x < w; x++) {
data[rasterIndex++] = (byte)(binaryImage.data[indexSrc++] == 0 ? 0 : 255);
}
}
}
} else if (numBands == 3) {
if (invert) {
for (int y = 0; y < h; y++) {
int indexSrc = binaryImage.startIndex + y*binaryImage.stride;
for (int x = 0; x < w; x++) {
byte val = (byte)(binaryImage.data[indexSrc++] == 0 ? 255 : 0);
for (int i = 0; i < numBands; i++) {
data[rasterIndex++] = val;
}
}
}
} else {
for (int y = 0; y < h; y++) {
int indexSrc = binaryImage.startIndex + y*binaryImage.stride;
for (int x = 0; x < w; x++) {
byte val = (byte)(binaryImage.data[indexSrc++] == 0 ? 0 : 255);
for (int i = 0; i < numBands; i++) {
data[rasterIndex++] = val;
}
}
}
}
} else if (numBands == 4) {
if (invert) {
for (int y = 0; y < h; y++) {
int indexSrc = binaryImage.startIndex + y*binaryImage.stride;
for (int x = 0; x < w; x++) {
byte val = (byte)(binaryImage.data[indexSrc++] == 0 ? 255 : 0);
data[rasterIndex++] = (byte)0xFF;
for (int i = 1; i < 4; i++) {
data[rasterIndex++] = val;
}
}
}
} else {
for (int y = 0; y < h; y++) {
int indexSrc = binaryImage.startIndex + y*binaryImage.stride;
for (int x = 0; x < w; x++) {
byte val = (byte)(binaryImage.data[indexSrc++] == 0 ? 0 : 255);
data[rasterIndex++] = (byte)0xFF;
for (int i = 1; i < 4; i++) {
data[rasterIndex++] = val;
}
}
}
}
}
}
private static void _renderBinary( GrayU8 binaryImage, boolean invert, DataBufferInt buffer ) {
int rasterIndex = 0;
int[] data = buffer.getData();
int w = binaryImage.getWidth();
int h = binaryImage.getHeight();
if (invert) {
for (int y = 0; y < h; y++) {
int indexSrc = binaryImage.startIndex + y*binaryImage.stride;
for (int x = 0; x < w; x++) {
data[rasterIndex++] = binaryImage.data[indexSrc++] != 0 ? 0 : 0xFFFFFFFF;
}
}
} else {
for (int y = 0; y < h; y++) {
int indexSrc = binaryImage.startIndex + y*binaryImage.stride;
for (int x = 0; x < w; x++) {
data[rasterIndex++] = binaryImage.data[indexSrc++] != 0 ? 0xFFFFFFFF : 0;
}
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy