Image Processing and Computer vision in java (Image Filtering part1)

Image filtering:

today we are going to learn image filtering. We can apply various kind of effects on our picture by image filtering. Basically it is a neighborhood operation, which means the value of output pixel depends on the neighboring pixels of input pixel. In image filtering we have a 2D filtering matrix and a 2D image. Actually we are multiplying each filter value with a corresponding neighboring pixel of the input pixel and then sum them out. The sum will be the value of output pixel. Some times we have to normalize value of output pixel by averaging. Take a look at the picture below

convolution2

we can call the filtering matrix a kernel. As we can see from the picture above, we apply the filter to the center pixel by multiplying its neighborhood with the kernel. This operation is also called convolution and the kernel is called the convolution matrix . The size of kernel has to be odd so that it has a center like an example 3×3,5×5 and 7×7 kernels are valid.

Blurring:

blurring can be achieved simply by averaging the neighborhood of a pixel. To get a better idea look at the code snippet below below

    //5x5 filtering matrix
    public static final int[][] MEEAN_FILTR_5 = {{  1,1,1,1,1  },
                                                 {  1,1,1,1,1  },
                                                 {  1,1,1,1,1  },
                                                 {  1,1,1,1,1  },
                                                 {  1,1,1,1,1  }};
    public void meanFilter(BufferedImage img){
        int pixel[];
        //looping trough each pixel of the image
        for (int i = 0; i < img.getWidth(); i++) {
            for (int j = 0; j < img.getHeight(); j++) {
                int n=0;
                //looping into filtering matrix
                for(int k =0 ; k<MEEAN_FILTR_5.length;k++){
                    for(int l=0;l<MEEAN_FILTR_5[k].length;l++){
                        //getting the corresponding neighboring pixel
                        // we use modulus of the width or height of the image so that pixels outside the image will be wrapped around
                        int imgX = (i-MEEAN_FILTR_5.length/2+k+img.getWidth())%img.getWidth();
                        int imgY = (j-MEEAN_FILTR_5[k].length/2+l+img.getHeight())%img.getHeight();
                        pixel = img.getRaster().getPixel(imgX,imgY, new int[3]);
                        //get the new value
                        n += pixel[0]*MEEAN_FILTR_5[k][l];

                        
                    }
                }
                //normalize the value
                n = n/25;
                if(n>255)
                    n =255;
                else if(n<0)
                    n=0;
                //set the new pixel value
                Color color = new Color(n, n, n);

                int rgb = color.getRGB();

                img.setRGB(i, j, rgb);

            }

        }
    }

Input Image:
meanfilbeforeOutput Image:
meanafter

Motion Blur:

For motion filter we can use the kernel below

public static final int[][] MOTION_FILTR_5 =   { {  1,0,0,0,0  },
                                                 {  0,1,0,0,0  },
                                                 {  0,0,1,0,0  },
                                                 {  0,0,0,1,0  },
                                                 {  0,0,0,0,1  } };
//here our normalize factor will be 5 because the sum of the kernel values is 5

So the code will be

public void motionFilter(BufferedImage img){
        int pixel[];
        for (int i = 0; i < img.getWidth(); i++) {
            for (int j = 0; j < img.getHeight(); j++) {
                int n=0;
                for(int k =0 ; k<MOTION_FILTR_5.length;k++){
                    for(int l=0;l<MOTION_FILTR_5[k].length;l++){
                        int imgX = (i-MOTION_FILTR_5.length/2+k+img.getWidth())%img.getWidth();
                        int imgY = (j-MOTION_FILTR_5[k].length/2+l+img.getHeight())%img.getHeight();
                        pixel = img.getRaster().getPixel(imgX,imgY, new int[3]);
                        //get the new value
                        n += pixel[0]*MOTION_FILTR_5[k][l];

                        
                    }
                }
                n = n/5;
                if(n>255)
                    n =255;
                else if(n<0)
                    n=0;
                Color color = new Color(n, n, n);

                int rgb = color.getRGB();

                img.setRGB(i, j, rgb);

            }

        }
    }

Input Image:
meanfilbeforeOutput Image:
motion blur

On our next tutorial we will be talking about Image Sharpening and Edge Detection.

Image Processing and Computer vision in java (Point Operators part 2)Histogram Equalization

Histogram Equalization: Histogram equalization is used to enhance the contrast of an image. to do this  first we have to know about histogram. Histogram is a representation of the distribution of data. So the histogram of an image represents how the pixel values are distributed. take a look at the image array below
pixel
here we can see pixel value 170 appears 4 times and 68 appears 3 times and so on. To get the histogram of an image we have to calculate which value appears how many times in the image. to calculate histogram we can use the code snippet below

public int[] CalculateHist(BufferedImage img) {
    int k;
    int pixel[];
    //array represents the intecity values of the pixels
    int levels[] = new int[256];
    for (int i = 0; i < img.getWidth(); i++) {
        for (int j = 0; j < img.getHeight(); j++) {
        pixel = img.getRaster().getPixel(i, j, new int[3]);
        //increase if same pixel appears
        levels[pixel[0]]++;
        }
     }
     //return the histogram array
     return levels;
}

Histogram_Equalization2

In the right side of the image is a graphical representation of its histogram. In the X-direction of the graph is the intensity values of the image and in the Y-direction of the image is the number of repetition of the values. We can see most of the pixel values are concentrated in brighter region for that the darker region is not clear. In histogram equalization basically what we do is to distribute the values uniformly. To do this we first calculate the PMF(probability mass function) from the histogram and then calculate the CDF(cumulative distribution function) and multiply it with (I-1) where I is the maximum intensity value. We can use the following formulas
CDF

EQ

So the first formula calculate the cumulative distribution of the histogram and second formula calculate equalization. If we apply this to the first image we will get
Histogram_Equalization3

The java code for Histogreme equalization is given below

public void histEqualize(BufferedImage img) {
    //call CalculateHist method to get the histogram
    int[] h = CalculateHist(img);
    //calculate total number of pixel
    int mass = img.getWidth() * img.getHeight();
    int k = 0;
    long sum = 0;
    int pixel[];
    //calculate the scale factor
    float scale = (float) 255.0 / mass;
    //calculte cdf
    for (int x = 0; x < h.length; x++) {
        sum += h[x];
        int value = (int) (scale * sum);
        if (value > 255) {
           value = 255;
        }
        h[x] = value;
    }
    for (int i = 0; i < img.getWidth(); i++) {
        for (int j = 0; j < img.getHeight(); j++) {
        pixel = img.getRaster().getPixel(i, j, new int[3]);
        //set the new value
        k = h[pixel[0]];
        Color color = new Color(k, k, k);
        int rgb = color.getRGB();
        img.setRGB(i, j, rgb);
    }
  }
}

Input Image:

before

Output Image:

after
Phew we are done with point operators next we will talk about pixel neighborhood and filtering.

Image Processing and Computer vision in java (Point Operators part 1)

Image point operators are the simplest kind of image transform in which each output pixel’s value depends on only the corresponding input pixel value. Converting color, changing image brightness, gamma correction, thresholding etc. are the example of image point operation.

We are going to apply these transform to the image given below:

Capture

Convert RGB to Grey: As we are performing image processing in greyscale images then we need to convert a color image into a greyscale image. There are many ways to do this but I am going to describe two of them one is averaging and second one is luminosity.

  1. Averaging: in this method we average the rgb value of each pixel and set those values to corresponding pixels.

GreyScale = (R+G+B)/3

To get a clear view you can look at the code snippet below


for(int i=0; i<image.getWidth(); i++){

    for(int j=0; j<image.getHeight(); j++){

       int pixel[] = image.getRaster().getPixel(i, j, new int[3]);
       //get the average of RGB value
       int k = (pixel[0]+pixel[1]+pixel[2])/3;
       //set the average to the pixel
       Color color = new Color(k, k, k);

       int rgb = color.getRGB();

       image.setRGB(i, j, rgb);

    }
}

output Image:

grey

Though it is very easy to implement but most of the time output image is not as good as we expect. To give greyscale image a natural look we can use luminosity.

  1. Luminosity or Weighted method: The philosophy behind luminosity or weighted method is the contribution of color to form an image. We all know that red color has more wavelength of all the three of colors. For that red color dominates in image color composition. On the other hand green color not only has less wavelength but it also very soothing for our eyes. So to make the grey image more natural we can reduce the contribution of red color and increase the contribution of green color. We put the blue color in between them. So the equation will be:

GreyScale = ( (0.3 * R) + (0.59 * G) + (0.11 * B) )

Here in this equation red has contributed 33% ,green 59% and blue has contributed 11%

To implement this in java this in java we can do something like this:


for(int i=0; i<img.getWidth(); i++){

    for(int j=0; j<img.getHeight(); j++){

        int pixel[] = img.getRaster().getPixel(i, j, new int[3]);
        //get the new value
        int k =(int)((0.3*pixel[0])+(0.59*pixel[1])+(0.11*pixel[2]));

        Color color = new Color(k, k, k);

        int rgb = color.getRGB();

       img.setRGB(i, j, rgb);

    }

}

output Image:
Capturelum

Gamma Transform: it is also known as power-law transform. This transform used in CRT monitors to correct the image intensity. It is mathematically denoted as follows:

gamma eq

where c and ɣ are two constants. This transform can make image brighter or darker depending on the value of ɣ. If ɣ is lager it will make the image darker and if ɣ is smaller than the image will brighter. To implement this in java with the ɣ value 0.45 we can use the code given below:


for(int i=0; i<img.getWidth(); i++){

    for(int j=0; j<img.getHeight(); j++){

       int pixel[] = img.getRaster().getPixel(i, j, new int[3]);
       //get the gamma corrected value
       int k = (int) (255*(Math.pow((double)pixel[0]/(double)255, 2.2)));

       Color color = new Color(k, k, k);

       int rgb = color.getRGB();

       img.setRGB(i, j, rgb);

    }

}

We can take a look at the picture below to get a clear idea

conv
Output Image:
gamma
Photographic Negative: negative is just the inverse of a picture. To create a negative of a binary image we can transform the black points(0s) into white(1s) and white points(1s) into black(0s). for that the equation will be:

binary neg

For greyscale image the transform can be accomplish by

negateeq1

And the java implementation is


for(int i=0; i<img.getWidth(); i++){

    for(int j=0; j<img.getHeight(); j++){

       int pixel[] = img.getRaster().getPixel(i, j, new int[3]);
       //get the new value
       k = 255 - pixel[0];

       Color color = new Color(k, k, k);

       int rgb = color.getRGB();

       img.setRGB(i, j, rgb);

   }

}

output Image:
negat

Brightness: it can be achieve by adding or deleting constant value from image pixel. If you add value image will be bright and if we delete image will dark. The equation for that is:

P’ = P+C or P’ = P-C here “P” is the old value and “P’ ” is the new pixel value

The java code is:

for(int i=0; i<img.getWidth(); i++){

    for(int j=0; j<img.getHeight(); j++){

        pixel = img.getRaster().getPixel(i, j, new int[3]);
        //adding constant we can also subtract constant from here
        int k = pixel[0]+50;
        //check if the value out side of the boundary
        if(k>255)

            k = 255;

        else if(k<0)

            k = 0;

        Color color = new Color(k, k,k);

        int rgb = color.getRGB();

        img.setRGB(i, j, rgb);

    }

}

Here we have to check the value limit. The cannot be higher than 255 or less than 0.

Output Image:

bright

Thresholding: transforming a grey image into binary image is thresholding. There are many ways to do that but I am going to show you one. In this method we are going to calculate the mean of  the pixel values of an image and compare the mean with each pixel value. If the value is bigger than mean we will set the pixel value to 255 and if the pixel value is less than mean we will put 0 in it. The method will be more clearer if you take a look at the code snippet below:


public void threshold(BufferedImage img){

    int pixel[];

    int k = 0;

    Color color;

    int rgb;
    //calculating the number of pixel
    int mean = img.getWidth()* img.getHeight();

    for(int i=0; i<img.getWidth(); i++){

        for(int j=0; j<img.getHeight(); j++){

            pixel = img.getRaster().getPixel(i, j, new int[3]);
            //adding the value of pixel
            k += pixel[0];

        }

    }
    //calculating the mean
    mean = k/mean;

    for(int i=0; i<img.getWidth(); i++){

        for(int j=0; j<img.getHeight(); j++){

            pixel = img.getRaster().getPixel(i, j, new int[3]);
            //check the pixel value is greater or less then mean
            if(pixel[0]>mean)
                //if value is bigger than set 255
                k = 255;

            else
            //else set the value 0
                k = 0;

            color = new Color(k, k, k);

            rgb = color.getRGB();

            img.setRGB(i, j, rgb);

        }

    }

}

output Image:
threshold
On our next tutorial we are going to discuss Histogram and histogram equalization

Image Processing and Computer vision in java (Intro)

Hi guys,this is my first tutorial on digital Image processing and computer vision in java. I assume that you have a better understanding in java programming language. First of all in these sets of tutorials I will discuss about image processing and cv algorithms and show you how to implement those in java. To make things easy and more understandable I will try to make the codes as simple as possible. For that the code won’t be so efficient but if you get the idea you can implement the code as efficient as you can.

At first we have to understand the structure of an image.  Images are nothing but a two-dimensional array of pixels. Each pixel represents a point of an image. As it is a two-dimensional structure every pixel has a (x,y) position.  In the figure below there are two pixel with a value of 85 appear in (2, 3) and (0, 5) position. The position of the first pixel is (0, 0).

pixel

Basically there are three types of images:

  1. Binary image in which each pixel has 2 bit value ‘0’ and ‘1’. 0 represents black and 1 represents white color. Actually 255 represents white color but conventionally we wrote it 1.
  2. Grey Image in which each pixel has 8 bit value from 0 to 255.
  3. Color image in which each pixel has three channels for ‘red’, ‘green’ and ‘blue’. Each channel has 8 bit value from 0 to 255. So a color image has a total of 24 bit value and if we add 8 bits of alpha value then color images actually have 32 bits of value. So there are 224 which is 16.7 million combination of colors we can see with our eyes and that’s why some LED screens label says it has 16 million colors.

In these tutorials we will use grey level images for better understanding but after that I will show you how to perform image processing in colored image.

Loading and displaying an Image:

To read an image in java we need to use ‘ImageIO’ class and save the data into a ‘BufferedImage’.


 BufferedImage image = ImageIO.read(new File("C:\\Users\\nausad\\Pictures\\Test.JPG"));


 

 

and to Display an image we can use “JFrame”.


 //add the image in JLable
 JLabel label = new JLabel(new ImageIcon(image));

 JFrame f = new JFrame();
 //Exit whenever colose button pressed
 f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 //add label in JFrame
 f.getContentPane().add(label);
 //display the image to its original size
 f.pack();
 //center the window
 f.setLocationRelativeTo(null);

 f.setVisible(true);

 

 

The full code of loading and displaying an image in java is given below



 import PointOperation.PointOperation;

 import java.awt.image.BufferedImage;

 import java.io.File;

 import javax.imageio.ImageIO;

 public class Test {

 public static void main(String[] args){
 //Exception must handled to use ImageIO
     try{

         BufferedImage image = ImageIO.read(new File("C:\\Users\\nausad\\Pictures\\Test.JPG"));

         JLabel label = new JLabel(new ImageIcon(image));

         JFrame f = new JFrame();

         f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

         f.getContentPane().add(label);

         f.pack();

         f.setLocationRelativeTo(null);

         f.setVisible(true);

     }catch(Exception e){

     System.err.println("Cannot load image");

     }

   }

 }

 

 

Getting the pixel values of an Image:

To access each pixel value of an Image we need two for loop  to iterate over the two-dimensional array. We can create a method which takes a BufferdImage   as a parameter  and iterate each pixel of the image and print their value.



 public void rgbToGrey(BufferedImage img){

//pixel array to hold the r,g,b value of the pixel
         int pixel[];
         for(int i=0; i<img.getWidth(); i++){
             for(int j=0; j<img.getHeight(); j++){

//get the r,g,b value of the pixel at ( i , j ) location
                 pixel = img.getRaster().getPixel(i, j, new int[3]);

//at 0 index the array contains the red pixel value and 1, 2 index have the value of green and blue respectively
                 System.out.println("R: "+pixel[0]+" G: "+pixel[1]+" B: "+pixel[2]);
             }
         }
     }


 

On our next tutorial I will show you pixel manipulation and point operations