001package org.openimaj.demos.sandbox.tldcpp.detector; 002 003import org.openimaj.image.FImage; 004 005/** 006 * The variance filter forms the first step of the {@link DetectorCascade#detect(FImage)}. 007 * For each window in the {@link DetectorCascade} a variance is calculated using {@link IntegralImage} 008 * for speed. 009 * 010 * Windows are filtered by whether they contain more variance than minVar which is the variance of 011 * the original bounding box being tracked 012 * @author Sina Samangooei (ss@ecs.soton.ac.uk) 013 * 014 */ 015public class VarianceFilter { 016 017 private IntegralImage integralImg; 018 private IntegralImage integralImg_squared; 019 020 /** 021 * whether the variance filter is enabled 022 */ 023 public boolean enabled; 024 int[][] windowOffsets; 025 026 /** 027 * the results of the variance check are saved to this results instance 028 */ 029 public DetectionResult detectionResult; 030 031 /** 032 * the minimum variance (variance of the original bounding box) 033 */ 034 public float minVar; 035 036 /** 037 * enabled with a 0 minvar (most permissive) 038 */ 039 public VarianceFilter() { 040 enabled = true; 041 minVar = 0; 042 integralImg = null; 043 integralImg_squared = null; 044 } 045 046 private double calcVariance(int winIndex) { 047 int offIndex = DetectorCascade.TLD_WINDOW_OFFSET_SIZE * winIndex; 048 double[][] ii1 = integralImg.data; 049 double[][] ii2 = integralImg_squared.data; 050 int[][] off = this.windowOffsets; 051 int[] tlXY = off[offIndex + 0]; 052 int[] blXY = off[offIndex + 1]; 053 int[] trXY = off[offIndex + 2]; 054 int[] brXY = off[offIndex + 3]; 055 int[] area = off[offIndex + 5]; 056 double mX = (ii1[brXY[1]][brXY[0]] - ii1[trXY[1]][trXY[0]] - ii1[blXY[1]][blXY[0]] + ii1[tlXY[1]][tlXY[0]]) / (float) area[0]; //Sum of Area divided by area 057 double mX2 = ( 058 ii2[brXY[1]][brXY[0]] - 059 ii2[trXY[1]][trXY[0]] - 060 ii2[blXY[1]][blXY[0]] + 061 ii2[tlXY[1]][tlXY[0]] 062 ) / (float) area[0]; 063 return mX2 - mX*mX; 064 } 065 066 /** 067 * calculates the integralImage and the integral(image*image) (these are used to calculate variance) 068 * @param img 069 */ 070 public void nextIteration(FImage img) { 071 if(!enabled) return; 072 integralImg = new IntegralImage(); 073 integralImg.calcIntImg(img,false); 074 075 integralImg_squared = new IntegralImage(); 076 integralImg_squared.calcIntImg(img, true); 077 } 078 079 080 081 /** 082 * @param windowIndex 083 * @return whether the ith window has a variance higher than minvar 084 */ 085 public boolean filter(int windowIndex) { 086 if(!enabled) return true; 087 088 float bboxvar = (float) calcVariance(windowIndex); 089 090 detectionResult.variances[windowIndex] = bboxvar; 091 092 if(bboxvar < minVar) { 093 return false; 094 } 095 096 return true; 097 } 098}