Adaptive Parallel Threshold

public static double VariableThresholdingLocalPropertiesParallel(Bitmap image, double a, double b)
{
    int w = image.Width;
    int h = image.Height;

    BitmapData image_data = image.LockBits(
        new Rectangle(0, 0, w, h),
        ImageLockMode.ReadOnly,
        PixelFormat.Format24bppRgb);

    int bytes = image_data.Stride * image_data.Height;
    byte[] buffer = new byte[bytes];

    Marshal.Copy(image_data.Scan0, buffer, 0, bytes);
    image.UnlockBits(image_data);

    // Get global mean - this works only for grayscale images
    double mg = 0;
    for (int i = 0; i < bytes; i += 3)
    {
        mg += buffer[i];
    }
    mg /= (w * h);

    // ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ ์ค€๋น„: ์ž„๊ณ„๊ฐ’์˜ ๋ˆ„์  ํ•ฉ๊ณผ ํ”ฝ์…€ ์ˆ˜
    double cumulativeThreshold = 0;
    int count = 0;
    object lockObject = new object(); // ๋™๊ธฐํ™” ๊ฐ์ฒด

    Parallel.For(1, w - 1, x =>
    {
        double localCumulativeThreshold = 0; // ๊ฐ ์Šค๋ ˆ๋“œ์—์„œ ์ž„๊ณ„๊ฐ’ ๋ˆ„์  ํ•ฉ์‚ฐ
        int localCount = 0; // ๊ฐ ์Šค๋ ˆ๋“œ์—์„œ ์ฒ˜๋ฆฌํ•œ ํ”ฝ์…€ ์ˆ˜

        for (int y = 1; y < h - 1; y++)
        {
            int position = x * 3 + y * image_data.Stride;
            double mean = 0;
            double std = 0;

            // 3x3 ์ฃผ๋ณ€ ํ”ฝ์…€์˜ ํ‰๊ท ๊ณผ ํ‘œ์ค€ ํŽธ์ฐจ ๊ณ„์‚ฐ
            for (int i = -1; i <= 1; i++)
            {
                for (int j = -1; j <= 1; j++)
                {
                    int nposition = position + i * 3 + j * image_data.Stride;
                    byte pixelValue = buffer[nposition];
                    mean += pixelValue;
                    std += pixelValue * pixelValue;
                }
            }

            mean /= 9.0;
            std = Math.Sqrt(std / 9.0 - mean * mean);

            // ์ž„๊ณ„๊ฐ’ ๊ณ„์‚ฐ
            double threshold = a * std + b * mg;
            localCumulativeThreshold += threshold;
            localCount++;
        }

        // ๋ˆ„์ ๋œ ๊ฒฐ๊ณผ๋ฅผ ๋ฉ”์ธ ๋ณ€์ˆ˜์— ๋ณ‘ํ•ฉ
        lock (lockObject)
        {
            cumulativeThreshold += localCumulativeThreshold;
            count += localCount;
        }
    });

    // ๋ชจ๋“  ํ”ฝ์…€์˜ ํ‰๊ท  ์ž„๊ณ„๊ฐ’์„ ๋ฐ˜ํ™˜
    return cumulativeThreshold / count;
}