public static <T extends ImageBase<T>, K extends Kernel2D>
	void convolveNormalized(K kernel, T input, T output ) {
		switch (input.getImageType().getFamily()) {
			case GRAY: {
				if (input instanceof GrayF32) {
					ConvolveImageNormalized.convolve((Kernel2D_F32) kernel, (GrayF32) input, (GrayF32) output);
				} else if (input instanceof GrayF64) {
					ConvolveImageNormalized.convolve((Kernel2D_F64) kernel, (GrayF64) input, (GrayF64) output);
				} else if (input instanceof GrayU8) {
					ConvolveImageNormalized.convolve((Kernel2D_S32) kernel, (GrayU8) input, (GrayI8) output);
				} else if (input instanceof GrayS16) {
					ConvolveImageNormalized.convolve((Kernel2D_S32) kernel, (GrayS16) input, (GrayI16) output);
				} else {
					throw new IllegalArgumentException("Unknown image type: " + input.getClass().getName());
				}
			} break;

			case INTERLEAVED: {
				if (input instanceof InterleavedF32) {
					ConvolveImageNormalized.convolve((Kernel2D_F32) kernel, (InterleavedF32) input, (InterleavedF32) output);
				} else if (input instanceof InterleavedF64) {
					ConvolveImageNormalized.convolve((Kernel2D_F64) kernel, (InterleavedF64) input, (InterleavedF64) output);
				} else if (input instanceof InterleavedU8) {
					ConvolveImageNormalized.convolve((Kernel2D_S32) kernel, (InterleavedU8) input, (InterleavedI8) output);
				} else if (input instanceof InterleavedS16) {
					ConvolveImageNormalized.convolve((Kernel2D_S32) kernel, (InterleavedS16) input, (InterleavedI16) output);
				} else {
					throw new IllegalArgumentException("Unknown image type: " + input.getClass().getName());
				}
			} break;

			case PLANAR: {
				Planar inp = (Planar) input;
				Planar outp = (Planar) output;

				for (int i = 0; i < inp.getNumBands(); i++) {
					convolveNormalized(kernel, inp.getBand(i), outp.getBand(i));
				}
			} break;

			default:
				throw new IllegalArgumentException("Unknown image family");
		}
	}
public static < T extends ImageBase < T > , K extends Kernel2D > void convolveNormalized ( K kernel , T input , T output ) { switch ( input . getImageType ( ) . getFamily ( ) ) { case GRAY : { if ( input instanceof GrayF32 ) { ConvolveImageNormalized . convolve ( ( Kernel2D_F32 ) kernel , ( GrayF32 ) input , ( GrayF32 ) output ) ; } else if ( input instanceof GrayF64 ) { ConvolveImageNormalized . convolve ( ( Kernel2D_F64 ) kernel , ( GrayF64 ) input , ( GrayF64 ) output ) ; } else if ( input instanceof GrayU8 ) { ConvolveImageNormalized . convolve ( ( Kernel2D_S32 ) kernel , ( GrayU8 ) input , ( GrayI8 ) output ) ; } else if ( input instanceof GrayS16 ) { ConvolveImageNormalized . convolve ( ( Kernel2D_S32 ) kernel , ( GrayS16 ) input , ( GrayI16 ) output ) ; } else { throw new IllegalArgumentException ( "Unknown image type: " + input . getClass ( ) . getName ( ) ) ; } } break ; case INTERLEAVED : { if ( input instanceof InterleavedF32 ) { ConvolveImageNormalized . convolve ( ( Kernel2D_F32 ) kernel , ( InterleavedF32 ) input , ( InterleavedF32 ) output ) ; } else if ( input instanceof InterleavedF64 ) { ConvolveImageNormalized . convolve ( ( Kernel2D_F64 ) kernel , ( InterleavedF64 ) input , ( InterleavedF64 ) output ) ; } else if ( input instanceof InterleavedU8 ) { ConvolveImageNormalized . convolve ( ( Kernel2D_S32 ) kernel , ( InterleavedU8 ) input , ( InterleavedI8 ) output ) ; } else if ( input instanceof InterleavedS16 ) { ConvolveImageNormalized . convolve ( ( Kernel2D_S32 ) kernel , ( InterleavedS16 ) input , ( InterleavedI16 ) output ) ; } else { throw new IllegalArgumentException ( "Unknown image type: " + input . getClass ( ) . getName ( ) ) ; } } break ; case PLANAR : { Planar inp = ( Planar ) input ; Planar outp = ( Planar ) output ; for ( int i = 0 ; i < inp . getNumBands ( ) ; i ++ ) { convolveNormalized ( kernel , inp . getBand ( i ) , outp . getBand ( i ) ) ; } } break ; default : throw new IllegalArgumentException ( "Unknown image family" ) ; } }
Performs a 2D convolution across the image while re-normalizing the kernel depending on its
overlap with the image.

@param input	 The original image. Not modified.
@param output	 Where the resulting image is written to. Modified.
@param kernel The kernel that is being convolved. Not modified.