Accord.Imaging.Filters.SauvolaThreshold.ProcessFilter C# (CSharp) Method

ProcessFilter() protected method

Process the filter on the specified image.
protected ProcessFilter ( UnmanagedImage sourceData, UnmanagedImage destinationData ) : void
sourceData UnmanagedImage Source image data.
destinationData UnmanagedImage Destination image data.
return void
        protected override unsafe void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData)
        {
            int width = sourceData.Width;
            int height = sourceData.Height;
            int size = radius * 2;

            int pixelSize = System.Drawing.Image.GetPixelFormatSize(sourceData.PixelFormat) / 8;

            int srcStride = sourceData.Stride;
            int dstStride = destinationData.Stride;

            int srcOffset = srcStride - width * pixelSize;
            int dstOffset = dstStride - width * pixelSize;

            byte* src = (byte*)sourceData.ImageData.ToPointer();
            byte* dst = (byte*)destinationData.ImageData.ToPointer();


            // do the processing job
            if (sourceData.PixelFormat == PixelFormat.Format8bppIndexed)
            {
                // for each line
                for (int y = 0; y < height; y++)
                {
                    // for each pixel
                    for (int x = 0; x < width; x++, src++, dst++)
                    {
                        long sum = 0;
                        int count = 0;

                        for (int i = 0; i < size; i++)
                        {
                            int ir = i - radius;
                            int t = y + ir;

                            if (t < 0) 
                                continue;
                            if (t >= height) 
                                break;

                            for (int j = 0; j < size; j++)
                            {
                                int jr = j - radius;
                                t = x + jr;

                                if (t < 0) 
                                    continue;
                                if (t >= width) 
                                    continue;

                                sum += src[ir * srcStride + jr];
                                count++;
                            }
                        }

                        double mean = sum / (double)count;
                        double variance = 0;

                        for (int i = 0; i < size; i++)
                        {
                            int ir = i - radius;
                            int t = y + ir;

                            if (t < 0) 
                                continue;
                            if (t >= height) 
                                break;

                            for (int j = 0; j < size; j++)
                            {
                                int jr = j - radius;
                                t = x + jr;

                                if (t < 0) 
                                    continue;
                                if (t >= width) 
                                    continue;

                                byte val = src[ir * srcStride + jr];
                                variance += (val - mean) * (val - mean);
                            }
                        }

                        variance /= count - 1;

                        double cut = mean * (1.0 + k * ((Math.Sqrt(variance) / r) - 1.0));

                        *dst = (*src > cut) ? (byte)255 : (byte)0;
                    }
                    src += srcOffset;
                    dst += dstOffset;
                }
            }
            else
            {
                // for each line
                for (int y = 0; y < height; y++)
                {
                    // for each pixel
                    for (int x = 0; x < width; x++, src += pixelSize, dst += pixelSize)
                    {
                        long sumR = 0;
                        long sumG = 0;
                        long sumB = 0;
                        int count = 0;

                        for (int i = 0; i < size; i++)
                        {
                            int ir = i - radius;
                            int t = y + ir;

                            if (t < 0) 
                                continue;
                            if (t >= height) 
                                break;

                            for (int j = 0; j < size; j++)
                            {
                                int jr = j - radius;
                                t = x + jr;

                                if (t < 0) 
                                    continue;
                                if (t >= width) 
                                    continue;

                                byte* p = &src[ir * srcStride + jr * pixelSize];

                                count++;

                                sumR += p[RGB.R];
                                sumG += p[RGB.G];
                                sumB += p[RGB.B];
                            }
                        }

                        double meanR = sumR / (double)count;
                        double meanG = sumG / (double)count;
                        double meanB = sumB / (double)count;

                        double varR = 0;
                        double varG = 0;
                        double varB = 0;

                        for (int i = 0; i < size; i++)
                        {
                            int ir = i - radius;
                            int t = y + ir;

                            if (t < 0) 
                                continue;
                            if (t >= height) 
                                break;

                            // for each kernel column
                            for (int j = 0; j < size; j++)
                            {
                                int jr = j - radius;
                                t = x + jr;

                                if (t < 0) 
                                    continue;
                                if (t >= width) 
                                    continue;

                                byte* p = &src[ir * srcStride + jr * pixelSize];

                                varR += (p[RGB.R] - meanR) * (p[RGB.R] - meanR);
                                varG += (p[RGB.G] - meanG) * (p[RGB.G] - meanG);
                                varB += (p[RGB.B] - meanB) * (p[RGB.B] - meanB);
                            }
                        }

                        varR /= count - 1;
                        varG /= count - 1;
                        varB /= count - 1;

                        double cutR = meanR * (1.0 + k * ((Math.Sqrt(varR) / r) - 1.0));
                        double cutG = meanG * (1.0 + k * ((Math.Sqrt(varG) / r) - 1.0));
                        double cutB = meanB * (1.0 + k * ((Math.Sqrt(varB) / r) - 1.0));

                        dst[RGB.R] = (src[RGB.R] > cutR) ? (byte)255 : (byte)0;
                        dst[RGB.G] = (src[RGB.G] > cutG) ? (byte)255 : (byte)0;
                        dst[RGB.B] = (src[RGB.B] > cutB) ? (byte)255 : (byte)0;

                        // take care of alpha channel
                        if (pixelSize == 4)
                            dst[RGB.A] = src[RGB.A];
                    }
                    src += srcOffset;
                    dst += dstOffset;
                }
            }
        }