Home > Back-end >  C# .Net Emgu.CV is inconsistently transferring bytes to itself
C# .Net Emgu.CV is inconsistently transferring bytes to itself

Time:03-14

I'm using Emgu.CV to templateMatch and to save Images. Unfortunetly I have ran into an issue that I have no been able to solve for a weeks.

Problem is that i serialize byte array and size from original Image to json file, and whenever i try to convert it back sometimes the image is distorted. I have already tried skipping over serializing procces and it still became distorted. Here is code of converting procces:

            Image<Bgr565, byte> screenCrop = SnipMaker.takeSnip();//method creates screenshot at this point when i display the images they are 100% correct

            byte[] data = screenCrop.Bytes;//I would get normaly all this from json file(in this case im skipping over it)

            Mat mat = new Mat(screenCrop.Rows, screenCrop.Cols, screenCrop.Mat.Depth, asset.NumberOfChannels);

            Marshal.Copy(data, 0, mat.DataPointer, screenCrop.asset.Cols * screenCrop.asset.Rows * asset.NumberOfChannels);

            Image<Bgr565, byte> img = mat.ToImage<Bgr565, byte>();//This image is suddenly distorted

Problem is that this results depending on "I'm not sure what" is either prefecly good image or skwed one:

normal result

same code different result

Its almost like its sometimes 1 pixel behind but only thing that is changing is size and dimentions of screen shots. I have tried dirrect ways like

Image<Bgr, byte> img = new Image<Bgr, byte>(width, height);
img.Bytes = data;//data is byte array that i got from file

This also gives sometimes correct picture but other times it throws an exeption (out of range exception in marshal.cs when trying to copy bytes from data to img)

only thing that i suspect at this point is that im doing something wrong whenever im taking screenshot but im not sure what:

public static Image<Bgr565, byte> Snip()
    {
        int screenWidth = (int)System.Windows.SystemParameters.PrimaryScreenWidth;
        int screenHeight = (int)System.Windows.SystemParameters.PrimaryScreenHeight;
        using (Bitmap bmp = new Bitmap(screenWidth, screenHeight))
        {
            using (Graphics gr = Graphics.FromImage(bmp))
                gr.CopyFromScreen(0, 0, 0, 0, bmp.Size);

            using (var snipper = new SnippingTool(bmp))
            {
                if (snipper.ShowDialog() == true)
                {
                    Bitmap bitmapImage = new Bitmap(snipper.Image);

                    Rectangle rectangle = new Rectangle(0, 0, bitmapImage.Width, bitmapImage.Height);//System.Drawing
                    BitmapData bmpData = bitmapImage.LockBits(rectangle, ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format24bppRgb);//System.Drawing.Imaging

                    Image<Bgr565, byte> outputImage = new Image<Bgr565, byte>(bitmapImage.Width, bitmapImage.Height, bmpData.Stride, bmpData.Scan0);

                    bitmapImage.Dispose();
                    snipper.Close();
                    return outputImage;
                }
            }
            return null;
        }
    }

So far I have not been able to solve this and knowing my luck noone will proppably anwser me here. But please could someone help me with this? Thank you in advance

CodePudding user response:

So thank you to everyones help.

The issue was indeed in the screenshot script. I've used incorrect combination of pixel formats which resulted in inconsistent bit transfer. But because the step property in Image<bgr,byte>.Mat was calculated based on the width of the image (Emgucv SC):

step = sizeof(byte) * s.Width * channels;

It caused that some of the images looked normal and other didn't.(speculation based on observation)

Fix: change all Image<Bgr, byte> to Image<Bgra, byte> to make it 32bit and then change:

BitmapData bmpData = bitmapImage.LockBits(rectangle, ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format24bppRgb);

to:

BitmapData bmpData = bitmapImage.LockBits(rectangle, ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppRgb);

Hope this will help someone in the future. : )

  • Related