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