从 byte[] 创建图像时 C#/EmguCv 参数超出范围异常

C# / EmguCv Argument Out of Range exception when creating images from byte[]

我尝试在 edgeimages 上使用 MatchTemplate 来查找图像中的教学对象。作为图像源,我使用 kinect2。我首先教一个边缘图像并在后来捕获的图像中搜索教过的模板。用 canny 计算边缘图像效果很好。我将边保存为 byte[] with

byte[] bytes = cannyFrame.GetData();

稍后我尝试使用给定的数据创建图像。不幸的是,有时创建图像会在 ArgumentOutOfRange-Exception 中运行并声称数组太大。有时会发生异常,有时不会发生。创建当前图像以及创建教学图像时都可能发生异常(请参阅我的代码中的注释)。谁能告诉我,为什么会出现这个异常?

        Bitmap bmp; 

        //bmp is filled with the image from the kinect

        int width;
        int height;
        byte[] currentEdges = EdgeDetector.CalculateEdges(bmp, referenceImage.BorderOne, referenceImage.BorderTwo, out width, out height);
        try
        {
            Console.WriteLine("ref width: {0}, height: {1}, byte[]length: {2}", referenceImage.Width_px, referenceImage.Height_px, referenceImage.Edges.Length);                
            //Here happens the exception sometimes: 
            Image<Gray, byte> templateImage = new Image<Gray, byte>(referenceImage.Width_px, referenceImage.Height_px);
            templateImage.Bytes = referenceImage.Edges;
            Console.WriteLine("current image width: {0}, height: {1}, byte[]length: {2}", width, height, currentEdges.Length);

            //Here happens the exception sometimes: 
            Image<Gray, byte> searchImage = new Image<Gray, byte>(width, height);
            searchImage.Bytes = currentEdges;
            Console.WriteLine("");
            Image<Gray, float> imgMatch = searchImage.MatchTemplate(templateImage, TemplateMatchingType.CcoeffNormed);
            }
        catch (Exception)
        {                
            Console.WriteLine(ex.ToString());
        }


    internal class EdgeDetector
    {
        internal static byte[] CalculateEdges(Bitmap bmp, int borderOne, int borderTwo, out int width, out int height)
        {
            try
            {
                Image<Bgr, byte> img = new Image<Bgr, byte>(bmp);

                Mat smallGrayFrame = new Mat();
                Mat smoothedGrayFrame = new Mat();
                Mat cannyFrame = new Mat();

                CvInvoke.PyrDown(img, smallGrayFrame);

                CvInvoke.PyrUp(smallGrayFrame, smoothedGrayFrame);

                CvInvoke.Canny(smoothedGrayFrame, cannyFrame, borderOne, borderTwo);

                byte[] bytes = cannyFrame.GetData();

                width = cannyFrame.Width;
                height = cannyFrame.Height;

                return bytes;
            }
            catch (Exception ex)
            {
                width = 0;
                height = 0;
                return null;
            }
        }

示例输出: 参考宽度:46,高度:44,字节[]长度:2024 System.ArgumentOutOfRangeException:请求的范围超出了结尾 大批。 在 System.Runtime.InteropServices.Marshal.CopyToNative(对象源,Int32 s tartIndex、IntPtr 目标、Int32 长度) 在 Emgu.CV.CvArray`1.set_Bytes(字节 [] 值) 在 AlgorithmsHelper.SearchEdgeImage(AssistentEdgeImageOpenCv referenceImage, Image currentImage)

感谢任何帮助。

我仍然不知道为什么会出现异常,但我已经找到了一个解决方案作为解决方案。就像 http://www.emgu.com/wiki/index.php/Working_with_Images 建议我创建一个垫子,用字节填充它并从垫子创建图像 工作正常。

            Mat currentMat;
            using (MemoryStream memoryStream = new MemoryStream(currentEdges))
            {
                byte[] rawData = new byte[memoryStream.Length];
                memoryStream.Read(rawData, 0, (int)memoryStream.Length);

                GCHandle rawDataHandle = GCHandle.Alloc(rawData, GCHandleType.Pinned);
                IntPtr address = rawDataHandle.AddrOfPinnedObject();

                currentMat = new Mat(new System.Drawing.Size(width, height), DepthType.Cv8U, 1, address, width);
                rawDataHandle.Free();
            }
            Image<Gray, byte> currentImage = currentMat.ToImage<Gray, byte>();

            Mat templateMat;
            using (MemoryStream memoryStream = new MemoryStream(referenceImage.Edges))
            {
                byte[] rawData = new byte[memoryStream.Length];
                memoryStream.Read(rawData, 0, (int)memoryStream.Length);

                GCHandle rawDataHandle = GCHandle.Alloc(rawData, GCHandleType.Pinned);
                IntPtr address = rawDataHandle.AddrOfPinnedObject();

                templateMat = new Mat(new System.Drawing.Size(referenceImage.Width_px, referenceImage.Height_px), DepthType.Cv8U, 1, address, referenceImage.Width_px);
                rawDataHandle.Free();
            }
            Image<Gray, byte> templateImage = templateMat.ToImage<Gray, byte>();

            Image<Gray, float> imgMatch = currentImage.MatchTemplate(templateImage, TemplateMatchingType.CcoeffNormed);