Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* 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.alg.shapes.polygon;
import boofcv.alg.shapes.corner.RefineCornerLinesToImage;
import boofcv.alg.shapes.edge.SnapToLineEdge;
import boofcv.misc.CircularIndex;
import boofcv.struct.distort.PixelTransform2_F32;
import boofcv.struct.image.ImageGray;
import georegression.struct.point.Point2D_F64;
import georegression.struct.point.Point2D_I32;
import georegression.struct.shapes.Polygon2D_F64;
import org.ddogleg.struct.GrowQueue_I32;
import java.util.List;
/**
* Given a contour and the index of corner points it will fit the corners individually to sub-pixel precision
* by locally fitting line segments near by each corner. The length of each line segment is specified
* by the number of pixels away it will traverse the contour. It makes sure that the end point does not go
* past the next corner.
*
* @author Peter Abeles
*/
public class RefinePolygonCornersToImage implements RefineBinaryPolygon {
// number of pixels along the contour away should the end point be from the corner
private int pixelsAway;
// used to refine individual corners
protected RefineCornerLinesToImage refineCorner;
// storage for corner points
protected Point2D_F64 cornerPt = new Point2D_F64();
protected Point2D_F64 leftPt = new Point2D_F64();
protected Point2D_F64 rightPt = new Point2D_F64();
// reference ti input contour and corner indexes
protected List contour;
protected GrowQueue_I32 splits;
/**
* Configures all parameters of the detector
*
* @param endPointDistance How many indexes away in the contour list should end points be.
* @param cornerOffset pixels this close to the corner will be ignored. Try 2
* @param maxLineSamples Number of points along the line which will be sampled. try 10
* @param sampleRadius How far away from the line will it sample pixels. ≥ 1
* @param maxIterations Maximum number of iterations it will perform. Try 10
* @param convergeTolPixels When the corner changes less than this amount it will stop iterating. Try 1e-5
* @param maxCornerChangePixels maximum change in corner location allowed from previous iteration in pixels. Try 2.0
* @param imageType Type of input image.
*/
public RefinePolygonCornersToImage(int endPointDistance,
double cornerOffset, int maxLineSamples, int sampleRadius,
int maxIterations, double convergeTolPixels,double maxCornerChangePixels,
Class imageType) {
this.pixelsAway = endPointDistance;
this.refineCorner = new RefineCornerLinesToImage<>(cornerOffset, maxLineSamples, sampleRadius, maxIterations,
convergeTolPixels, maxCornerChangePixels, imageType);
}
/**
* Provides reasonable default values for all parameters that it can
*
* @param imageType Type of input image.
*/
public RefinePolygonCornersToImage(Class imageType) {
this(12,2,10,1,10,1e-6,2,imageType);
}
/**
* Sets the input image
*
* @param input Input image-
*/
@Override
public void setImage( T input ) {
refineCorner.setImage(input);
}
@Override
public void setLensDistortion(int width, int height, PixelTransform2_F32 distToUndist, PixelTransform2_F32 undistToDist) {
this.refineCorner.getSnapToEdge().setTransform(undistToDist);
}
@Override
public void clearLensDistortion() {
this.refineCorner.getSnapToEdge().setTransform(null);
}
/**
* Refines the corner estimates in the contour.
*
* @param contour (Input) Shape's contour
* @param splits (Input) index of corners in the contour
* @param refined (Output) Refined polygon with sub-pixel accurate corners
* @return Number of corners it successfully optimized.
*/
@Override
public boolean refine(Polygon2D_F64 input, List contour , GrowQueue_I32 splits, Polygon2D_F64 refined) {
if( refined.size() != splits.size() )
throw new IllegalArgumentException("Miss match between number of splits and polygon order");
this.contour = contour;
this.splits = splits;
int numGood = 0;
for (int cornerS = 0; cornerS < splits.size(); cornerS++) {
int indexLeft = pickEndIndex(cornerS, 1);
int indexRight = pickEndIndex(cornerS, -1);
Point2D_I32 contourCorner = contour.get(splits.get(cornerS));
Point2D_I32 contourLeft = contour.get(indexLeft);
Point2D_I32 contourRight = contour.get(indexRight);
cornerPt.set(contourCorner.x,contourCorner.y);
leftPt.set(contourLeft.x,contourLeft.y);
rightPt.set(contourRight.x,contourRight.y);
if( refineCorner.refine(cornerPt,leftPt,rightPt)) {
refined.get(cornerS).set( refineCorner.getRefinedCorner());
numGood++;
} else {
// use the original
refined.get(cornerS).set(cornerPt);
}
}
// allow partial success
return numGood >= refined.size()-1;
}
/**
* Selects the index to use as the end point. Makes sure that the index does not go past
* the next corner.
*
* @param cornerS index of corner in split list
* @param dir Specifies which corner is next. can be -1 or 1.
*/
protected int pickEndIndex(int cornerS, int dir)
{
int cornerIndex = splits.get(cornerS);
int endIndex0 = splits.get(CircularIndex.addOffset(cornerS, dir, splits.size));
int endIndex1 = splits.get(CircularIndex.addOffset(cornerS, -dir, splits.size));
// splits being in increasing or decreasing order isn't specified. This make sure the correct
// point is selected
int dist0 = CircularIndex.distanceP(cornerIndex, endIndex0, contour.size());
int dist1 = CircularIndex.distanceP(cornerIndex, endIndex1, contour.size());
if( dir == 1 != dist1 > dist0 )
dir = -dir;
if( dir < 0 ) {
int distance = CircularIndex.distanceP(endIndex0, cornerIndex, contour.size());
distance = Math.min(distance,pixelsAway);
return CircularIndex.addOffset(cornerIndex, -distance, contour.size());
} else {
int distance = CircularIndex.distanceP(cornerIndex, endIndex0, contour.size());
distance = Math.min(distance,pixelsAway);
return CircularIndex.addOffset(cornerIndex, distance, contour.size());
}
}
public int getPixelsAway() {
return pixelsAway;
}
public void setPixelsAway(int pixelsAway) {
this.pixelsAway = pixelsAway;
}
public SnapToLineEdge getSnapToEdge() {
return refineCorner.getSnapToEdge();
}
}