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;
}