2012-12-22 21 views
7

Ho provato a fare OCR da perceptrons con Aforge.Net in C#. Ho imparato la mia rete con nove immagini 30 * 30 in binario. Ma nei risultati, riconosce tutto come "C". questo è il codice:OCR con rete neurale perceptron di Aforge.net risposte errate

private void button1_Click(object sender, EventArgs e) 
    { 
     AForge.Neuro.ActivationNetwork network = new AForge.Neuro.ActivationNetwork(new AForge.Neuro.BipolarSigmoidFunction(2), 900, 3); 
     network.Randomize(); 
     AForge.Neuro.Learning.PerceptronLearning learning = new AForge.Neuro.Learning.PerceptronLearning(network); 
     learning.LearningRate =1 ; 
     double[][] input = new double[9][]; 
     for (int i = 0; i < 9; i++) 
     { 
      input[i] = new double[900]; 
     } 
    //Reading A images 
     for (int i = 1; i <= 3; i++) 
     { 
      Bitmap a = AForge.Imaging.Image.FromFile(path + "\\a" + i + ".bmp"); 
      for (int j = 0; j < 30; j++) 
       for (int k = 0; k < 30; k++) 
       { 
        if (a.GetPixel(j, k).ToKnownColor() == KnownColor.White) 
        { 
         input[i-1][j * 10 + k] = -1; 
        } 
        else 
         input[i-1][j * 10 + k] = 1; 
       } 
      // showImage(a); 

     } 
    //Reading B images 
     for (int i = 1; i <= 3; i++) 
     { 
      Bitmap a = AForge.Imaging.Image.FromFile(path + "\\b" + i + ".bmp"); 
      for (int j = 0; j < 30; j++) 
       for (int k = 0; k < 30; k++) 
       { 
        if (a.GetPixel(j , k).ToKnownColor() == KnownColor.White) 
        { 
         input[i + 2][j * 10 + k] = -1; 
        } 
        else 
         input[i + 2][j * 10 + k] = 1; 
       } 
      // showImage(a); 

     } 
    //Reading C images 
     for (int i = 1; i <= 3; i++) 
     { 
      Bitmap a = AForge.Imaging.Image.FromFile(path + "\\c" + i + ".bmp"); 
      for (int j = 0; j < 30; j++) 
       for (int k = 0; k < 30; k++) 
       { 
        if (a.GetPixel(j , k).ToKnownColor() == KnownColor.White) 
        { 
         input[i + 5][j * 10 + k] = -1; 
        } 
        else 
         input[i + 5][j * 10 + k] = 1; 
       } 
      // showImage(a); 

     } 

     bool needToStop = false; 
     int iteration = 0; 
     while (!needToStop) 
     { 
      double error = learning.RunEpoch(input, new double[9][] { new double[3] { 1, -1, -1 },new double[3] { 1, -1, -1 },new double[3] { 1, -1, -1 },//A 
       new double[3] { -1, 1, -1 },new double[3] { -1, 1, -1 },new double[3] { -1, 1, -1 },//B 
       new double[3] { -1, -1, 1 },new double[3] { -1, -1, 1 },new double[3] { -1, -1, 1 } }//C 
        /*new double[9][]{ input[0],input[0],input[0],input[1],input[1],input[1],input[2],input[2],input[2]}*/ 
       ); 
      //learning.LearningRate -= learning.LearningRate/1000; 
      if (error == 0) 
       break; 
      else if (iteration < 1000) 
       iteration++; 
      else 
       needToStop = true; 
      System.Diagnostics.Debug.WriteLine("{0} {1}", error, iteration); 
     } 
     Bitmap b = AForge.Imaging.Image.FromFile(path + "\\b1.bmp"); 
    //Reading A Sample to test Netwok 
     double[] sample = new double[900]; 
     for (int j = 0; j < 30; j++) 
      for (int k = 0; k < 30; k++) 
      { 
       if (b.GetPixel(j , k).ToKnownColor() == KnownColor.White) 
       { 
        sample[j * 30 + k] = -1; 
       } 
       else 
        sample[j * 30 + k] = 1; 
      } 
     foreach (double d in network.Compute(sample)) 
      System.Diagnostics.Debug.WriteLine(d);//Output is Always C = {-1,-1,1} 
    } 

volevo sapere perché risposte sbagliate.

+0

Ciao, hai trovato una soluzione per questo problema? –

risposta

3

Durante il caricamento delle immagini 30x30 iniziali in un doppio array [900] nella struttura input si sta utilizzando il seguente calcolo:

for (int j = 0; j < 30; j++) 
    for (int k = 0; k < 30; k++) 
    { 
     if (a.GetPixel(j, k).ToKnownColor() == KnownColor.White) 
      input[i-1][j * 10 + k] = -1; 
     else 
      input[i-1][j * 10 + k] = 1; 
    } 

il calcolo offset è sbagliato qui. Devi cambiare j * 10 + k a j * 30 + k o otterrai risultati non validi. Successivamente si utilizza il calcolo dell'offset corretto durante il caricamento dell'immagine di prova, motivo per cui non viene corrisposto correttamente ai campioni danneggiati.

Si dovrebbe scrivere un metodo per caricare un bitmap in un array double[900] e chiamarlo per ogni immagine, invece di scrivere lo stesso codice più volte. Questo aiuta a ridurre problemi come questo, dove i risultati differenti sono dati da due pezzi di codice che dovrebbero restituire lo stesso risultato.

1

Ho provato il tuo codice. Mi ha aiutato anche me e grazie mille per questo. Potrei far funzionare il codice eseguendo alcune modifiche per ottenere l'array di bit dall'immagine. Ecco il metodo che ho usato.

` 
     private double[] GetImageData(Bitmap bmp) 
     { 
     double[] imageData = null; 

     //Make the image grayscale 
     Grayscale filter = new Grayscale(0.2125, 0.7154, 0.0721); 
     bmp = filter.Apply(bmp); 

     //Binarize the image 
     AForge.Imaging.Filters.Threshold thFilter = new AForge.Imaging.Filters.Threshold(128); 
     thFilter.ApplyInPlace(bmp); 

     int height = bmp.Height; 
     int width = bmp.Width; 
     imageData = new double[height * width]; 
     int imagePointer = 0; 
     System.Diagnostics.Debug.WriteLine("Height : " + height); 
     System.Diagnostics.Debug.WriteLine("Width : " + width); 

     for (int i = 0; i < height; i++) 
     { 
      for (int j = 0; j < width; j++) 
      { 
       System.Diagnostics.Debug.Write(string.Format("({0} , {1})  Color : {2}\n", i, j, bmp.GetPixel(i, j))); 

       //Identify the black points of the image 
       if (bmp.GetPixel(i, j) == Color.FromArgb(255, 0, 0, 0)) 
       { 
        imageData[imagePointer] = 1; 
       } 
       else 
       { 
        imageData[imagePointer] = 0; 
       } 
       imagePointer++; 
      } 
      System.Diagnostics.Debug.WriteLine(""); 
     } 
     System.Diagnostics.Debug.WriteLine("Bits : " + imagePointer); 
     return imageData; 
    }` 

Spero che questo possa essere d'aiuto. Grazie.

0

provare questo

double error = learning.RunEpoch(input, new double[9][] { new double[3] **{ 1, -1, -1 }**,new double[3] **{ -1, 1, -1 }**,new double[3] **{ -1, -1, 1 }**,//A 
       new double[3] **{ 1, -1, -1 }**,new double[3] **{ -1, 1, -1 }**,new double[3] **{ -1, -1, 1 }**,//B 
       new double[3] **{ 1, -1, -1 }**,new double[3] **{ -1, 1, -1 }**,new double[3] **{ -1, -1, 1 }** }//C 

       ); 

o così

double[][] output = new double[patterns][]; 
      for (int j = 0; j < patterns; j++) 
      { 
       output[j] = new double[patterns]; 
       for (int i = 0; i < patterns; i++) 
       { 
        if (i != j) 
        { 
         output[j][i] = -1; 
        } 
        else 
        { 
         output[j][i] = 1; 
        } 
       } 
      } 


double error = learning.RunEpoch(input,output) 

double[] netout = neuralNet.Compute(pattern); 

int maxIndex = 0; 
      double max = netout[0]; 

      for (int i = 1; i < netout.Length; i++) 
      { 
       if (netout[i] > max) 
       { 
        max = netout[i]; 
        maxIndex = i; 
       } 
      } 

se MaxIndex = 0 risposta è A

se MaxIndex = 1 risposta è B

se MaxIndex = 2 risposta è C

anche Penso che è necessario creare matrice da immagini e usarlo come modello, ad esempio 20/20 o 15/15 o piccolo, la vostra 30/30 è grande.

Io uso un modo diverso per ottenere Schema di immagine. I Divide immagine 20/20 e Se uno dei pixel nel rettangolo è nero (o altro colore desiderato) salva 1 in matrice, altrimenti 0.

Faccio sostituire tutti i pixel e dopo questo ho solo due colori, Bianco e nero, posso manipolare con il contorno.

private void Cmd_ReplaceColors(ref WriteableBitmap Par_WriteableBitmap,int Par_Limit=180) 
     { 

      for (int y = 0; y < Par_WriteableBitmap.PixelHeight; y++) 
      { 
       for (int x = 0; x < Par_WriteableBitmap.PixelWidth; x++) 
       { 

        Color color = Par_WriteableBitmap.GetPixel(x, y); 

        if (color == Colors.White) 
        { 

        } 
        else 
        { 
         if (color.R < Par_Limit) 
         { 
          Par_WriteableBitmap.SetPixel(x, y, Colors.Black); 
         } 
         else 
         { 
          Par_WriteableBitmap.SetPixel(x, y, Colors.White); 
         } 

        } 

       } 
      } 

      Par_WriteableBitmap.Invalidate(); 
     } 

1000 iterazioni a mio parere è piccolo, meglio 100 000 :)

Problemi correlati