/*
* 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.
*/
package boofcv.demonstrations.fiducial;
import boofcv.abst.filter.binary.InputToBinary;
import boofcv.alg.distort.AdjustmentType;
import boofcv.alg.distort.ImageDistort;
import boofcv.alg.distort.LensDistortionOps;
import boofcv.alg.fiducial.square.BaseDetectFiducialSquare;
import boofcv.alg.fiducial.square.FoundFiducial;
import boofcv.core.image.border.BorderType;
import boofcv.factory.filter.binary.ConfigThreshold;
import boofcv.factory.filter.binary.FactoryThresholdBinary;
import boofcv.factory.filter.binary.ThresholdType;
import boofcv.factory.shape.ConfigPolygonDetector;
import boofcv.factory.shape.FactoryShapeDetector;
import boofcv.gui.ListDisplayPanel;
import boofcv.gui.binary.VisualizeBinaryData;
import boofcv.gui.feature.VisualizeShapes;
import boofcv.gui.fiducial.VisualizeFiducial;
import boofcv.gui.image.ShowImages;
import boofcv.io.UtilIO;
import boofcv.io.image.ConvertBufferedImage;
import boofcv.io.image.UtilImageIO;
import boofcv.struct.calib.IntrinsicParameters;
import boofcv.struct.distort.PointTransform_F64;
import boofcv.struct.image.GrayF32;
import boofcv.struct.image.ImageType;
import georegression.struct.point.Point2D_F64;
import georegression.struct.se.Se3_F64;
import georegression.struct.shapes.Quadrilateral_F64;
import org.ddogleg.struct.FastQueue;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
/**
* @author Peter Abeles
*/
public class VisualizeSquareFiducial {
static ConfigThreshold configThreshold = ConfigThreshold.local(ThresholdType.LOCAL_SQUARE,6);
static InputToBinary inputToBinary = FactoryThresholdBinary.threshold(configThreshold, GrayF32.class);
public void process( String nameImage , String nameIntrinsic ) {
IntrinsicParameters intrinsic = nameIntrinsic == null ? null : (IntrinsicParameters)UtilIO.loadXML(nameIntrinsic);
GrayF32 input = UtilImageIO.loadImage(nameImage, GrayF32.class);
GrayF32 undistorted = new GrayF32(input.width,input.height);
Detector detector = new Detector();
if( intrinsic != null ) {
IntrinsicParameters paramUndist = new IntrinsicParameters();
ImageDistort undistorter = LensDistortionOps.imageRemoveDistortion(
AdjustmentType.EXPAND, BorderType.EXTENDED, intrinsic, paramUndist,
ImageType.single(GrayF32.class));
detector.configure(paramUndist,false);
undistorter.apply(input,undistorted);
} else {
undistorted.setTo(input);
}
detector.process(undistorted);
System.out.println("Total Found: "+detector.squares.size());
FastQueue fiducials = detector.getFound();
int N = Math.min(20,detector.squares.size());
ListDisplayPanel squares = new ListDisplayPanel();
for (int i = 0; i < N; i++) {
squares.addImage(ConvertBufferedImage.convertTo(detector.squares.get(i),null)," "+i);
}
BufferedImage output = new BufferedImage(input.width,input.height,BufferedImage.TYPE_INT_RGB);
VisualizeBinaryData.renderBinary(detector.getBinary(), false, output);
Graphics2D g2 = output.createGraphics();
g2.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.RED);
g2.setStroke(new BasicStroke(2));
if( intrinsic != null ) {
PointTransform_F64 add_p_to_p = LensDistortionOps.transformPoint(intrinsic).distort_F64(true, true);
Se3_F64 targetToWorld = new Se3_F64();
for (int i = 0; i < N; i++) {
// add back in lens distortion
Quadrilateral_F64 q = fiducials.get(i).location;
detector.computeTargetToWorld(q, 0.1, targetToWorld);
VisualizeFiducial.drawCube(targetToWorld, intrinsic, 0.1, 3, g2);
apply(add_p_to_p, q.a, q.a);
apply(add_p_to_p, q.b, q.b);
apply(add_p_to_p, q.c, q.c);
apply(add_p_to_p, q.d, q.d);
VisualizeShapes.draw(q, g2);
}
}
BufferedImage outputGray = new BufferedImage(input.width,input.height,BufferedImage.TYPE_INT_RGB);
ConvertBufferedImage.convertTo(undistorted,outputGray);
g2 = outputGray.createGraphics();
g2.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
for (int i = 0; i < N; i++) {
// add back in lens distortion
Quadrilateral_F64 q = fiducials.get(i).location;
// g2.setStroke(new BasicStroke(2));
// VisualizeBinaryData.renderExternal(detector.getSquareDetector().getUsedContours(),Color.BLUE,outputGray);
VisualizeShapes.drawArrowSubPixel(q,3,g2);
}
ShowImages.showWindow(output,"Binary");
ShowImages.showWindow(outputGray,"Gray");
ShowImages.showWindow(squares,"Candidates");
}
private void apply( PointTransform_F64 dist , Point2D_F64 p , Point2D_F64 o ) {
dist.compute(p.x,p.y,o);
}
public static class Detector extends BaseDetectFiducialSquare {
public List squares = new ArrayList();
protected Detector() {
super(inputToBinary,FactoryShapeDetector.polygon(new ConfigPolygonDetector(false, 4,4), GrayF32.class),
0.25,0.65,200,GrayF32.class);
}
@Override
protected boolean processSquare(GrayF32 square, Result result, double a, double b) {
squares.add(square.clone());
return true;
}
}
public static void main(String[] args) {
String directory = UtilIO.pathExample("fiducial/binary");
// String directory = UtilIO.pathExample("fiducial/image");
VisualizeSquareFiducial app = new VisualizeSquareFiducial();
// app.process(directory+"/image0000.jpg",directory+"/intrinsic.xml");
// app.process(directory+"/image0001.jpg",directory+"/intrinsic.xml");
// app.process(directory+"/image0002.jpg",directory+"/intrinsic.xml");
app.process("/home/pabeles/Downloads/image00003.png",null);
}
}
Ads help maintain this website.