در ادامه آموزشهای پردازش تصویر کدگیت این قسمت به معرفی فیلتر میانگین در جاوا (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 میباشد پس باید حتما برای هر سه عدد به صورت جداگانه میانگین محاسبه شود.
کد فیلتر میانگین در جاوا به صورت زیر میباشد:
public class MeanFilter {
public static void main(String[] args) {
BufferedImage img = null;
File f = null;
// read image
try {
f = new File("mean filter.jpg");
img = ImageIO.read(f);
} catch (IOException e) {
System.out.println(e);
}
// get width and height
int width = img.getWidth();
int height = img.getHeight();
BufferedImage outputimage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
for (int x = 1; x < width - 1; x++) {
for (int y = 1; y < height - 1; y++) {
int Avgred = 0;
int Avggreen = 0;
int Avgblue = 0;
Avgred = AvgRed(img, x, y);
Avggreen = AvgGreen(img, x, y);
Avgblue = AvgBlue(img, x, y);
Color col = new Color(Avgred, Avggreen, Avgblue);
outputimage.setRGB(x, y, col.getRGB());
}
}
// write image
try {
f = new File("mean filter output.jpg");
ImageIO.write(outputimage, "jpg", f);
} catch (IOException e) {
System.out.println(e);
}
}
public static int AvgBlue(BufferedImage img, int x, int y) {
return (getBlue(img.getRGB(x - 1, y - 1)) + getBlue(img.getRGB(x + 1, y + 1))
+ getBlue(img.getRGB(x, y - 1))+ getBlue(img.getRGB(x, y + 1)) +
getBlue(img.getRGB(x - 1, y)) + getBlue(img.getRGB(x + 1, y))
+ getBlue(img.getRGB(x - 1, y + 1)) + getBlue(img.getRGB(x + 1, y - 1))
+ getBlue(img.getRGB(x, y)))/ 9;
}
public static int AvgGreen(BufferedImage img, int x, int y) {
return (getGreen(img.getRGB(x - 1, y - 1)) + getGreen(img.getRGB(x + 1, y + 1))
+ getGreen(img.getRGB(x, y - 1))+ getGreen(img.getRGB(x, y + 1))
+ getGreen(img.getRGB(x - 1, y)) + getGreen(img.getRGB(x + 1, y))
+ getGreen(img.getRGB(x - 1, y + 1)) + getGreen(img.getRGB(x + 1, y - 1))
+ getGreen(img.getRGB(x, y)))/ 9;
}
private static int AvgRed(BufferedImage img, int x, int y) {
int sumR;
sumR = (getRed(img.getRGB(x - 1, y - 1)) + getRed(img.getRGB(x + 1, y + 1))
+ getRed(img.getRGB(x, y - 1))+ getRed(img.getRGB(x, y + 1)) + getRed(img.getRGB(x - 1, y))
+ getRed(img.getRGB(x + 1, y))+ getRed(img.getRGB(x - 1, y + 1))
+ getRed(img.getRGB(x + 1, y - 1)) + getRed(img.getRGB(x, y))) / 9;
return sumR;
}
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 بوده اما در خروجی میانگین رنگ آبی پیکسل ورودی و همسایگانش را برمیگرداند.
خوب