001/** 002 * Copyright (c) 2011, The University of Southampton and the individual contributors. 003 * All rights reserved. 004 * 005 * Redistribution and use in source and binary forms, with or without modification, 006 * are permitted provided that the following conditions are met: 007 * 008 * * Redistributions of source code must retain the above copyright notice, 009 * this list of conditions and the following disclaimer. 010 * 011 * * Redistributions in binary form must reproduce the above copyright notice, 012 * this list of conditions and the following disclaimer in the documentation 013 * and/or other materials provided with the distribution. 014 * 015 * * Neither the name of the University of Southampton nor the names of its 016 * contributors may be used to endorse or promote products derived from this 017 * software without specific prior written permission. 018 * 019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 020 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 022 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 023 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 026 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 029 */ 030package org.openimaj.image.feature.local.interest; 031 032import org.openimaj.image.FImage; 033import org.openimaj.image.processing.convolution.FImageConvolveSeparable; 034import org.openimaj.image.processor.PixelProcessor; 035 036 037public class QuadratureIPD extends AbstractStructureTensorIPD { 038 public QuadratureIPD(float detectionScale, float integrationScale) { 039 super(detectionScale, integrationScale); 040 } 041 042 @Override 043 public FImage createInterestPointMap() { 044 float s2 = detectionScale * detectionScale; 045 046 int filtsize = (int) Math.max(3,Math.round(5*detectionScale)); 047 048 float [] g = new float[2*filtsize + 1]; 049 float [] f1 = new float[2*filtsize + 1]; 050 float [] f2 = new float[2*filtsize + 1]; 051 float [] mf2 = new float[2*filtsize + 1]; 052 float [] f3 = new float[2*filtsize + 1]; 053 float [] mf3 = new float[2*filtsize + 1]; 054 float [] f4 = new float[2*filtsize + 1]; 055 056 for (int i=0, t=-filtsize; t<=filtsize; t++, i++) { 057 g[i] = (float) (Math.exp(-(t*t)/(2*s2))/Math.sqrt(2*Math.PI*s2)); 058 059 f1[i] = g[i] * ((t*t)/s2-1)/s2; 060 f2[i] = g[i] * t/s2; 061 mf2[i] = -f2[i]; 062 f3[i] = (float) (g[i] * (3.0-2.0/3.0*t*t/s2)*t/Math.sqrt(Math.PI)/Math.sqrt(s2)/s2); 063 mf3[i] = f3[i]; 064 f4[i] = (float) (g[i] * (1.0-2.0/3.0*t*t/s2)/Math.sqrt(Math.PI)/Math.sqrt(s2)); 065 } 066 067 FImage e1 = this.originalImage.process(new FImageConvolveSeparable(f3, g)); 068 FImage e2 = this.originalImage.process(new FImageConvolveSeparable(f4, mf2)); 069 FImage e3 = this.originalImage.process(new FImageConvolveSeparable(f2, f4)); 070 FImage e4 = this.originalImage.process(new FImageConvolveSeparable(g, mf3)); 071 072 FImage gx = e1.addInplace(e3).multiplyInplace(0.75f); 073 FImage gy = e2.addInplace(e4).multiplyInplace(0.75f); 074 075 FImage hxx = this.originalImage.process(new FImageConvolveSeparable(f1, g)); 076 FImage hxy = this.originalImage.process(new FImageConvolveSeparable(f2, mf2)); 077 FImage hyy = this.originalImage.process(new FImageConvolveSeparable(g, f1)); 078 079 FImage b11 = gx.multiply(gx).add(hxx.multiplyInplace(hxx)); 080 FImage b12 = gx.multiply(gy).add(hxy.multiplyInplace(hxy)); 081 FImage b22 = gy.multiply(gy).add(hyy.multiplyInplace(hyy)); 082 083 FImage ebound = b11.add(b22); 084 FImage b11b22 = b11.subtractInplace(b22); 085 FImage eedge = b11b22.multiplyInplace(b11b22).add(b12.multiplyInplace(b12).multiplyInplace(4f)).processInplace(new PixelProcessor<Float>() { 086 @Override 087 public Float processPixel(Float pixel) { 088 return (float) Math.sqrt(pixel); 089 }}); 090 FImage cimg = ebound.subtractInplace(eedge).processInplace(new PixelProcessor<Float>() { 091 @Override 092 public Float processPixel(Float pixel) { 093 return -pixel; 094 }}); 095 096 return cimg; 097 } 098 099 @Override 100 public QuadratureIPD clone() { 101 return (QuadratureIPD) super.clone(); 102 } 103}