در این جلسه تیم کدگیت را با یکی دیگر از آموزشهای پردازش تصویر یعنی « فیلتر Min در جاوا » همراهی کنید. قبل از شروع آموزش طبق روال آموزشهای گذشته پیشنیازهای این جلسه را معرفی میکنیم. پیشنیازها به صورت زیر است:
- خواندن و نوشتن تصاویر در جاوا
- بهبود تصاویر در جاوا
- حلقه For در جاوا
- استثناها در جاوا
- فایل در جاوا
- آرایه در جاوا
همسایه یک پیکسل در تصاویر
همانطور که در آموزش بهبود تصاویر در جاوا گفته شد تصاویر از پیکسلها تشکیل شده و نحوه نمایش آنها به صورت آرایه دو بعدی است(البته تصاویر RGB سه آرایه دو بعدی داریم!). به تصویر زیر دقت کنید:
در تصویر بالا همسایگان پیکسل X و Y را نمایش دادیم. این نمایش را نمایش همسایگان 8 تایی یک پیکسل تعریف میکنند. همسایه 4 تایی یک پیکسل به صورت زیر نمایش داده میشود:
الگوریتم فیلتر Minimum
الگوریتم فیلتر Min بسیار ساده بوده و نیاز به فرمول ریاضی خاصی ندارد. با استفاده از همسایههای 8 تایی پیکسل X و Y، ما مینیمم(مقدار کمینه) همسایگی و پیکسل X و Y را به عنوان پیکسل جدید انتخاب میکنیم. باید توجه کنید ما نقاط مرزی را در نظر نمیگیریم اما روشهای مختلفی وجود دارد که میتوان از آن استفاده کرد.(ما برای سادگی پیاده سازی از پیکسلهای مرزی صرف نظر کردیم.)
پیادهسازی فیلتر Min در جاوا
برای پیاده سازی فیلتر Min در جاوا مراحل زیر را انجام میدهیم:
- یک تصویر را به عنوان ورودی دریافت میکنیم.
- تصویر ورودی را میخوانیم. با توجه به تصویر نیاز به سه مینیمم داریم. (هر پیکسل شامل سه رنگ R و G و B است)
- برای پیکسل X و Y، پیکسلهای R و G و B همسایه 8 تایی و خود X و Y را درون آرایه میریزیم.
- آرایههای خود را مرتب میکنیم.
- مقدار پیکسل جدید، مقدار خانه اول آرایههای R و G و B است. (آرایه به صورت صعودی مرتب شده است)
- موارد 3 تا 5 را برای تمام پیکسلهای تصویر انجام میدهیم.
کد این الگوریتم به صورت زیر است:
public class MinFilter {
public static void main(String[] args) {
BufferedImage img = null;
File f = null;
// read image
try {
f = new File("Min 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("Min 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 = MinRed(img, x, y);
maxgreen = MinGreen(img, x, y);
maxblue = MinBlue(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("Min Filter output.png");
ImageIO.write(outputimage, "png", f);
} catch (IOException e) {
System.out.println(e);
}
System.out.println("program finish....");
}
private static int MinRed(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[0];
}
private static int MinBlue(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[0];
}
private static int MinGreen(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[0];
}
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: مانند متدهای بالا بوده اما رنگ قرمز یک پیکسل را به ما میدهد.
- متد MinRed: این متد اندیسهای یک پیکسل را در ورودی دریافت میکند و مینیمم رنگ قرمز همسایگان 8 تایی به همراه پیکسل ورودی را بدست آورده در خروجی به ما میدهد. نکته قابل ذکر این است که چون پیکسل تصویر ما شامل سه عدد R و G و B بوده باید برای هر سه آنها به طور جداگانه مقدار مینیمم را محاسبه کرد.
- متد MinGreen: دقیقا مانند متد MinRed کار میکند فقط در خروجی مینیمم رنگهای سبز را به ما میدهد.
- متد MinBlue: مانند متدهای MinRed و MinGreen بوده اما در خروجی مینیمم رنگ آبی پیکسل ورودی و همسایگانش را برمیگرداند.
خروجی کد بالا به صورت زیر است:
در بالا ما یک تصویر داریم که واژه Min را در ورودی دریافت کرده است و در خروجی به دلیل استفاده از فیلتر مینیمم رنگ سیاه ضخیمتر شده، فیلتر مینیمم بین رنگ سیاه (مقدار صفر) و رنگ سفید (مقدار 255) مقدار کمتر یعنی رنگ سیاه را انتخاب میکند به همین دلیل تصویر خروجی به اصطلاح به حالت Bold تبدیل شده است.