// Path: cv4j/src/main/java/com/cv4j/core/datamodel/FloatProcessor.java
// public class FloatProcessor implements ImageProcessor {
// 
//     private int width;
//     private int height;
//     private float[] GRAY;
//     private ImageData image;
// 
//     public FloatProcessor(float[] data, int width, int height) {
//         this.width = width;
//         this.height = height;
//         this.GRAY = data;
//     }
// 
//     protected void setCallBack(ImageData data) {
//         this.image = data;
//     }
// 
//     @Override
//     public int getWidth() {
//         return width;
//     }
// 
//     @Override
//     public int getHeight() {
//         return height;
//     }
// 
//     @Override
//     public int getChannels() {
//         return 1;
//     }
// 
//     @Override
//     public void getPixel(int row, int col, byte[] rgb) {
// 
//     }
// 
//     @Override
//     public int[] getPixels() {
//         return new int[0];
//     }
// 
//     public void getPixel(int row, int col, float[] rgb) {
//         int index = row*width + col;
//         if(rgb != null && rgb.length == 1) {
//             rgb[0] = GRAY[index];
//         }
//     }
// 
//     public float[] getGray() {
//         return GRAY;
//     }
// 
//     public void putGray(float[] gray) {
//         System.arraycopy(gray, 0, GRAY, 0, gray.length);
//     }
// 
//     public ImageData getImage() {
// 
//         return this.image;
//     }
// 
//     @Override
//     public float[] toFloat(int index) {
//         return GRAY;
//     }
// 
//     @Override
//     public int[] toInt(int index) {
//         int[] data = new int[GRAY.length];
//         for(int i=0; i<data.length; i++)
//             data[i] = (int)GRAY[i];
//         return data;
//     }
// 
//     @Override
//     public byte[] toByte(int index) {
//         throw new IllegalStateException("Invalid data type, not support this type!!!");
//     }
// 	
// 	public void addArray(float[] fa) {
//     	for(int i=0; i<fa.length; i++) {
//     		GRAY[i] += fa[i];
//     	}
//     }
// 
// }


import java.util.Arrays;
import com.cv4j.core.datamodel.FloatProcessor;
import com.cv4j.core.datamodel.ImageProcessor;
import com.cv4j.core.datamodel.IntIntegralImage;
package com.cv4j.core.tpl;



public class TemplateMatch2 {
    public static final int TM_SQDIFF_NORMED = 2;
    public static final int TM_CCORR_NORMED = 4;
    public static final int TM_CCOEFF_NORMED = 6;
    
    private float[] sqrt_tpl;
    private void initParams(ImageProcessor tpl) {
    	int chs = tpl.getChannels();
        sqrt_tpl = new float[chs];
        Arrays.fill(sqrt_tpl, 0);
        int r=0;
        for(int c=0; c<chs; c++) {
        	byte[] R = tpl.toByte(c);
        	for(int i=0; i<R.length; i++) {
        		r = R[i]&0xff;
        		sqrt_tpl[c] += r*r;
        	}        	
        }
    }
    
// Path: cv4j/src/main/java/com/cv4j/core/datamodel/FloatProcessor.java
// public class FloatProcessor implements ImageProcessor {
// 
//     private int width;
//     private int height;
//     private float[] GRAY;
//     private ImageData image;
// 
//     public FloatProcessor(float[] data, int width, int height) {
//         this.width = width;
//         this.height = height;
//         this.GRAY = data;
//     }
// 
//     protected void setCallBack(ImageData data) {
//         this.image = data;
//     }
// 
//     @Override
//     public int getWidth() {
//         return width;
//     }
// 
//     @Override
//     public int getHeight() {
//         return height;
//     }
// 
//     @Override
//     public int getChannels() {
//         return 1;
//     }
// 
//     @Override
//     public void getPixel(int row, int col, byte[] rgb) {
// 
//     }
// 
//     @Override
//     public int[] getPixels() {
//         return new int[0];
//     }
// 
//     public void getPixel(int row, int col, float[] rgb) {
//         int index = row*width + col;
//         if(rgb != null && rgb.length == 1) {
//             rgb[0] = GRAY[index];
//         }
//     }
// 
//     public float[] getGray() {
//         return GRAY;
//     }
// 
//     public void putGray(float[] gray) {
//         System.arraycopy(gray, 0, GRAY, 0, gray.length);
//     }
// 
//     public ImageData getImage() {
// 
//         return this.image;
//     }
// 
//     @Override
//     public float[] toFloat(int index) {
//         return GRAY;
//     }
// 
//     @Override
//     public int[] toInt(int index) {
//         int[] data = new int[GRAY.length];
//         for(int i=0; i<data.length; i++)
//             data[i] = (int)GRAY[i];
//         return data;
//     }
// 
//     @Override
//     public byte[] toByte(int index) {
//         throw new IllegalStateException("Invalid data type, not support this type!!!");
//     }
// 	
// 	public void addArray(float[] fa) {
//     	for(int i=0; i<fa.length; i++) {
//     		GRAY[i] += fa[i];
//     	}
//     }
// 
// }


// Path: cv4j/src/main/java/com/cv4j/core/tpl/TemplateMatch2.java
import java.util.Arrays;
import com.cv4j.core.datamodel.FloatProcessor;
import com.cv4j.core.datamodel.ImageProcessor;
import com.cv4j.core.datamodel.IntIntegralImage;

package com.cv4j.core.tpl;



public class TemplateMatch2 {
    public static final int TM_SQDIFF_NORMED = 2;
    public static final int TM_CCORR_NORMED = 4;
    public static final int TM_CCOEFF_NORMED = 6;
    
    private float[] sqrt_tpl;
    private void initParams(ImageProcessor tpl) {
    	int chs = tpl.getChannels();
        sqrt_tpl = new float[chs];
        Arrays.fill(sqrt_tpl, 0);
        int r=0;
        for(int c=0; c<chs; c++) {
        	byte[] R = tpl.toByte(c);
        	for(int i=0; i<R.length; i++) {
        		r = R[i]&0xff;
        		sqrt_tpl[c] += r*r;
        	}        	
        }
    }
    
    public FloatProcessor match(ImageProcessor target, ImageProcessor tpl, int method) {