Search code examples
c#bitmapcomparisonlockbits

Comparing images using lockbits not functioning correctly


I am trying to perform a basic number-only OCR on an image by comparing it to bitmaps of the numbers 0 - 9, using the code below. I have tried to follow the code in the answer to this question, but it is not returning the correct results. There are 2 main issues that I am facing:

1: If the program determines that the number 0 is present at any given point, then it also determines that 1, 2, 3, ... , and 9 are present at that location, which is obviously not true.

2: The locations that it finds numbers in ... most of the locations are blank (white) spaces.

I'll be the first to admit that using the lockbits method is new to me, as I usually use the getPixel() method of comparing, but it was far too slow for this project, so I may be making a rookie mistake or 2.

Thanks for the help!!!

P.S. The image to OCR is RTA, and I believe everything else is self-explanatory.

void newOCR()
    {
        Rectangle rect = new Rectangle(0, 0, 8, 9);
        Rectangle numRect = new Rectangle(0, 0, 8, 9);

        for (int i = 0; i < RTA.Width - 8; i++)
        {
            for (int j = 0; j < RTA.Height - 9; j++)
            {
                rect.Location = new Point(i, j);
                for (int n = 0; n < numbers.Length; n++)
                {
                    System.Drawing.Imaging.BitmapData data = RTA.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadOnly, RTA.PixelFormat);
                    System.Drawing.Imaging.BitmapData numData = numbers[n].LockBits(numRect, System.Drawing.Imaging.ImageLockMode.ReadOnly, numbers[n].PixelFormat);

                    unsafe
                    {
                        byte* ptr = (byte*)data.Scan0.ToPointer();
                        byte* numPtr = (byte*)data.Scan0.ToPointer();

                        int width = rect.Width * Image.GetPixelFormatSize(data.PixelFormat) / 8;
                        for(int y = 0; y < rect.Height; y++)
                        {
                            bool outBreak = false;
                            for(int x = 0; x < width; x++)
                            {
                                if(*ptr != *numPtr)
                                {
                                    outBreak = true;
                                    break;
                                }
                                else if(y == rect.Height - 1 && x == width - 1)
                                {
                                    timeDict.Add(new Point(i, j), n);
                                }

                                ptr++;
                                numPtr++;
                            }

                            if(outBreak)
                            {
                                break;
                            }

                            ptr += data.Stride - width;
                            numPtr += numData.Stride - width;
                        }

                        RTA.UnlockBits(data);
                        numbers[n].UnlockBits(numData);
                    }
                }
            }
        }
    }

Solution

  • There is a (probably copy/paste) mistake in the following line

    byte* numPtr = (byte*)data.Scan0.ToPointer();
    

    which is causing comparing the bitmap to itself. It should be

    byte* numPtr = (byte*)numData.Scan0.ToPointer();