2012-12-22 4 views
7

Ich habe versucht, OCR Perceptrons mit Aforge.Net in C#. Ich habe mein Netzwerk mit neun 30 * 30 Bildern in Binärform gelernt. Aber in den Ergebnissen erkennt es alles als "C". Dies ist der Code:OCR mit Perzeptron neuronales Netzwerk von Aforge.net antwortet falsch

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} 
    } 

Ich wollte wirklich wissen, warum es falsch beantwortet.

+0

Hallo, Haben Sie eine Lösung für dieses Problem zu finden? –

Antwort

3

Im Laufe der ersten 30x30 Bilder in ein Doppel [900] Array in der input Struktur Laden Sie die folgende Berechnung verwenden:

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; 
    } 

Ihre Offset-Berechnung ist hier falsch. Sie müssen j * 10 + k zu j * 30 + k ändern oder Sie werden ungültige Ergebnisse erhalten. Später verwenden Sie beim Laden des Testbildes die korrekte Offset-Berechnung, weshalb es nicht korrekt mit den beschädigten Proben übereinstimmt.

Sie sollten eine Methode schreiben, um eine Bitmap in ein Array double[900] zu laden und für jedes Bild aufzurufen, anstatt denselben Code mehrmals zu schreiben. Dies hilft, Probleme wie diese zu reduzieren, bei denen unterschiedliche Ergebnisse durch zwei Codeabschnitte gegeben sind, die das gleiche Ergebnis liefern sollten.

1

Ich habe Ihren Code versucht. Es hat mir auch geholfen und vielen Dank dafür. Ich könnte Ihren Code zum Laufen bringen, indem Sie einige Änderungen vornehmen, um Bit-Array aus dem Bild zu bekommen. Hier ist die Methode, die ich verwendet habe.

` 
     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; 
    }` 

Hoffe, das wird helfen. Vielen Dank.

0

versuchen dieses

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 

       ); 

oder diese Weise

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; 
       } 
      } 

wenn MaxIndex = 0 Antwort A

ist, wenn MaxIndex = 1 Antwort B

ist

wenn MaxIndex = 2 Antwort C ist

auch denke ich, dass Sie Matrix aus Bildern erstellen müssen und sie als Muster verwenden, zum Beispiel 20/20 oder 15/15 oder klein, Ihr 30/30 ist groß.

Ich benutze unterschiedliche Weise für Image Schema. I Teilen Sie Bild 20/20 und Wenn eines der Pixel im Rechteck schwarz ist (oder eine andere Farbe) speichern Sie 1 in der Matrix, sonst 0.

Ich mache alle Pixel zu ersetzen und danach habe ich nur zwei Farben, Weiß und Schwarz kann ich mit Kontur manipulieren.

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 Iterationen meiner Meinung nach ist klein, besser 100 000 :)

Verwandte Themen