001/******************************************************************************* 002 * This software is provided as a supplement to the authors' textbooks on digital 003 * image processing published by Springer-Verlag in various languages and editions. 004 * Permission to use and distribute this software is granted under the BSD 2-Clause 005 * "Simplified" License (see http://opensource.org/licenses/BSD-2-Clause). 006 * Copyright (c) 2006-2016 Wilhelm Burger, Mark J. Burge. All rights reserved. 007 * Visit http://imagingbook.com for additional details. 008 *******************************************************************************/ 009 010package imagingbook.pub.matching; 011import ij.process.ByteProcessor; 012import imagingbook.pub.matching.DistanceTransform.Norm; 013 014import java.awt.Point; 015 016/** 017 * This class performs chamfer matching on binary images. 018 * @author W. Burger 019 * @version 2014-04-20 020 */ 021public class ChamferMatcher { 022 023 private final ByteProcessor I; 024 private final int MI, NI; 025 private final float[][] D; // distance transform of I 026 027 public ChamferMatcher(ByteProcessor I) { 028 this(I, Norm.L2); 029 } 030 031 public ChamferMatcher(ByteProcessor I, Norm norm) { 032 this.I = I; 033 this.MI = this.I.getWidth(); 034 this.NI = this.I.getHeight(); 035 this.D = (new DistanceTransform(I, norm)).getDistanceMap(); 036 } 037 038 public float[][] getMatch(ByteProcessor R) { 039 final int MR = R.getWidth(); 040 final int NR = R.getHeight(); 041 final int[][] Ra = R.getIntArray(); 042 float[][] Q = new float[MI - MR + 1][NI - NR + 1]; 043 for (int r = 0; r <= MI - MR; r++) { 044 for (int s = 0; s <= NI - NR; s++) { 045 float q = getMatchValue(Ra, r, s); 046 Q[r][s] = q; 047 } 048 } 049 return Q; 050 } 051 052 private float getMatchValue(int[][] R, int r, int s) { 053 float q = 0.0f; 054 for (int i = 0; i < R.length; i++) { 055 for (int j = 0; j < R[i].length; j++) { 056 if (R[i][j] > 0) { // foreground pixel in reference image 057 q = q + D[r + i][s + j]; 058 } 059 } 060 } 061 return q; 062 } 063 064 public float[][] getMatch(Point[] points, int width, int height) { 065 float[][] Q = new float[width][height]; 066 for (int r = 0; r <= width; r++) { 067 for (int s = 0; s <= height; s++) { 068 float q = getMatchValue(points, r, s); 069 Q[r][s] = q; 070 } 071 } 072 return Q; 073 } 074 075 private float getMatchValue(Point[] points, int r, int s) { 076 float q = 0.0f; 077 for (Point p : points) { 078 final int u = r + p.x; 079 final int v = s + p.y; 080 if (0 <= u && u < MI && 0 <= v && v < NI) { 081 q = q + D[u][v]; 082 } 083 } 084 return q; 085 } 086 087}