در این جلسه تیم کدگیت را با یکی دیگر از آموزشهای پردازش تصویر یعنی « فیلتر Max در جاوا » همراهی کنید. قبل از شروع آموزش طبق روال آموزشهای گذشته پیشنیازهای این جلسه را معرفی میکنیم. پیشنیازها به صورت زیر است:
- خواندن و نوشتن تصاویر در جاوا
- بهبود تصاویر در جاوا
- حلقه For در جاوا
- استثناها در جاوا
- فایل در جاوا
- آرایه در جاوا
همسایه یک پیکسل در تصاویر
همانطور که در آموزش بهبود تصاویر در جاوا گفته شد تصاویر از پیکسلها تشکیل شده و نحوه نمایش آنها به صورت آرایه دو بعدی است(البته تصاویر RGB سه آرایه دو بعدی داریم!). به تصویر زیر دقت کنید:

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

الگوریتم فیلتر Max در جاوا
الگوریتم فیلتر Max بسیار ساده بوده و نیاز به فرمول ریاضی خاصی ندارد. با استفاده از همسایههای 8 تایی پیکسل X و Y، ما ماکزیمم(مقدار بیشینه) همسایگی و پیکسل X و Y را به عنوان پیکسل جدید انتخاب میکنیم. باید توجه کنید ما نقاط مرزی را در نظر نمیگیریم اما روشهای مختلفی وجود دارد که میتوان از آن استفاده کرد.(ما برای سادگی پیاده سازی از پیکسلهای مرزی صرف نظر کردیم.)

پیادهسازی فیلتر Max در جاوا
برای پیاده سازی فیلتر Max در جاوا مراحل زیر را انجام میدهیم:
- یک تصویر را به عنوان ورودی دریافت میکنیم.
- تصویر ورودی را میخوانیم. با توجه به تصویر نیاز به سه ماکزیمم داریم. (هر پیکسل شامل سه رنگ R و G و B است)
- برای پیکسل X و Y، پیکسلهای R و G و B همسایه 8 تایی و خود X و Y را درون آرایه میریزیم.
- آرایههای خود را مرتب میکنیم.
- مقدار پیکسل جدید، مقدار خانه آخر آرایههای R و G و B است. (آرایه به صورت صعودی مرتب شده است)
- موارد 3 تا 5 را برای تمام پیکسلهای تصویر انجام میدهیم.
کد این الگوریتم به صورت زیر است:
public class MaxFilter {
public static void main(String[] args) {
BufferedImage img = null;
File f = null;
// read image
try {
f = new File("Max Filter input.png");
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);
System.out.println("Max Filter starts....");
for (int x = 1; x < width - 1; x++) {
for (int y = 1; y < height - 1; y++) {
int maxred = 0;
int maxgreen = 0;
int maxblue = 0;
maxred = MaxRed(img, x, y);
maxgreen = MaxGreen(img, x, y);
maxblue = MaxBlue(img, x, y);
Color col = new Color(maxred, maxgreen, maxblue);
outputimage.setRGB(x, y, col.getRGB());
}
}
System.out.println("start create output image....");
// write image
try {
f = new File("Max Filter output.png");
ImageIO.write(outputimage, "png", f);
} catch (IOException e) {
System.out.println(e);
}
System.out.println("program finish....");
}
private static int MaxRed(BufferedImage img, int x, int y) {
int neighbour[] = new int[9];
neighbour[0] = getRed(img.getRGB(x - 1, y - 1));
neighbour[1] = getRed(img.getRGB(x + 1, y + 1));
neighbour[2] = getRed(img.getRGB(x, y - 1));
neighbour[3] = getRed(img.getRGB(x, y + 1));
neighbour[4] = getRed(img.getRGB(x - 1, y));
neighbour[5] = getRed(img.getRGB(x + 1, y));
neighbour[6] = getRed(img.getRGB(x - 1, y + 1));
neighbour[7] = getRed(img.getRGB(x + 1, y - 1));
neighbour[8] = getRed(img.getRGB(x, y));
Arrays.sort(neighbour);
return neighbour[8];
}
private static int MaxBlue(BufferedImage img, int x, int y) {
int neighbour[] = new int[9];
neighbour[0] = getBlue(img.getRGB(x - 1, y - 1));
neighbour[1] = getBlue(img.getRGB(x + 1, y + 1));
neighbour[2] = getBlue(img.getRGB(x, y - 1));
neighbour[3] = getBlue(img.getRGB(x, y + 1));
neighbour[4] = getBlue(img.getRGB(x - 1, y));
neighbour[5] = getBlue(img.getRGB(x + 1, y));
neighbour[6] = getBlue(img.getRGB(x - 1, y + 1));
neighbour[7] = getBlue(img.getRGB(x + 1, y - 1));
neighbour[8] = getBlue(img.getRGB(x, y));
Arrays.sort(neighbour);
return neighbour[8];
}
private static int MaxGreen(BufferedImage img, int x, int y) {
int neighbour[] = new int[9];
neighbour[0] = getGreen(img.getRGB(x - 1, y - 1));
neighbour[1] = getGreen(img.getRGB(x + 1, y + 1));
neighbour[2] = getGreen(img.getRGB(x, y - 1));
neighbour[3] = getGreen(img.getRGB(x, y + 1));
neighbour[4] = getGreen(img.getRGB(x - 1, y));
neighbour[5] = getGreen(img.getRGB(x + 1, y));
neighbour[6] = getGreen(img.getRGB(x - 1, y + 1));
neighbour[7] = getGreen(img.getRGB(x + 1, y - 1));
neighbour[8] = getGreen(img.getRGB(x, y));
Arrays.sort(neighbour);
return neighbour[8];
}
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: مانند متدهای بالا بوده اما رنگ آبی یک پیکسل را به ما میدهد.
- متد MaxRed: این متد اندیسهای یک پیکسل را در ورودی دریافت میکند و ماکزیمم رنگ قرمز همسایگان 8 تایی به همراه پیکسل ورودی را بدست آورده در خروجی به ما میدهد. نکته قابل ذکر این است که چون پیکسل تصویر ما شامل سه عدد R و G و B بوده باید برای هر سه آنها به طور جداگانه مقدار ماکزیمم را محاسبه کرد.
- متد MaxGreen: دقیقا مانند متد MaxRed کار میکند فقط در خروجی ماکزیمم رنگهای سبز را به ما میدهد.
- متد MaxBlue: مانند متدهای MaxRed و MaxGreen بوده اما در خروجی ماکزیمم رنگ آبی پیکسل ورودی و همسایگانش را برمیگرداند.
خروجی برنامه
خروجی کد بالا به صورت زیر است:

در بالا ما یک تصویر داریم که واژه Max را به صورت Bold در ورودی دریافت کرده است و در خروجی به دلیل استفاده از فیلتر ماکزیمم رنگ سیاه نازکتر شده، فیلتر ماکزیمم بین رنگ سیاه (مقدار صفر) و رنگ سفید (مقدار 255) مقدار بیشتر یعنی رنگ سفید را انتخاب میکند به همین دلیل تصویر خروجی به اصطلاح از حالت Bold خارج شده است.