OpenCV(Emgu)入門系列(8):在C#的PictureBox顯示由EmguCV讀取的圖片


使用VC++對着《學習OpenCV》做了幾個例子之后,我覺得該改用C#了。因為我想自己實驗一下OpenCV的功能,比如弄幾個輸入框、按扭來控制程序,發現使用VC++特別難(相對我的c++水平來說)。對於這種非核心的部分,我不願意浪費太多時間,於是果斷轉向C#。

在C#中使用OpenCV,就要使用它的wrapper了。目前發現有兩個:

  • EmguCV 開發活躍、功能強,使用者也多一些,可惜是GPL/商業授權。好在License不是很貴,200$左右,用得好的話買一個也可以接受
  • OpencvSharp 由日本人開發,LGPL,相對EmguCV友好一些,對API的封裝看起來也舒服一些。比如CV.LoadImage(),而不像Emgu的CvInvoke.cvLoadImage()

最開始試的是OpencvSharp,可惜在寫簡單的Hello world時,不知道哪里的庫沒調對,總是出錯,折騰半天放棄了,轉而使用Emgu。實際上在Emgu中也遇到了同樣的問題,好在解決了就先用着吧。

因為Emgu/OpencvSharp的API都跟OpenCV相當相似,所以以后根據情況切換應該也不麻煩。

任務

雖然Emgu提供了一個功能強大的ImageBox控件,但這里我想先測試一下,如何將Emgu與C#的控件結合起來:由Emgu讀取圖片,顯示在C#的控件PictureBox中。

注意:使用64位的OpenCV和Emgu

效果圖

image

關鍵代碼

直接使用PictureBox顯示一幅圖片,或者直接使用Emgu的API把一張圖片顯示到一個窗口,都是很容易的事。難點在於,如何把Emgu讀取的圖片,轉為PictureBox可使用的Bitmap呢?

看以下代碼:

IntPtr image = CvInvoke.cvLoadImage(filename, Emgu.CV.CvEnum.LOAD_IMAGE_TYPE.CV_LOAD_IMAGE_ANYCOLOR);
Image<Bgr, byte> dest = new Image<Bgr, byte>(CvInvoke.cvGetSize(image));
CvInvoke.cvCopy(image, dest, IntPtr.Zero);
pictureBox1.Image = dest.ToBitmap();

其中image是由Emgu讀取的圖片,它實際上是一個指針(IntPtr),如果想把它轉為Bitmap,需要一個中間步驟:創建一個Emgu.CV.Image對象,再用cvCopy把數據拷貝過去,然后再調用ToBitmap()方法轉換即可。

完整代碼

以下為Form1的完整代碼,不包含GUI的布局:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Emgu.CV;
using Emgu.CV.Structure;

namespace ShowCVImage {
    public partial class Form1 : Form {
        public Form1() {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e) {
            var dialog = new OpenFileDialog();
            dialog.Filter = "圖片(*.jpg/*.png/*.gif/*.bmp)|*.jpg;*.png;*.gif;*.bmp";
            if (dialog.ShowDialog() == DialogResult.OK) {
                var filename = dialog.FileName;

                IntPtr image = CvInvoke.cvLoadImage(filename, Emgu.CV.CvEnum.LOAD_IMAGE_TYPE.CV_LOAD_IMAGE_ANYCOLOR);
                Image<Bgr, byte> dest = new Image<Bgr, byte>(CvInvoke.cvGetSize(image));
                CvInvoke.cvCopy(image, dest, IntPtr.Zero);
                pictureBox1.Image = dest.ToBitmap();
            }
        }
    }
}

可見還是相當簡潔的。

注意事項

注意這是一個x64程序,使用的OpenCV鏈接庫、Emgu和編譯平台,都應該是x64的。有一項不對則程序無法正常運行。

這里再復習一遍

  • PATH中:E:\OpenCV\OpenCV-2.4.0\build\x64\vc10\bin;E:\OpenCV\OpenCV-2.4.0\build\common\tbb\intel64\vc10;E:\OpenCV\Emgu\emgucv-windows-x64 2.4.0.1717\bin
  • 項目引用:Emgu.CV和Emgu.Util即可
  • 編譯平台:右鍵“解決方案”->“屬性”->“配置管理器”->“活動解決方案平台”->“新建”->“鍵入或選擇新平台”選x64 -> 確定即可

另外,當前的OpenCV版本為2.4.2,但Emgu和OpencvSharp使用的還是2.4.0。也就是說,你需要下載OpenCV2.4.0才可以正常使用。


免責聲明!

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



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