从byte []

时间:2017-05-02 07:38:26

标签: c# opencv emgucv

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

byte[] bytes = cannyFrame.GetData();

稍后我尝试使用给定的数据创建Image。不幸的是,有时候创建图像会在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;
            }
        }

示例输出: ref width:46,height:44,byte [] length:2024 System.ArgumentOutOfRangeException:请求的范围超出了结尾 阵列。    在System.Runtime.InteropServices.Marshal.CopyToNative(Object source,Int32 s) tartIndex,IntPtr目的地,Int32长度)    在Emgu.CV.CvArray`1.set_Bytes(Byte []值)    at AlgorithmsHelper.SearchEdgeImage(AssistentEdgeImageOpenCv referenceImage,Image currentImage)

感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

我仍然不知道为什么会发生异常,但我找到了一个解决方案作为walkaround。就像http://www.emgu.com/wiki/index.php/Working_with_Images建议我创建一个Mat,用字节填充它并从Mat巫婆中创建一个图像。

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