001package org.openimaj.demos.sandbox.tldcpp.detector; 002 003import org.openimaj.image.FImage; 004import org.openimaj.image.processing.algorithm.MeanCenter; 005import org.openimaj.image.processing.resize.ResizeFilterFunction; 006import org.openimaj.image.processing.resize.ResizeProcessor; 007import org.openimaj.image.processing.resize.filters.TriangleFilter; 008import org.openimaj.math.geometry.shape.Rectangle; 009 010/** 011 * Defines a intensity normalised patch extracted from an image. Allowances are 012 * made for reuse of patches 013 * 014 * @author Sina Samangooei (ss@ecs.soton.ac.uk) 015 * 016 */ 017public class NormalizedPatch { 018 private final static MeanCenter msp = new MeanCenter(); 019 /** 020 * Normalised patch size 021 */ 022 public static final int TLD_PATCH_SIZE = 15; 023 private static final ResizeFilterFunction filter = TriangleFilter.INSTANCE; 024 025 /** 026 * The slut workspace gets around a little bit. Use the slut workspace but 027 * don't expect it to be yours for long. 028 */ 029 public static final FImage SLUT_WORKSPACE = new FImage(TLD_PATCH_SIZE, TLD_PATCH_SIZE); 030 /** 031 * Is this patch positive, i.e. representative of the object 032 */ 033 public boolean positive; 034 /** 035 * The image to extract this patch from 036 */ 037 public FImage source; 038 /** 039 * The window to extract form the source 040 */ 041 public Rectangle window; 042 /** 043 * The extracted patch, might be null, might be the SLUT_WORKSPACE. 044 */ 045 public FImage normalisedPatch; 046 047 /** 048 * A function which uses 049 * {@link ResizeProcessor#zoom(FImage, Rectangle, FImage, Rectangle, ResizeFilterFunction)} 050 * on a to put {@link NormalizedPatch#window} form 051 * {@link NormalizedPatch#source} into normalisedPatch. 052 * 053 * This is not a convenient function but it allows for very efficient 054 * resize/normalisation process (with minimal new stuff constructed) 055 * 056 * @param holder 057 * @return the holder as a convenience 058 */ 059 protected FImage zoomAndNormaliseTo(FImage holder) { 060 ResizeProcessor.zoom(source, window, holder, holder.getBounds(), filter); 061 return holder.processInplace(msp); 062 } 063 064 /** 065 * calculate the variance, sets the valueImg if it is null 066 * 067 * @return an inefficient way to calculate variance of this window, a new 068 * image is constructed! 069 */ 070 public float calculateVariance() { 071 prepareNormalisedPatch(); 072 final float[][] value = normalisedPatch.pixels; 073 float temp = 0; 074 final int n = normalisedPatch.width * normalisedPatch.height; 075 for (int y = 0; y < normalisedPatch.height; y++) { 076 for (int x = 0; x < normalisedPatch.width; x++) { 077 temp += (value[y][x]) * (value[y][x]); // There are two implied 078 // (- 0)'s here. these 079 // values are MEAN 080 // CENTERED 081 } 082 } 083 return temp / n; 084 } 085 086 /** 087 * for construction of a new normalised patch 088 */ 089 public void prepareNormalisedPatch() { 090 if (this.normalisedPatch == null) { 091 this.normalisedPatch = new FImage(TLD_PATCH_SIZE, TLD_PATCH_SIZE); 092 zoomAndNormaliseTo(normalisedPatch); 093 } 094 } 095}