带有多个图片框缩放和平移同步的C#AccessViolationException [WinForms]

时间:2017-04-26 02:05:27

标签: c# winforms exception emgucv gdi

我目前正在使用EmguCV对图像应用一些过滤器,所以我有6个图片框,每个图片框代表相同的图像,但带有过滤器。问题是当平移和缩放有时我得到AccessViolationException错误。

    /// <summary>
    /// Start processing the image
    /// </summary>
    public void ProcessImage()
    {
        //Load the image from file and resize it for display
        Image<Bgr, Byte> img =
            new Image<Bgr, byte>(FilePath);
        AddImageBox("Original", img.Bitmap);
        //.Resize(400, 400, Emgu.CV.CvEnum.Inter.Linear, true);

        HistogramPanel.ClearHistogram();
        HistogramPanel.GenerateHistograms(img, 256);
        HistogramPanel.Refresh();

        ListViewItem item = lvData.Items.Add("FileName");
        item.SubItems.Add(FileName);

        item = lvData.Items.Add("Size");
        item.SubItems.Add($"{img.Bitmap.Size.Width}, {img.Bitmap.Size.Height}");




        //Convert the image to grayscale and filter out the noise
        Image<Gray, Byte> imgGray = img.Convert<Gray, Byte>().PyrDown().PyrUp();
        /*UMat uimage = new UMat();
        CvInvoke.CvtColor(img, uimage, ColorConversion.Bgr2Gray);

        //use image pyr to remove noise
        UMat pyrDown = new UMat();
        CvInvoke.PyrDown(uimage, pyrDown);
        CvInvoke.PyrUp(pyrDown, uimage);*/
        AddImageBox("Filtered", imgGray.Bitmap);

        /*Image<Gray, Byte> imgGray =
            new Image<Gray, byte>(uimage.Bitmap);*/
        Image<Gray, Byte> imgCanny = imgGray.Canny(200, 100);
        AddImageBox("Canny", imgCanny.Bitmap);

        Image<Gray, float> imgSobel = imgGray.Sobel(1, 0, 5);
        AddImageBox("Sobel", imgSobel.Bitmap);

        Image<Gray, float> imgLaplace = imgGray.Laplace(3);
        AddImageBox("Laplace", imgLaplace.Bitmap);

        Image<Gray, float> imgSobelHeavy = imgGray.Sobel(0, 1, 3).Add(imgGray.Sobel(1, 0, 3)).AbsDiff(new Gray(0.0));
        AddImageBox("Sobel Heavy", imgSobelHeavy.Bitmap);

        IsLoaded = true;
    }

Output GUI

每个图片框都与其他图片同步,因此如果缩放或平移,其他图片框将同步到相同位置并缩放

ImageBox.ZoomChanged += (sender, args) => SyncImages(); ImageBox.Scroll += (sender, args) => SyncImages();

        /// <summary>
    /// Sync all images to be at same zoom and position
    /// </summary>
    public void SyncImages()
    {
        if (ReferenceEquals(ParentTab, null) || ParentTab.SuspendEvents) return;
        ParentTab.SuspendEvents = true;
        foreach (var ctrlImageBox in ParentTab.ImageBoxs)
        {
            if (ReferenceEquals(ctrlImageBox, this))
                continue;

            ctrlImageBox.ImageBox.Zoom = ImageBox.Zoom;
            ctrlImageBox.ImageBox.AutoScrollPosition = new Point(Math.Abs(ImageBox.AutoScrollPosition.X), Math.Abs(ImageBox.AutoScrollPosition.Y));
        }

        Program.FrmMain.UpdateStatusBar();
        ParentTab.SuspendEvents = false;
    }

在进行一些平移或缩放后,此错误将显示:

  

发生了System.AccessViolationException     的HResult = 0x80004003     消息= Tentativa de ler ou escrevernamemóriaprotegida。 Istoénormalmenteumainindicaçãodeque existeoutramemoóriapanificada。     来源= System.Drawing中     堆栈跟踪:      在System.Drawing.SafeNativeMethods.Gdip.GdipDrawImageRectRect(HandleRef图形,HandleRef图像,单dstx,单dsty,单dstwidth,单dstheight,单srcx,单srcy,单srcwidth,单srcheight,Int32 srcunit,HandleRef imageAttributes,DrawImageAbort回调, HandleRef callbackdata)      在System.Drawing.Graphics.DrawImage(Image image,RectangleF destRect,RectangleF srcRect,GraphicsUnit srcUnit)      在Cyotek.Windows.Forms.ImageBox.DrawImage(Graphics g)      在Cyotek.Windows.Forms.ImageBox.OnPaint(PaintEventArgs e)      在System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e,Int16 layer)      在System.Windows.Forms.Control.WmPaint(消息&amp; m)      在System.Windows.Forms.Control.WndProc(消息&amp; m)      在System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd,Int32 msg,IntPtr wparam,IntPtr lparam)

Exception

我正在使用AppDomain.CurrentDomain.UnhandledException来导致此

.NET Framework:4.6.2(使用WinForms)

问题:AccessViolationException

正在使用的图片框:Cyotek.Windows.Forms.ImageBox,也尝试使用Emgu.CV.UI.PanAndZoomPictureBox,我得到了同样的错误

内存看起来像是损坏了还是GC?

1 个答案:

答案 0 :(得分:1)

我在同一个视频文件中只使用过两次VideoCapture,遇到了类似的问题。

虽然我不知道确切的原因,但这是一个并发问题,适当地使用lock statements通常是解决方案。

我认为,当下一个VideoCapture实例尝试访问硬盘驱动器上视频文件存储中的相同位置时,两个VideoCapture实例都会在幕后运行一些异步代码。

这不是一个完整的修复,但编译64位项目将减少这些问题的频率。我确信这是因为代码在64位而不是某些环形交叉dll问题上运行效率更高。

如果我找到完整的解决方案,我一定会通知您。