package com.github.axet.lookup.proc;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.github.axet.lookup.Lookup.NotFound;
import com.github.axet.lookup.common.GFirst;
import com.github.axet.lookup.common.GPoint;
import com.github.axet.lookup.common.ImageBinary;
import com.github.axet.lookup.common.ImageBinaryChannel;
import com.github.axet.lookup.common.ImageBinaryRGB;
import com.github.axet.lookup.common.ImageMultiplySum;
/**
*
* http://www.fmwconcepts.com/imagemagick/similar/index.php
*
* 1) mean && stddev
*
* 2) image1(x,y) - mean1 && image2(x,y) - mean2
*
* 3) [3] = (image1(x,y) - mean)(x,y) * (image2(x,y) - mean)(x,y)
*
* 4) [4] = mean([3])
*
* 5) [4] / (stddev1 * stddev2)
*
* Normalized cross correlation algorithm
*
* @author axet
*
*/
public class NCC {
static public GPoint lookup(BufferedImage i, BufferedImage t, float m) {
List<GPoint> list = lookupAll(i, t, m);
if (list.size() == 0)
throw new NotFound();
Collections.sort(list, new GFirst());
return list.get(0);
}
static public List<GPoint> lookupAll(BufferedImage i, BufferedImage t, float m) {
ImageBinaryRGB imageBinary = new ImageBinaryRGB(i);
ImageBinaryRGB templateBinary = new ImageBinaryRGB(t);
return lookupAll(imageBinary, templateBinary, m);
}
static public GPoint lookup(ImageBinary image, ImageBinary template, float m) {
List<GPoint> list = lookupAll(image, template, m);
if (list.size() == 0)
throw new NotFound();
Collections.sort(list, new GFirst());
return list.get(0);
}
static public List<GPoint> lookupAll(ImageBinary image, ImageBinary template, float m) {
return lookupAll(image, 0, 0, image.getWidth() - 1, image.getHeight() - 1, template, m);
}
static public GPoint lookup(ImageBinary image, int x1, int y1, int x2, int y2, ImageBinary template, float m) {
List<GPoint> list = lookupAll(image, x1, y1, x2, y2, template, m);
if (list.size() == 0)
throw new NotFound();
Collections.sort(list, new GFirst());
return list.get(0);
}
static public List<GPoint> lookupAll(ImageBinary image, int x1, int y1, int x2, int y2, ImageBinary template,
float m) {
List<GPoint> list = new ArrayList<GPoint>();
for (int x = x1; x <= x2 - template.getWidth() + 1; x++) {
for (int y = y1; y <= y2 - template.getHeight() + 1; y++) {
GPoint g = lookup(image, template, x, y, m);
if (g != null)
list.add(g);
}
}
return list;
}
static double numerator(ImageBinaryChannel image, ImageBinaryChannel template, int xx, int yy) {
ImageMultiplySum m = new ImageMultiplySum(image.zeroMean, xx, yy, template.zeroMean);
return m.sum;
}
static double denominator(ImageBinaryChannel image, ImageBinaryChannel template, int xx, int yy) {
double di = image.dev2n(xx, yy, xx + template.getWidth() - 1, yy + template.getHeight() - 1);
double dt = template.dev2n();
return Math.sqrt(di * dt);
}
static public GPoint lookup(ImageBinary image, ImageBinary template, int x, int y, float m) {
List<ImageBinaryChannel> ci = image.getChannels();
List<ImageBinaryChannel> ct = template.getChannels();
int ii = Math.min(ci.size(), ct.size());
double g = Double.MAX_VALUE;
for (int i = 0; i < ii; i++) {
double gg = gamma(ci.get(i), ct.get(i), x, y);
if (gg < m)
return null;
g = Math.min(g, gg);
}
return new GPoint(x, y, g);
}
static public double gamma(ImageBinary image, ImageBinary template, int x, int y) {
List<ImageBinaryChannel> ci = image.getChannels();
List<ImageBinaryChannel> ct = template.getChannels();
int ii = Math.min(ci.size(), ct.size());
double g = 0;
for (int i = 0; i < ii; i++) {
g += gamma(ci.get(i), ct.get(i), x, y);
}
g /= ii;
return g;
}
static public double gammaMin(ImageBinary image, ImageBinary template, int x, int y) {
List<ImageBinaryChannel> ci = image.getChannels();
List<ImageBinaryChannel> ct = template.getChannels();
int ii = Math.min(ci.size(), ct.size());
double g = Double.MAX_VALUE;
for (int i = 0; i < ii; i++) {
g = Math.min(g, gamma(ci.get(i), ct.get(i), x, y));
}
return g;
}
static public double gamma(ImageBinaryChannel image, ImageBinaryChannel template, int xx, int yy) {
double d = denominator(image, template, xx, yy);
if (d == 0)
return -1;
double n = numerator(image, template, xx, yy);
return (n / d);
}
}