【问题标题】:OCR with perceptron neural network of Aforge.net answers wrong带有 Aforge.net 感知器神经网络的 OCR 回答错误
【发布时间】:2012-12-09 20:53:55
【问题描述】:

我尝试使用 C# 中的 Aforge.Net 通过感知器制作 OCR。我用九张 30*30 的二进制图片学习了我的网络。但在结果中,它将所有内容都识别为“C”。 这是代码:

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

我真的很想知道为什么它回答错了。

【问题讨论】:

  • 您好,您找到解决此问题的方法了吗?

标签: c# artificial-intelligence neural-network ocr aforge


【解决方案1】:

试试这个

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

                );

或者这样

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

如果 maxIndex=0 答案是 A

如果 maxIndex=1 答案是 B

如果 maxIndex=2 答案是 C

我也认为您必须从图像创建矩阵并将其用作图案,例如 20/20 或 15/15 或更小,您的 30/30 很大。

我使用不同的方式获取图像方案。 我将图像分割为 20/20,如果矩形中的一个像素是黑色(或您想要的另一种颜色),则在矩阵中保存 1,否则为 0。

我替换所有像素,然后我只有两种颜色,白色和黑色,我可以用轮廓进行操作。

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 次迭代很小,最好 100 000 :)

【讨论】:

    【解决方案2】:

    我试过你的代码。它也帮助了我,非常感谢。我可以通过对从图像中获取位数组进行一些更改来使您的代码正常工作。这是我使用的方法。

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

    希望这会有所帮助。谢谢。

    【讨论】:

      【解决方案3】:

      在将初始 30x30 图像加载到 input 结构中的 double[900] 数组中时,您正在使用以下计算:

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

      您的偏移量计算在这里是错误的。您需要将j * 10 + k 更改为j * 30 + k,否则您将得到无效结果。稍后您在加载测试图像时使用正确的偏移量计算,这就是它无法与损坏的样本正确匹配的原因。

      您应该编写一个方法来将位图加载到double[900] 数组中并为每个图像调用它,而不是多次编写相同的代码。这有助于减少这样的问题,即两段应该返回相同结果的代码给出不同的结果。

      【讨论】:

        猜你喜欢
        • 2019-03-10
        • 2011-01-29
        • 2011-08-13
        • 2015-01-27
        • 1970-01-01
        • 2017-04-25
        • 2014-03-06
        • 2014-12-02
        • 2015-01-17
        相关资源
        最近更新 更多