第一次使用 EmguCV 處理圖像問題,使用過程當中老是莫名其妙的閃退,程序崩潰,或者內存泄漏。php
剛開始覺得是EmguCV那些地方用的不對,後來發現可能更是由於 PictureBox用的很差。緩存
羅列注意事項一兩點。但願能保住遇到一樣問題的童鞋們。ui
EmguCV 是 OpenCV在.Net平臺上的一個包,詳見 http://www.emgu.com/wiki/index.php/Main_Pagespa
我用的EmguCV 版本是 NuGet中的v3.4.3.3016.net
故障1:
「嘗試讀取或寫入受保護的內存。這一般指示其餘內存已損壞。」code
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.dllblog
多半由於沒有及時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