/// <summary> /// Slides a window with a subwindow with sizes specified by the input parameters over the frame. The average depth in the windows are compared and if above a certain threshold considered to be head candidates. /// </summary> private List <int> SlideWindow(int outerWindowWidth, int innerWindowWidth, float windowDifferenceThreshold) { var candidates = new List <int>(); int marginInnerWindow = (outerWindowWidth - innerWindowWidth) / 2; int innerWindowArea = innerWindowWidth * innerWindowWidth; for (int i = 0; i < GlobVar.ScaledFrameHeight - innerWindowWidth; i += 2) { for (int j = 0; j < GlobVar.ScaledFrameWidth - innerWindowWidth; j += 2) { int outerWindowHeight = outerWindowWidth; int outerWindowTempWidth = outerWindowWidth; int iOuter = i - marginInnerWindow; int jOuter = j - marginInnerWindow; if (iOuter < 0) { outerWindowHeight += iOuter; iOuter = 0; } if (jOuter < 0) { outerWindowTempWidth += jOuter; jOuter = 0; } if (iOuter + outerWindowWidth > GlobVar.ScaledFrameHeight - 1) { outerWindowHeight += iOuter + outerWindowWidth - GlobVar.ScaledFrameHeight - 1; iOuter = GlobVar.ScaledFrameHeight - 1 - outerWindowHeight; } if (jOuter + outerWindowWidth > GlobVar.ScaledFrameWidth - 1) { outerWindowTempWidth += jOuter + outerWindowWidth - GlobVar.ScaledFrameWidth - 1; jOuter = GlobVar.ScaledFrameWidth - 1 - outerWindowTempWidth; } int innerIndexA = GlobUtils.GetIndex(j, i); int innerIndexB = GlobUtils.GetIndex(j + innerWindowWidth, i); int innerIndexC = GlobUtils.GetIndex(j, i + innerWindowWidth); int innerIndexD = GlobUtils.GetIndex(j + innerWindowWidth, i + innerWindowWidth); int outerIndexA = GlobUtils.GetIndex(jOuter, iOuter); int outerIndexB = GlobUtils.GetIndex(jOuter + outerWindowTempWidth, iOuter); int outerIndexC = GlobUtils.GetIndex(jOuter, iOuter + outerWindowHeight); int outerIndexD = GlobUtils.GetIndex(jOuter + outerWindowTempWidth, iOuter + outerWindowHeight); int outerWindowArea = GlobUtils.CalculateRectangleAreaFromIndexes(outerIndexA, outerIndexB, outerIndexC); float sumInnerWindow = (_integralImage[innerIndexA] + _integralImage[innerIndexD] - _integralImage[innerIndexB] - _integralImage[innerIndexC]); float sumOuterWindow = (_integralImage[outerIndexA] + _integralImage[outerIndexD] - _integralImage[outerIndexB] - _integralImage[outerIndexC]); float averageInnerWindow = sumInnerWindow / innerWindowArea; if (averageInnerWindow > GlobVar.MaxSensingDepth - Thresholds.HaarDetectionHeightHeadMin) { continue; } float averageOuterWindow = (sumOuterWindow - sumInnerWindow) / (outerWindowArea - innerWindowArea); if ((averageOuterWindow - averageInnerWindow) > windowDifferenceThreshold) { int candidate = GlobUtils.GetHighestValidPointIndexInRectangle(innerIndexB, innerIndexC); candidates.Add(candidate); if (Logger.ShowHaarInnerRects) { GraphicsUtils.DrawRectangle(new IndexRectangle(innerIndexA, innerIndexB, innerIndexC)); } if (Logger.ShowHaarOuterRects) { GraphicsUtils.DrawRectangle(new IndexRectangle(outerIndexA, outerIndexB, outerIndexC)); } } } } return(candidates); }