OCR with perceptron neural network of Aforge.net answers wrong

I tried to make OCR by perceptrons with Aforge.Net in C#. I learned my network with nine 30*30 pictures in binary. But in the results, it recognizes everything as 'C'. this is the code:

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

I really wanted to know why it answers wrong.


While loading your initial 30x30 images into a double[900] array in the input structure you are using the following calculation:

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

Your offset calculation is wrong here. You need to change j * 10 + k to j * 30 + k or you will get invalid results. Later you use the correct offset calculation while loading the test image, which is why it's not being matched correctly against the corrupted samples.

You should write a method to load a bitmap into a double[900] array and call it for each image, instead of writing the same code multiple times. This helps to reduce problems like this, where different results are given by two pieces of code that should return the same result.


I tried your code. It helped me too and thanks a lot for that. I could get your code working by doing some changes to getting bit array from the image. Here's the method I used.

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

Hope this will help. Thanks.


try this

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

                );

or this way

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

if maxIndex=0 answer is A

if maxIndex=1 answer is B

if maxIndex=2 answer is C

also I think that you must create matrix from images and use it as pattern, for example 20/20 or 15/15 or small, your 30/30 is big.

I use different way for get Image Scheme. I Divide image 20/20 and If one of pixels in rectangle is black (or another colour you want) save 1 in matrix, else 0.

I make replace all pixels an after this I have only two colours, White and Black, I can manipulate with contour.

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 iterations in my opinion is small, better 100 000 :)

链接地址: http://www.djcxy.com/p/67760.html

上一篇: 与GDI +进行高级颜色混合

下一篇: OCR与感知器神经网络Aforge.net答案错误