在 C# 中使用 EmguCV 時需要注意的一些問題


第一次使用 EmguCV 處理圖像問題,使用過程中總是莫名其妙的閃退,程序崩潰,或者內存泄漏。

剛開始以為是EmguCV那些地方用的不對,后來發現可能更是因為 PictureBox用的不好。

羅列注意事項一兩點。希望能保住遇到同樣問題的童鞋們。

 

EmguCV 是 OpenCV在.Net平台上的一個包,詳見 http://www.emgu.com/wiki/index.php/Main_Page

我用的EmguCV 版本是 NuGet中的v3.4.3.3016


 

故障1:

“嘗試讀取或寫入受保護的內存。這通常指示其他內存已損壞。”

Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

An unhandled exception of type 'System.AccessViolationException' occurred in System.Drawing.dll

多半因為沒有及時Dispose掉不用的緩存,或者持續引用導致GC都清理不掉部分緩存。


 

故障2:

程序閃退

多半因為調用EmguCV時出錯,建議在適當的地方添加 Try Catch.


 

收獲 和 注意事項

1.頻繁設置PictureBox時,釋放上一次緩存。

(參考:https://stackoverflow.com/questions/1831732/c-sharp-picturebox-memory-releasing-problem

 1         public static void ClearAndSetImage(PictureBox dest, Bitmap src)
 2         {
 3             if (dest == null) return;
 4             
 5             if (dest.Image != null)
 6                 dest.Image.Dispose();     //釋放上次的圖片
 7 
 8             if (src == null)
 9             {
10                 dest.Image = null;
11             }
12             else
13             {
14                 dest.Image = new Bitmap(src); // 設置本次圖片
15                 src.Dispose();
16             }
17         }

 

2.調用EmguCV的Mat輸出Image時,轉換為Image再輸出Bitmap

  這點,我沒有仔細考究,只是在網上發現類似的對策,使用后,效果良好,就沒再仔細驗證。

  (參考原著:https://blog.csdn.net/oHuanCheng/article/details/81451909

        public static Bitmap Crop(Bitmap src, Rectangle rect)
        {
            Image<Bgr, Byte> img = new Image<Bgr, byte>(src);

            //Check Crop area
            //crop數據超出范圍也會觸發Emgu的錯誤,導致程序閃退。

            if (rect.X > img.Width) rect.X = img.Width-1;
            if (rect.Y > img.Height) rect.Y = img.Height-1;
            if (rect.X + rect.Width > img.Width) rect.Width = img.Width - rect.X;
            if (rect.Y + rect.Height > img.Height) rect.Height = img.Height - rect.Y;
            
            Mat crop = new Mat(img.Mat, rect);

            //轉換為Image輸出Bitmap
            Image<Bgr, Byte> outImg = crop.ToImage<Bgr, Byte>();
            
//使用 new Bitmap 切斷和outImg間的關系 Bitmap rtn
= new Bitmap(outImg.Bitmap); return rtn; }

 

3. 使用 new Bitmap() 來切斷引用

      Bitmap.clone() 是效率高的淺復制,共享圖片bit

      new Bitmap() 是效率低占內存多的深復制,和被拷貝的對象間沒有指引關系。

      使用 new Bitmap() 后,資源可以被GC有效回收,或者手動Dispose不會報錯。

      實例代碼見第一條和第二條中的應用。

 

4. 對可能出現 EmguCV 錯誤的地方進行捕獲 

            Image<Bgr, Byte> img = new Image<Bgr, byte>(input).Resize(400, 400, Emgu.CV.CvEnum.Inter.Linear, true);
            //Convert the image to grayscale and filter out the noise
            UMat uimage = new UMat();
            try
            {
                // 這句話不穩定,有時會報錯  OpenCV: OpenCL error CL_OUT_OF_RESOURCES (-5)
                // C#捕獲失敗會導致程序閃退
                // 添加捕獲后,可保證程序持續運行,第二次執行是好的。
                CvInvoke.CvtColor(img, uimage, ColorConversion.Bgr2Gray);
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.Print(ex.Message);
            }

 

5. 程序長時間運行后,依然會莫名其妙的崩潰,問題持續查找中。

 TBD

 

其他參考鏈接:

https://blog.csdn.net/liukun0928/article/details/71516020

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM