/*
* 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.filter.derivative;
import boofcv.abst.filter.derivative.AnyImageDerivative;
import boofcv.core.image.GeneralizedImageOps;
import boofcv.core.image.border.*;
import boofcv.struct.convolve.Kernel1D;
import boofcv.struct.convolve.Kernel2D;
import boofcv.struct.convolve.KernelBase;
import boofcv.struct.image.*;
/**
* Generalized operations related to compute different image derivatives.
*
* @author Peter Abeles
*/
public class GImageDerivativeOps {
public static
void laplace( I input , D output ) {
if( input instanceof GrayF32) {
LaplacianEdge.process((GrayF32)input,(GrayF32)output);
} else if( input instanceof GrayU8) {
LaplacianEdge.process((GrayU8)input,(GrayS16)output);
} else {
throw new IllegalArgumentException("Unknown input image type: "+input.getClass().getSimpleName());
}
}
/**
* Returns the type of image the derivative should be for the specified input type.
* @param imageType Input image type.
* @return Appropriate output image type.
*/
public static
Class getDerivativeType( Class imageType ) {
if( imageType == GrayF32.class ) {
return (Class) GrayF32.class;
} else if( imageType == GrayU8.class ) {
return (Class) GrayS16.class;
} else if( imageType == GrayU16.class ) {
return (Class) GrayS32.class;
} else {
throw new IllegalArgumentException("Unknown input image type: "+imageType.getSimpleName());
}
}
/**
* Computes the gradient using the specified image type.
*
* @param type Type of gradient to compute
* @param input Input image
* @param derivX Output. Derivative X
* @param derivY Output. Derivative Y
* @param borderType How it should handle borders. null == skip border
* @param Input image type
* @param Output image type
*/
public static
void gradient( DerivativeType type , I input , D derivX , D derivY , BorderType borderType ) {
ImageBorder border = BorderType.SKIP == borderType ? null : FactoryImageBorder.single(input, borderType);
switch( type ) {
case PREWITT:
if( input instanceof GrayF32) {
GradientPrewitt.process((GrayF32)input,(GrayF32)derivX,(GrayF32)derivY,(ImageBorder_F32)border);
} else if( input instanceof GrayU8) {
GradientPrewitt.process((GrayU8)input,(GrayS16)derivX,(GrayS16)derivY,(ImageBorder_S32)border);
} else if( input instanceof GrayS16) {
GradientPrewitt.process((GrayS16)input,(GrayS16)derivX,(GrayS16)derivY,(ImageBorder_S32)border);
} else {
throw new IllegalArgumentException("Unknown input image type: "+input.getClass().getSimpleName());
}
break;
case SOBEL:
if( input instanceof GrayF32) {
GradientSobel.process((GrayF32)input,(GrayF32)derivX,(GrayF32)derivY,(ImageBorder_F32)border);
} else if( input instanceof GrayU8) {
GradientSobel.process((GrayU8)input,(GrayS16)derivX,(GrayS16)derivY,(ImageBorder_S32)border);
} else if( input instanceof GrayS16) {
GradientSobel.process((GrayS16)input,(GrayS16)derivX,(GrayS16)derivY,(ImageBorder_S32)border);
} else {
throw new IllegalArgumentException("Unknown input image type: "+input.getClass().getSimpleName());
}
break;
case THREE:
if( input instanceof GrayF32) {
GradientThree.process((GrayF32)input,(GrayF32)derivX,(GrayF32)derivY,(ImageBorder_F32)border);
} else if( input instanceof GrayU8) {
GradientThree.process((GrayU8)input,(GrayS16)derivX,(GrayS16)derivY,(ImageBorder_S32)border);
} else if( input instanceof GrayS16) {
GradientThree.process((GrayS16)input,(GrayS16)derivX,(GrayS16)derivY,(ImageBorder_S32)border);
} else {
throw new IllegalArgumentException("Unknown input image type: "+input.getClass().getSimpleName());
}
break;
case TWO_0:
if( input instanceof GrayF32) {
GradientTwo0.process((GrayF32) input, (GrayF32) derivX, (GrayF32) derivY, (ImageBorder_F32) border);
} else if( input instanceof GrayU8) {
GradientTwo0.process((GrayU8) input, (GrayS16) derivX, (GrayS16) derivY, (ImageBorder_S32) border);
} else if( input instanceof GrayS16) {
GradientTwo0.process((GrayS16) input, (GrayS16) derivX, (GrayS16) derivY, (ImageBorder_S32) border);
} else {
throw new IllegalArgumentException("Unknown input image type: "+input.getClass().getSimpleName());
}
break;
case TWO_1:
if( input instanceof GrayF32) {
GradientTwo1.process((GrayF32) input, (GrayF32) derivX, (GrayF32) derivY, (ImageBorder_F32) border);
} else if( input instanceof GrayU8) {
GradientTwo1.process((GrayU8) input, (GrayS16) derivX, (GrayS16) derivY, (ImageBorder_S32) border);
} else if( input instanceof GrayS16) {
GradientTwo1.process((GrayS16) input, (GrayS16) derivX, (GrayS16) derivY, (ImageBorder_S32) border);
} else {
throw new IllegalArgumentException("Unknown input image type: "+input.getClass().getSimpleName());
}
break;
default:
throw new IllegalArgumentException("Unknown type: "+type);
}
}
/**
* Computes the hessian from the original input image. Only Sobel and Three supported.
*
* @param type Type of gradient to compute
* @param input Input image
* @param derivXX Output. Derivative XX
* @param derivYY Output. Derivative YY
* @param derivXY Output. Derivative XY
* @param borderType How it should handle borders. null == skip border
* @param Input image type
* @param Output image type
*/
public static
void hessian( DerivativeType type , I input , D derivXX , D derivYY , D derivXY , BorderType borderType ) {
ImageBorder border = BorderType.SKIP == borderType ? null : FactoryImageBorder.single(input, borderType);
switch( type ) {
case SOBEL:
if( input instanceof GrayF32) {
HessianSobel.process((GrayF32) input, (GrayF32) derivXX, (GrayF32) derivYY, (GrayF32) derivXY, (ImageBorder_F32) border);
} else if( input instanceof GrayU8) {
HessianSobel.process((GrayU8) input, (GrayS16) derivXX, (GrayS16) derivYY, (GrayS16) derivXY, (ImageBorder_S32) border);
} else {
throw new IllegalArgumentException("Unknown input image type: "+input.getClass().getSimpleName());
}
break;
case THREE:
if( input instanceof GrayF32) {
HessianThree.process((GrayF32) input, (GrayF32) derivXX, (GrayF32) derivYY, (GrayF32) derivXY, (ImageBorder_F32) border);
} else if( input instanceof GrayU8) {
HessianThree.process((GrayU8) input, (GrayS16) derivXX, (GrayS16) derivYY, (GrayS16) derivXY, (ImageBorder_S32) border);
} else {
throw new IllegalArgumentException("Unknown input image type: "+input.getClass().getSimpleName());
}
break;
default:
throw new IllegalArgumentException("Unsupported derivative type "+type);
}
}
/**
* Computes the hessian from the gradient. Only Prewitt, Sobel and Three supported.
*
* @param type Type of gradient to compute
* @param derivX Input derivative X
* @param derivY Input derivative Y
* @param derivXX Output. Derivative XX
* @param derivYY Output. Derivative YY
* @param derivXY Output. Derivative XY
* @param borderType How it should handle borders. null == skip border
*/
public static
void hessian( DerivativeType type , D derivX , D derivY , D derivXX , D derivYY , D derivXY , BorderType borderType ) {
ImageBorder border = BorderType.SKIP == borderType ? null : FactoryImageBorder.single(derivX, borderType);
switch( type ) {
case PREWITT:
if( derivX instanceof GrayF32) {
HessianFromGradient.hessianPrewitt((GrayF32) derivX, (GrayF32) derivY, (GrayF32) derivXX, (GrayF32) derivYY, (GrayF32) derivXY, (ImageBorder_F32) border);
} else if( derivX instanceof GrayS16) {
HessianFromGradient.hessianPrewitt((GrayS16) derivX, (GrayS16) derivY, (GrayS16) derivXX, (GrayS16) derivYY, (GrayS16) derivXY, (ImageBorder_S32) border);
} else {
throw new IllegalArgumentException("Unknown input image type: "+derivX.getClass().getSimpleName());
}
break;
case SOBEL:
if( derivX instanceof GrayF32) {
HessianFromGradient.hessianSobel((GrayF32) derivX, (GrayF32) derivY, (GrayF32) derivXX, (GrayF32) derivYY, (GrayF32) derivXY, (ImageBorder_F32) border);
} else if( derivX instanceof GrayS16) {
HessianFromGradient.hessianSobel((GrayS16) derivX, (GrayS16) derivY, (GrayS16) derivXX, (GrayS16) derivYY, (GrayS16) derivXY, (ImageBorder_S32) border);
} else {
throw new IllegalArgumentException("Unknown input image type: "+derivX.getClass().getSimpleName());
}
break;
case THREE:
if( derivX instanceof GrayF32) {
HessianFromGradient.hessianThree((GrayF32) derivX, (GrayF32) derivY, (GrayF32) derivXX, (GrayF32) derivYY, (GrayF32) derivXY, (ImageBorder_F32) border);
} else if( derivX instanceof GrayS16) {
HessianFromGradient.hessianThree((GrayS16) derivX, (GrayS16) derivY, (GrayS16) derivXX, (GrayS16) derivYY, (GrayS16) derivXY, (ImageBorder_S32) border);
} else {
throw new IllegalArgumentException("Unknown input image type: "+derivX.getClass().getSimpleName());
}
break;
default:
throw new IllegalArgumentException("Unsupported derivative type "+type);
}
}
/**
* Returns the kernel for finding the X derivative.
* @param type Type of gradient
* @param isInteger integer or floating point kernels
* @return The kernel. Can be 1D or 2D
*/
public static KernelBase lookupKernelX( DerivativeType type , boolean isInteger) {
switch( type ) {
case PREWITT:
return GradientPrewitt.getKernelX(isInteger);
case SOBEL:
return GradientSobel.getKernelX(isInteger);
case THREE:
return GradientThree.getKernelX(isInteger);
case TWO_0:
return GradientTwo0.getKernelX(isInteger);
case TWO_1:
return GradientTwo1.getKernelX(isInteger);
}
throw new IllegalArgumentException("Unknown kernel type: "+type);
}
/**
*
* Convenience function for creating an instance of {@link boofcv.abst.filter.derivative.AnyImageDerivative}.
* This class is an any way to compute any derivative of any order using the specified kernel. It might
* use more memory or be more expensive the specialized code but is easy to use.
*
*
* @param type Type of gradient to use
* @param inputType Type of input image.
* @param derivType Type of derivative image
* @param Image type.
* @param Image derivative type.
* @return AnyImageDerivative
*/
public static
AnyImageDerivative createAnyDerivatives( DerivativeType type , Class inputType , Class derivType ) {
boolean isInteger = !GeneralizedImageOps.isFloatingPoint(inputType);
KernelBase kernel = lookupKernelX(type,isInteger);
if( kernel instanceof Kernel1D )
return new AnyImageDerivative((Kernel1D)kernel,inputType,derivType);
else
return new AnyImageDerivative((Kernel2D)kernel,inputType,derivType);
}
/**
* Creates an instance of {@link AnyImageDerivative} which is intended for use of calculating scale-spaces.
* It uses {@link DerivativeType#THREE} since it does not blur the image. More typical operators, such as Sobel and
* Prewitt, blur the image.
*
* @param inputType Type of input image.
* @param derivType Type of derivative image
* @param Image type.
* @param Image derivative type.
* @return AnyImageDerivative
*/
public static
AnyImageDerivative derivativeForScaleSpace( Class inputType , Class derivType ) {
return createAnyDerivatives(DerivativeType.THREE,inputType,derivType);
}
}
Ads help maintain this website.