protected override void ProcessFilter(UnmanagedImage image, UnmanagedImage overlay)
{
BaseResizeFilter resizer = new ResizeNearestNeighbor(
(int)(image.Width * _subSamplingRatio),
(int)(image.Height * _subSamplingRatio));
UnmanagedImage imageSub = resizer.Apply(image);
UnmanagedImage overlaySub = resizer.Apply(overlay);
byte kernelSizeSub = (byte)(_kernelSize * _subSamplingRatio);
UnmanagedImage imageBorder = new FastBoxBlur(kernelSizeSub, kernelSizeSub).Apply(
GetFilledImage(imageSub.Width, imageSub.Height, imageSub.PixelFormat, Color.White));
UnmanagedImage imageMean = new FastBoxBlur(kernelSizeSub, kernelSizeSub).Apply(imageSub);
new Divide(imageBorder).ApplyInPlace(imageMean);
UnmanagedImage overlayMean = new FastBoxBlur(kernelSizeSub, kernelSizeSub).Apply(overlaySub);
new Divide(imageBorder).ApplyInPlace(overlayMean);
UnmanagedImage mulMean = new Multiply(overlaySub).Apply(imageSub);
overlaySub.Dispose();
new FastBoxBlur(kernelSizeSub, kernelSizeSub).ApplyInPlace(mulMean);
new Divide(imageBorder).ApplyInPlace(mulMean);
//This is the covariance of (image, overlay) in each local patch.
UnmanagedImage mulCov = new Subtract(new Multiply(overlayMean).Apply(imageMean)).Apply(mulMean);
mulMean.Dispose();
UnmanagedImage imageMean2 = new Multiply(imageSub).Apply(imageSub);
imageSub.Dispose();
new FastBoxBlur(kernelSizeSub, kernelSizeSub).ApplyInPlace(imageMean2);
new Divide(imageBorder).ApplyInPlace(imageMean2);
UnmanagedImage imageVar = new Subtract(new Multiply(imageMean).Apply(imageMean)).Apply(imageMean2);
imageMean2.Dispose();
byte cc = (byte)(255 * _epsilon);
var imageEpsilon = GetFilledImage(
imageVar.Width, imageVar.Height, imageVar.PixelFormat, Color.FromArgb(cc, cc, cc));
new Add(imageEpsilon).ApplyInPlace(imageVar);
imageEpsilon.Dispose();
UnmanagedImage a = new Divide(imageVar).Apply(mulCov);
imageVar.Dispose();
mulCov.Dispose();
UnmanagedImage b = new Subtract(new Multiply(imageMean).Apply(a)).Apply(overlayMean);
imageMean.Dispose();
overlayMean.Dispose();
UnmanagedImage aMean = new Divide(imageBorder).Apply(new FastBoxBlur(kernelSizeSub, kernelSizeSub).Apply(a));
UnmanagedImage bMean = new Divide(imageBorder).Apply(new FastBoxBlur(kernelSizeSub, kernelSizeSub).Apply(b));
imageBorder.Dispose();
a.Dispose();
b.Dispose();
resizer = new ResizeBilinear(image.Width, image.Height);
aMean = resizer.Apply(aMean);
bMean = resizer.Apply(bMean);
new Multiply(aMean).ApplyInPlace(image);
aMean.Dispose();
new Add(bMean).ApplyInPlace(image);
bMean.Dispose();
}