2012-12-22 10 views
7

Próbowałem zrobić OCR przez perceptron z Aforge.Net w C#. Nauczyłem się mojej sieci z dziewięcioma 30 * 30 obrazami w formacie binarnym. Ale w wynikach rozpoznaje wszystko jako "C". jest to kod:OCR z siecią neuronową perceptronu Aforge.net odpowiada błędnie

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

naprawdę chciałem wiedzieć, dlaczego odpowiedzi błędne.

+0

Witam, Czy można znaleźć rozwiązanie tego problemu? –

Odpowiedz

3

Podczas ładowania początkowych 30x30 obrazy w podwójnym [900] tablicy w strukturze input używasz następującego obliczenia:

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

Twój przesunięcie kalkulacja jest nie tak tutaj. Musisz zmienić j * 10 + k na j * 30 + k, inaczej uzyskasz nieprawidłowe wyniki. Później użyjesz prawidłowego obliczenia przesunięcia podczas ładowania obrazu testowego, dlatego nie jest ono poprawnie dopasowane do uszkodzonych próbek.

Powinieneś napisać metodę załadowania mapy bitowej do tablicy double[900] i wywołać ją dla każdego obrazu, zamiast wielokrotnie pisać ten sam kod. Pomaga to zmniejszyć takie problemy, w których różne wyniki dają dwa fragmenty kodu, które powinny zwrócić ten sam wynik.

1

Wypróbowałem twój kod. Pomógł mi też i bardzo dziękuję za to. Mogę sprawić, aby twój kod działał, wykonując pewne zmiany, aby uzyskać bitową tablicę z obrazu. Oto metoda, której użyłem.

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

Mam nadzieję, że to pomoże. Dzięki.

0

spróbować tej

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 

       ); 

lub ten sposób

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

jeśli maxIndex = 0 Odpowiedź jest

jeśli maxIndex = 1 odpowiedź B

jeśli maxIndex = 2 Odpowiedź jest C

także myślę, że należy utworzyć macierz z obrazów i używać go jako wzór, na przykład 20/20 lub 15/15 lub mała, twój 30/30 jest duża.

Używam innego sposobu, aby uzyskać Schemat Obrazu. I Podziel obraz 20/20 i Jeśli jeden z pikseli w prostokącie jest czarny (lub inny wybrany kolor), zapisz 1 w macierzy, w przeciwnym razie 0.

Wymieniam wszystkie piksele, a potem mam tylko dwa kolory, Biały i Czarny, mogę manipulować konturem.

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 iteracji moim zdaniem jest niewielka, lepiej 100 000 :)