Total Pageviews

Wednesday, October 2, 2019

Image Contrast and Grayscaling the Image in Java

Code First:

     public void contrastImage(BufferedImage img,float clip){//strecth luminance, adjust RGB proportionately
        int N=256;//bins
        makeHistogram(img,N);
        int height=img.getHeight();
        int width=img.getWidth();
        float min,max,sum=0,total=height*width;
        long index,mindex=0,maxdex=N;
        
        for(index=0;index<N;index++){
            sum+=hist[(int)index];
            if((mindex==0)&&((sum/total)>clip))     mindex=index;
            if((maxdex==N)&&((sum/total)>(1-clip))) maxdex=index-1;
        }
        min=255.0f*mindex/N;
        max=255.0f*maxdex/N;
        float scale;
        scale=(255.0f/(max-min));
        int result[][]=new int[width][height];
        for(int row=0;row<height;row++){
            for(int col=0;col<width;col++){
                result[col][row]=img.getRGB(col, row);
                Color c=new Color(result[col][row]);
                float red=c.getRed();
                float blue=c.getBlue();
                float green=c.getGreen();
                red=scale*(red-min);
                blue=scale*(blue-min);
                green=scale*(green-min);
                if(red>255)red=255;
                if(red<0)red=0;
                if(blue>255)blue=255;
                if(blue<0)blue=0;
                if(green>255)green=255;
                if(green<0)green=0;
                c=new Color((int)red,(int)green,(int)blue);
                img.setRGB(col,row,c.getRGB());
            }
        }
        
    }

Explanation:

     In processes where we need to contrast an image, the result is acquired by stretching the histogram curve, forming a comb-like graph. Thus, we first get the max and min intensities and then find the scale factor. Scaling is done for each color channel. 
The "clip" helps the user to change the amount of contrast. For example, 0.0025 means 25%. 

                                                      <<PREV      NEXT>>

Tuesday, October 1, 2019

Creating Image Histograms in Java

Why need histograms??

     Image histograms tell us a lot about their respective images. For example, a histogram with spaced lines tells us that its image has been previously scaled to contrast it. There will be a different post soon, that will tell you how important is the histograms. For now, we will see only, how to create histograms of images.

Extra software:

     Although you have ways to make histograms programmatically, but to reduce the effort for the learning process, you can rely on software that can show spreadsheets. I am using Microsoft Excel 2013.

The Code:

     int hist[];
     String Hist;
     public void makeHistogram(BufferedImage img,int bins){//woring on it
        int N=bins;
        hist=new int[N];
        for(int bright=0;bright<N;bright++)
            hist[bright]=0;
        
        int width=img.getWidth();
        int height=img.getHeight();
        int[][] result=new int[width][height];
        for(int row=0;row<height;row++){
            for(int col=0;col<width;col++){
                result[col][row]=img.getRGB(col, row);
                Color c=new Color(result[col][row]);
                int red=c.getRed();
                int blue=c.getBlue();
                int green=c.getGreen();
                int bright=(int)((red+blue+green)/3);
                int index=(int)((float)N*bright/bins);
                hist[index]++;
            }
        }
        for(int bright=0;bright<N;bright++){
            Hist=Hist+","+hist[bright];
        }
    }

In the code, the "bright" is calculated for each pixel, which is the average value of red, blue, and green values of the pixel. "bins" are nothing but defines the domain area of the histogram. It may be 256, 64, etc.
We are storing the array hist[] in String Hist, separated by commas. Contents in Hist then can be easily copied to a file. Such files be can easily analysed by these simple steps.

Here is an example:





<<PREV            NEXT>>

Sunday, September 29, 2019

BASICS- loading, saving, and accessing pixel details as an array

Why Java??

     I chose Java as the language of this tutorial just because most of the people around the world is really closest to this language. Normally we feel so ease with this simple but powerful language!


Overview of the tutorial:

This tutorial is not to teach you to do things in Java particularly. It's just a tool that I'm using. I always prefer C to learn how actually computers work. But, there are really many references for programming image processing algorithms in C or Python. 
I'm going to focus on algorithmic ideas mainly.

Importing Packages:

     These are some basic in-built packages required to be imported:

1.java.awt.*;
2.java.awt.image.*;
3.java.io.*;
4.javax.imageio.*;

Making life a little easier!

     IDE s are a really important part of a programmer's life. For Java, I always prefer NetBeans.
And if you are using NetBeans too, then I must say that to directly access an image by its name only,
keep the image in the Project level, that is, one level above the src folder.

Loading an Image:

Code:
         BufferedImage OrigImg,EditImg;
         public void loadImage(String fileName){
             try{
                 OrigImg=ImageIO.read(new File(fileName));
             }catch(IOException e){System.out.println("could not load the image");}
             EditImg=OrigImg;
         }

Explanation:
     As you can see, Java stores images as a class named BufferedImage. Here, "fileName" is the name of the image(with its extension), that is to be loaded. As soon as we read the original file, we copy it, so that we can use the original image data even after manipulating the original buffered image, "EditImg".

Saving an Image:

Code:
     public void saveImage(BufferedImage img,String ref){
             processImage(img);
             try{
                 String format=(ref.endsWith("png"))?"png":"jpg";
                 ImageIO.write(img, format,new File(ref));
             }catch(IOException e){e.printStackTrace();}
     }

Explanation:
     First of all, you can now ignore the "processImage(img);" statement for now. Here, "ref " is the name of the image file in which you want it to be saved. The code suggests that ref must include the extension of the file too(for example, "image1.jpg").

Getting Image Parameters:

Code:
     img.getWidth();
     img.getHeight();

Remember: The parameters are returned as pixels.

Getting the Pixel Array:

If you are already familiar with Image Processing, you know that we need a pixel array of an image to process it. Normally, its a 2D array provided by most APIs(Exception: Some python API, as in Blender3D, pixel array is 1D).
Code:
     int[][] result=new int[width][height];
        for(int row=0;row<height;row++){
            for(int col=0;col<width;col++){
                result[col][row]=img.getRGB(col, row);
            }
        }

Here, "result" is the pixel array. "img.getRGB(col, row)" extracts the RGB values of the pixel defined by the address [col][row].
Remember: First col, then row!

Extracting red,blue,green values from RGB value:

Code:
     result[col][row]=img.getRGB(col, row);
     Color c=new Color(result[col][row]);
     int red=c.getRed();
     int blue=c.getBlue();
     int green=c.getGreen();

The Color class can be initialized with either an RGB value or a set of three parameters(ie, red, blue, green). Here, since we had the RGB value, so we did the first case.

Setting the new value of a pixel:

Now, after manipulation of the red, blue, green values, we need to set them to the each respective pixels of the image to be saved. The code is as follows:
     c=new Color(red,green,blue);
     img.setRGB(col,row,c.getRGB());


What's next??

     Next, we will be covering some basic image processing algorithms and codes. 

                                                                       NEXT>>