Search code examples
javaimageimage-processinggenetic-algorithmnoise

How to reduce the error of the noise image using genetic algorithm?


The question says, given a noise image (lena_noise) and original image (lena_original), the programmer is asked to design and implement a program that minimize the noise by given mathematical formula using Genetic algorithm.

my problem is that my program works bad, really really bad. it means that when I start with lena_noise, then it should after a while the program give me the original image, but unfortunately it gives an image worse than lena_noise. so I thought that my noise program have a problem. So, I hope find a keypoint to find how to reduce the noise using Genetic algorithm?

 private int[][] Performing_Noise_into_grayscale_image(Storing_Images SI)
{
    this.Generate_New_Random_for_3_parameters();
    int [][] nose = new int[SI.heigth][SI.width];
    for (int row = 0; row < SI.heigth; row++) 
    {
        for (int col = 0; col < SI.width; col++) 
        {
            double no =  this.NoiseAmp*sin((2*Math.PI*this.NoiseFreqCol*row) + (2*Math.PI*this.NoiseFreqCol*col));
            int value = SI.Array[row][col];

            int alph = (value >> 24) & 0xff;
            int red = (value >> 16) & 0xff;
            int green = (value >> 8) & 0xff;
            int blue = value & 0xff;
            int avg = (red+green+blue)/3;

            alph = ((int)no) | (alph << 24);
            red = ((int) no) | (avg << 16);
            green = ((int) no) | (avg << 8);
            blue = ((int) no) | avg;

            int value2 = 0;
            value2 = (alph<<24) | (red<<16) | (green<<8) | blue;
            nose[row][col] = value2; 
        }
    }
    return nose;
}

the function Generate_New_Random_for_3_parameters() it is just a function that gives a random double number between 0-30 for 3 variables. These 3 variables are (NoiseAmp, NoiseFreqCol, NoiseFreqCol) used in the mathematical formula.

Storing_Images have three attributes, these are (int [][] Array, int height, int width)

Notice that the image is grayscale image, this is why we take the average value.


Brief about the program

the program have four parameters, these are as following: Crossover_probability = 0.3, mutation_probability = 0.05, number_of_population = 4, number_of_generations = 10. if you are not familiar with these parameters, then take a look at Introduction to Genetic Algorithm. So, the program begins with receiving the lena_noise and apply on it the mathematical formula for all population (each one of the population have its own random double number of mathematical formula), then we select the best one, that is the one that have less error comparing with the lena_original. then the best one is the one that would survive for next generation. On the next generation, we apply a the mathematical formula for all population, and then we select the best one that have a few error as possible comparing to the lena_original image. etc.


the Fitness function is as follows,

public Storing_Images[] Fitness()
{
    Storing_Images errorSSI [] = new Storing_Images[4];
    for (int i = 0; i < (this.Childs.length) ; i++)
    {
        //choose the best one among 4
        //the best one is the one that have the minimum error from the orginal image.
        int [][] error = IP.Compare_OriginalImage_with_given_Image(Childs[i].Array);
        errorSSI[i] = new Storing_Images(error,512,512);
    }
   int value=0;
   int Sum [] = new int[4];
   for (int i = 0; i < (this.Childs.length) ; i++)
   {
       for (int row = 0; row < IP.width; row++) 
       {
          for (int col = 0; col < IP.height; col++) 
          {
              int val = errorSSI[i].Array[row][col];
              if ( val < 0 )
                  val = val * -1;
              value = value + val;
          }
       }
       double x = (value/(IP.width * IP.height));
       Sum[i] = (int) x;
       value =0;

   }
   int Mini=Sum[0];
   int posi_of_mini= 0;
  // int pos2=0;
   for (int k = 0; k < Sum.length; k++)
   {
       if ( Sum[k] < Mini )
       {
         //  pos2 = Mini;
           Mini = Sum[k];
           posi_of_mini = k;
       }
   }
   this.Childs[0] = Childs[posi_of_mini];
   this.Childs[1] = Childs[posi_of_mini];
   this.Childs[2] = Childs[posi_of_mini];
   this.Childs[3] = Childs[posi_of_mini];

   return Childs;

}

about the function that do comparing between lena_original and the one of the population.

 public int [][] Compare_OriginalImage_with_given_Image(int [][] current) 
{
  int [][] error = new int [this.height][this.width];

  for (int row = 0; row < height; row++) 
  {
     for (int col = 0; col < width; col++) 
     {
         int value1 = this.Orginal[row][col];
         int value2 = current[row][col];
         //I need to put absolute value for either value 1 and value2
         if (value1 < 0)
             value1 = value1 *-1;
         if(value2 < 0)
             value2 = value2 * -1;
         //int min = Math.min(value1, value2);
         int er = value2 - value1;
         error[row][col] = er;

     }
  }
  return error;

}

Reference.

*similar question to my question but no details about the answer is from this page Image processing using genetic algorithm

*How to convert a color image into grayscale image in Java this pages tells us about how to deal with grayscale image and playing with it.


feel free to ask a questions about the problem. Also, any comments, hints, etc are welcome. Thank you


Solution

  • Try this to create a grey image:

    public static void makeGray(BufferedImage img)
    {
        for (int x = 0; x < img.getWidth(); x++) {
            for (int y = 0; y < img.getHeight(); y++) {
                int rgb = img.getRGB(x, y);
                int r = (rgb >> 16) & 0xFF;
                int g = (rgb >> 8) & 0xFF;
                int b = (rgb & 0xFF);
    
                int grayLevel = (r + g + b) / 3;
                int gray = (grayLevel << 16) + (grayLevel << 8) + grayLevel; 
                img.setRGB(x, y, gray);
            }
        }
    }
    

    Now, you need a way to combine 2 elements from your population. it doesn't matter how, so for the sake of the example, I split the image evenly:

    for (int x = 0; x < img1.getWidth() / 2; x++) 
        for (int y = 0; y < img1.getHeight(); y++) 
            // build 1st half of the result image 
    
    for (int x = img2.getWidth() / 2; x < img2.getWidth(); x++) 
        for (int y = 0; y < img2.getHeight(); y++) 
            // build 2nd half of the result image
    

    You also need to take into account the mutation rate which can change random elements on the result image. (do that later)