/*
* 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.distort;
import boofcv.abst.distort.FDistort;
import boofcv.abst.geo.Estimate1ofEpipolar;
import boofcv.alg.interpolate.InterpolationType;
import boofcv.factory.geo.FactoryMultiView;
import boofcv.struct.geo.AssociatedPair;
import boofcv.struct.image.ImageBase;
import boofcv.struct.image.ImageType;
import georegression.struct.point.Point2D_F64;
import org.ejml.data.DenseMatrix64F;
import java.util.ArrayList;
/**
* Class which simplifies the removal of perspective distortion from a region inside an image. Given the ordered
* corners of a quadrilateral in the input image it applies a homography transform which reprojects the region
* into the input image into a rectangular output image.
*
* @author Peter Abeles
*/
public class RemovePerspectiveDistortion<T extends ImageBase> {
FDistort distort;
// computes the homography
Estimate1ofEpipolar computeHomography = FactoryMultiView.computeHomography(true);
// RefineEpipolar refineHomography = FactoryMultiView.refineHomography(1e-8,20, EpipolarError.SIMPLE);
// storage for computed homography
DenseMatrix64F H = new DenseMatrix64F(3,3);
// DenseMatrix64F Hrefined = new DenseMatrix64F(3,3);
// transform which applies the homography
PointTransformHomography_F32 homography = new PointTransformHomography_F32();
// storage for associated points between the two images
ArrayList<AssociatedPair> associatedPairs = new ArrayList<>();
// input and output images
T output;
/**
* Constructor which specifies the characteristics of the undistorted image
*
* @param width Width of undistorted image
* @param height Height of undistorted image
* @param imageType Type of undistorted image
*/
public RemovePerspectiveDistortion( int width , int height , ImageType<T> imageType ) {
output = imageType.createImage(width,height);
distort = new FDistort(imageType);
distort.output(output);
distort.interp(InterpolationType.BILINEAR).transform(homography);
for (int i = 0; i < 4; i++) {
associatedPairs.add( new AssociatedPair());
}
associatedPairs.get(0).p1.set(0,0);
associatedPairs.get(1).p1.set(output.width-1,0);
associatedPairs.get(2).p1.set(output.width-1,output.height-1);
associatedPairs.get(3).p1.set(0,output.height-1);
}
/**
* Applies distortion removal to the specified region in the input image. The undistorted image is returned.
* @param input Input image
* @param corner0 Top left corner
* @param corner1 Top right corner
* @param corner2 Bottom right corner
* @param corner3 Bottom left corner
* @return true if successful or false if it failed
*/
public boolean apply( T input ,
Point2D_F64 corner0 , Point2D_F64 corner1 ,
Point2D_F64 corner2 , Point2D_F64 corner3 )
{
associatedPairs.get(0).p2.set(corner0);
associatedPairs.get(1).p2.set(corner1);
associatedPairs.get(2).p2.set(corner2);
associatedPairs.get(3).p2.set(corner3);
if( !computeHomography.process(associatedPairs, H) )
return false;
// if( !refineHomography.fitModel(associatedPairs,H,Hrefined) ) {
// return false;
// }
// homography.set(Hrefined);
homography.set(H);
distort.input(input).apply();
return true;
}
/**
* Returns the undistorted output image
*/
public T getOutput() {
return output;
}
}