در ادامه آموزشهای پردازش تصویر کدگیت این قسمت به معرفی فیلتر میانگین در سی شارپ (Mean Filter) میپردازیم. نخست فیلتر میانگین و نحوه کار آن را توضیح داده و در ادامه به پیاده سازی آن در زیان برنامهنویسی سی شارپ میپردازیم. پیشنهاد میکنیم قبل از مطالعه این آموزش، پیشنیازهای زیر را مطالعه کنید:
همسایه یک پیکسل در تصاویر
همانطور که در آموزش گذشته گفته شد تصاویر از پیکسلها تشکیل شده و نحوه نمایش آنها به صورت آرایه دو بعدی است(البته تصاویر RGB سه آرایه دو بعدی داریم!). به تصویر زیر دقت کنید:

در تصویر بالا همسایگان پیکسل X و Y را نمایش دادیم. این نمایش را نمایش همسایگان 8 تایی یک پیکسل تعریف میکنند. همسایه 4 تایی یک پیکسل به صورت زیر نمایش داده میشود:

حال که با تعریف همسایه یک پیکسل آشنا شدیم به سراغ معرفی فیلتر میانگین برویم.
فیلتر میانگین (Mean Filter)
برای بهبود کیفیت یک تصویر و یا تغییر در آن از فیلتر استفاده میشود. فیلتر یک تکنیک است که با اعمال بر روی پیکسلهای یک تصویر، تغییراتی را میتوان در آن اعمال کرد. فیلترها انواع مختلفی دارد که در این قسمت در خصوص فیلتر میانگین یا Mean Filter صحبت میکنیم. این فیلتر همانطور که از نام آن پیداست به دنبال میانگین پیکسلهای یک تصویر است اما سوال اینجاست میانگین کدام پیکسلها ؟
برای محاسبه فیلتر میانگین پیکسل X و Y، باید میانگین تمام پیکسلهای همسایه (همسایه 8 تایی) و خود پیکسل (پیکسل X و Y) گرفته شود. فرمول زیر نحوه محاسبه پیکسل X و Y را نشان میدهد(Img آرایه پیکسلهای تصویر است):
Img[x,y] = (img[x-1,y-1] + img[x-1,y] + img[x-1,y+1] + img[x,y-1] + img[x,y] + img[x,y+1] + img[x+1,y-1] + img[x+1,y] + img[x+1,y+1]) /9
برای محاسبه فیلتر میانگین باید بر روی تمام پیکسلهای تصویر فرمول بالا را اعمال کنیم. یک نکته قابل توجه مرزهای(گوشهها) تصویر است. پیکسلهای گوشه چپ همسایه سمت چپ ندارند همچنین پیکسلهای بالا پایین و راست نیز بهترتیب همسایه بالا، پایین و راست ندارند پس در این صورت چگونه فیلتر میانگین بر روی آنها محاسبه شود؟
برای سادگی کار ما مرز یک تصویر را در نظر نمیگیریم اما راهحلهای مختلفی وجود دارد که این مشکل را برطرف کرده است.

فیلتر میانگین برای حذف نویز مورد استفاده قرار میگیرد و تصویر ما را به اصطلاح تار میکند.
پیاده سازی فیلتر میانگین در سی شارپ
حال که فرمول فیلتر میانگین را داریم میتوانیم آن را پیاده سازی کنیم. برای پیاده سازی، ما پیکسلهای یک تصویر رنگی را در سی شارپ خوانده و فیلتر میانگین را بر روی آن اعمال میکنیم. برای اعمال این فیلتر بر روی تصویر رنگی توجه داشته باشید که هر پیکسل از تصویر ما شامل سه عدد R و G و B میباشد پس باید حتما برای هر سه عدد به صورت جداگانه میانگین محاسبه شود.
کد فیلتر میانگین در سی شارپ به صورت زیر میباشد:
class MainClass
{
public static void Main (string[] args)
{
Bitmap myimage = new Bitmap ("MeanFilterinput.png");
int width = myimage.Width;
int height = myimage.Height;
Bitmap output = new Bitmap (width, height);
for (int x = 1; x < width - 1; x++) {
for (int y = 1; y < height - 1; y++) {
int a = (myimage.GetPixel (x, y).ToArgb () >> 24) & 0xff;
int avgred = AvgRed (myimage, x, y);
int avggreen = AvgGreen (myimage, x, y);
int avgblue = AvgBlue (myimage, x, y);
output.SetPixel
(x, y, Color.FromArgb (a, avgred, avggreen, avgblue));
}
}
output.Save ("MeanFilterOutput.png");
Console.WriteLine
("Press any key to Finish Create Green Image....");
Console.ReadKey ();
}
public static int AvgRed (Bitmap image, int x, int y)
{
int avgred = getRed (image.GetPixel (x - 1, y - 1).ToArgb ()) +
getRed (image.GetPixel (x - 1, y).ToArgb ())
+
getRed (image.GetPixel (x - 1, y + 1).ToArgb ()) +
getRed (image.GetPixel (x, y - 1).ToArgb ())+
getRed (image.GetPixel (x, y).ToArgb ()) +
getRed (image.GetPixel (x, y + 1).ToArgb ())+
getRed (image.GetPixel (x + 1, y - 1).ToArgb ()) +
getRed (image.GetPixel (x + 1, y).ToArgb ()) +
getRed (image.GetPixel (x + 1, y + 1).ToArgb ());
return avgred / 9;
}
public static int AvgGreen (Bitmap image, int x, int y)
{
int avgred = getGreen (image.GetPixel (x - 1, y - 1).ToArgb ()) +
getGreen (image.GetPixel (x - 1, y).ToArgb ())+
getGreen (image.GetPixel (x - 1, y + 1).ToArgb ()) +
getGreen (image.GetPixel (x, y - 1).ToArgb ())+
getGreen (image.GetPixel (x, y).ToArgb ()) +
getGreen (image.GetPixel (x, y + 1).ToArgb ())+
getGreen (image.GetPixel (x + 1, y - 1).ToArgb ()) +
getGreen (image.GetPixel (x + 1, y).ToArgb ()) +
getGreen (image.GetPixel (x + 1, y + 1).ToArgb ());
return avgred / 9;
}
public static int AvgBlue (Bitmap image, int x, int y)
{
int avgBlue = getBlue (image.GetPixel (x - 1, y - 1).ToArgb ()) +
getBlue (image.GetPixel (x - 1, y).ToArgb ())+
getBlue (image.GetPixel (x - 1, y + 1).ToArgb ()) +
getBlue (image.GetPixel (x, y - 1).ToArgb ())+
getBlue (image.GetPixel (x, y).ToArgb ()) +
getBlue (image.GetPixel (x, y + 1).ToArgb ())+
getBlue (image.GetPixel (x + 1, y - 1).ToArgb ()) +
getBlue (image.GetPixel (x + 1, y).ToArgb ()) +
getBlue (image.GetPixel (x + 1, y + 1).ToArgb ());
return avgBlue / 9;
}
public static int getRed (int rgb)
{
return (rgb >> 16) & 0xff;
}
public static int getBlue (int rgb)
{
return rgb & 0xff;
}
public static int getGreen (int rgb)
{
return (rgb >> 8) & 0xff;
}
}
در کد بالا از متدهای زیر استفاده شده است:
- متد getRed: از آنجا که ما با تصاویر RGB کار میکنیم در هنگام دریافت یک پیکسل در سی شارپ رنگهای R و G و B را به صورت یکجا در یک مقدار به ما میدهد. این متد مقدار رنگ قرمز را از رنگ سبز و آبی جدا کرده و به ما برمیگرداند.
- متد getGreen: مانند متد getred بوده اما رنگ سبز یک پیکسل را برای ما برمیگرداند.
- متد getBlue: مانند متدهای بالا بوده اما رنگ آبی یک پیکسل را به ما میدهد.
- متد AvgRed: این متد اندیسهای یک پیکسل را در ورودی دریافت میکند و میانگین رنگ قرمز همسایگان 8 تایی به همراه پیکسل ورودی را در خروجی به ما میدهد (دقیقا فرمول فیلتر میانگین). نکته قابل ذکر این است که چون پیکسل تصویر ما شامل سه عدد R و G و B بوده باید برای هر سه آنها به طور جداگانه مقدار میانگین را محاسبه کرد.
- متد AvgGreen: دقیقا مانند متد AvgRed کار میکند فقط در خروجی میانگین رنگهای سبز را به ما میدهد.
- متد AvgBlue: مانند متدهای AvgRed و AvgGreen بوده اما در خروجی میانگین رنگ آبی پیکسل ورودی و همسایگانش را برمیگرداند.
در متد Main ابتدا یک تصویر را خوانده و سپس بر روی پیکسلهای آن فرمول فیلتر میانگین را اعمال کرده و در تصویری دیگر ذخیره میکنیم. توجه کنید ما آلفا(Alpha یا آلفا مقدار Transparency یک پیکسل) در هر پیکسل بدون تغییر به تصویر جدید انتقال دادیم(شما میتوانید فرمول فیلتر میانگین را برای آلفا نیز اعمال کنید).