 |
Idenify polygons and shapes using several methods
Source code name: "identify_polygon.java"
Programming language: Java
Topic: Images/Shape identification
DMelt Version 1.7. Last modified: 07/30/1970. License: Pro
https://datamelt.org/code/cache/identify_polygon_5196.java
To run this script using the DMelt IDE,
copy the above URL link to the menu [File]→[Read script from URL] of the DMelt IDE.
/*
* Copyright (c) 2011-2016, 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.
*/
import boofcv.alg.feature.detect.edge.CannyEdge;
import boofcv.alg.feature.detect.edge.EdgeContour;
import boofcv.alg.feature.detect.edge.EdgeSegment;
import boofcv.alg.filter.binary.BinaryImageOps;
import boofcv.alg.filter.binary.Contour;
import boofcv.alg.filter.binary.ThresholdImageOps;
import boofcv.alg.misc.ImageStatistics;
import boofcv.alg.shapes.ShapeFittingOps;
import boofcv.factory.feature.detect.edge.FactoryEdgeDetectors;
import boofcv.gui.ListDisplayPanel;
import boofcv.gui.feature.VisualizeShapes;
import boofcv.gui.image.ShowImages;
import boofcv.io.UtilIO;
import boofcv.io.image.ConvertBufferedImage;
import boofcv.io.image.UtilImageIO;
import boofcv.struct.ConnectRule;
import boofcv.struct.PointIndex_I32;
import boofcv.struct.image.GrayF32;
import boofcv.struct.image.GrayU8;
import georegression.struct.point.Point2D_I32;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.List;
import java.util.Random;
import jhplot.*;
/**
* Demonstration of how to convert a point sequence describing an objects outline/contour into a sequence of line
* segments. Useful when analysing shapes such as squares and triangles or when trying to simply the low level
* pixel output.
*
* @author Peter Abeles
*/
public class identify_polygon {
// Polynomial fitting tolerances
static double splitFraction = 0.05;
static double minimumSideFraction = 0.1;
static ListDisplayPanel gui = new ListDisplayPanel();
/**
* Fits polygons to found contours around binary blobs.
*/
public static void fitBinaryImage(GrayF32 input) {
GrayU8 binary = new GrayU8(input.width,input.height);
BufferedImage polygon = new BufferedImage(input.width,input.height,BufferedImage.TYPE_INT_RGB);
// the mean pixel value is often a reasonable threshold when creating a binary image
double mean = ImageStatistics.mean(input);
// create a binary image by thresholding
ThresholdImageOps.threshold(input, binary, (float) mean, true);
// reduce noise with some filtering
GrayU8 filtered = BinaryImageOps.erode8(binary, 1, null);
filtered = BinaryImageOps.dilate8(filtered, 1, null);
// Find the contour around the shapes
List contours = BinaryImageOps.contour(filtered, ConnectRule.EIGHT,null);
// Fit a polygon to each shape and draw the results
Graphics2D g2 = polygon.createGraphics();
g2.setStroke(new BasicStroke(2));
for( Contour c : contours ) {
// Fit the polygon to the found external contour. Note loop = true
List vertexes = ShapeFittingOps.fitPolygon(c.external,true,
splitFraction, minimumSideFraction,100);
g2.setColor(Color.RED);
VisualizeShapes.drawPolygon(vertexes,true,g2);
// handle internal contours now
g2.setColor(Color.BLUE);
for( List internal : c.internal ) {
vertexes = ShapeFittingOps.fitPolygon(internal,true, splitFraction, minimumSideFraction,100);
VisualizeShapes.drawPolygon(vertexes,true,g2);
}
}
gui.addImage(polygon, "Binary Blob Contours");
}
/**
* Fits a sequence of line-segments into a sequence of points found using the Canny edge detector. In this case
* the points are not connected in a loop. The canny detector produces a more complex tree and the fitted
* points can be a bit noisy compared to the others.
*/
public static void fitCannyEdges( GrayF32 input ) {
BufferedImage displayImage = new BufferedImage(input.width,input.height,BufferedImage.TYPE_INT_RGB);
// Finds edges inside the image
CannyEdge canny =
FactoryEdgeDetectors.canny(2, true, true, GrayF32.class, GrayF32.class);
canny.process(input,0.1f,0.3f,null);
List contours = canny.getContours();
Graphics2D g2 = displayImage.createGraphics();
g2.setStroke(new BasicStroke(2));
// used to select colors for each line
Random rand = new Random(234);
for( EdgeContour e : contours ) {
g2.setColor(new Color(rand.nextInt()));
for(EdgeSegment s : e.segments ) {
// fit line segments to the point sequence. Note that loop is false
List vertexes = ShapeFittingOps.fitPolygon(s.points,false,
splitFraction, minimumSideFraction,100);
VisualizeShapes.drawPolygon(vertexes, false, g2);
}
}
gui.addImage(displayImage, "Canny Trace");
}
/**
* Detects contours inside the binary image generated by canny. Only the external contour is relevant. Often
* easier to deal with than working with Canny edges directly.
*/
public static void fitCannyBinary( GrayF32 input ) {
BufferedImage displayImage = new BufferedImage(input.width,input.height,BufferedImage.TYPE_INT_RGB);
GrayU8 binary = new GrayU8(input.width,input.height);
// Finds edges inside the image
CannyEdge canny =
FactoryEdgeDetectors.canny(2, false, true, GrayF32.class, GrayF32.class);
canny.process(input,0.1f,0.3f,binary);
List contours = BinaryImageOps.contour(binary, ConnectRule.EIGHT, null);
Graphics2D g2 = displayImage.createGraphics();
g2.setStroke(new BasicStroke(2));
// used to select colors for each line
Random rand = new Random(234);
for( Contour c : contours ) {
// Only the external contours are relevant.
List vertexes = ShapeFittingOps.fitPolygon(c.external,true,
splitFraction, minimumSideFraction,100);
g2.setColor(new Color(rand.nextInt()));
VisualizeShapes.drawPolygon(vertexes,true,g2);
}
gui.addImage(displayImage, "Canny Contour");
}
public static void main( String args[] ) {
// load and convert the image into a usable format
String http="http://datamelt.org/examples/data/";
Web.get(http+"polygons.png");
BufferedImage image = UtilImageIO.loadImage("polygons.png");
GrayF32 input = ConvertBufferedImage.convertFromSingle(image, null, GrayF32.class);
gui.addImage(image,"Original");
fitCannyEdges(input);
fitCannyBinary(input);
fitBinaryImage(input);
ShowImages.showWindow(gui, "Polygon from Contour", true);
}
}
You see the box below because you did not login.