C#调用opencv的dll

opencv算法和界面配合,刚入职的时候尝试过,利用的MFC,调试起来很痛苦。

后来基本都没怎么用界面,DOS的黑窗口,opencv自带的显示界面及滑动条凑合着调试用。

最近有点时间,刚好双十一在一个视觉群里看到了一个讲C#调用opencv的dll的课程,鉴于群主也是那门课的讲师,在平时解答群员的问题的时候很细心,能力也很强,因此有了这篇文章。

根据相机不同动态调用相机默认的属性设置页 

目前所做的工作是跑通老师的框架,能够把opencv的处理结果显示在C#界面中。整体自己学习调试了几天,老师的ini文件有些默认参数,托管dll和显示界面间的关联不是那么强,也就是一边调节滑动条,opencv算法改变参数,界面上又显示结果。目前dll算是写死参数,然后呈现结果,这个还有待自己进一步学习加强。

// 注意注释掉Form1.Designer.cs中的Dispose函数
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 System.Threading;
using System.Runtime.InteropServices; // Marshal
using System.Drawing.Imaging;// PixelFormat.Format24bppRgb
using System.IO;// MemoryStream
using System.Diagnostics; // Process.GetCurrentProcess().Kill();

using GOClrDll;
using DirectShowLib;

namespace Yake2_WFormsApp_opencamera
{
    public partial class Form1 : Form
    {
        #region 成员变量
        [DllImport("oleaut32.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
        public static extern int OleCreatePropertyFrame(
            IntPtr hwndOwner,
            int x,
            int y,
            [MarshalAs(UnmanagedType.LPWStr)] string lpszCaption,
            int cObjects,
            [MarshalAs(UnmanagedType.Interface, ArraySubType = UnmanagedType.IUnknown)] 
            ref object ppUnk,
            int cPages,
            IntPtr lpPageClsID,
            int lcid,
            int dwReserved,
            IntPtr lpvReserved);

        IBaseFilter theDevice = null;
        Thread threadMain;
        private Capture cam;

        IntPtr m_ip = IntPtr.Zero;
        GOClrClass client = new GOClrClass();

        INIFileHelper inifilehelper = new INIFileHelper("./GOConfig");

        bool b_take_picture;

        #endregion
        private void ThreadRun()
        {
            while (true)
            {
                if (m_ip != IntPtr.Zero)
                {
                    Marshal.FreeCoTaskMem(m_ip);
                    m_ip = IntPtr.Zero;
                }

                if (cam == null)
                    continue;//必须的异常处理

                // capture image
                try
                {
                    m_ip = cam.Click();
                }
                catch
                {
                    continue;//继续下图采集显示
                }

                Bitmap b = new Bitmap(cam.Width, cam.Height, cam.Stride, PixelFormat.Format24bppRgb, m_ip);

                 If the image is upsidedown
                b.RotateFlip(RotateFlipType.RotateNoneFlipY);
                
              
                MemoryStream ms = new MemoryStream();
                b.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);

                byte[] bytes = ms.GetBuffer();
                // 这里才是真正调用GOClr托管代码里面的opencv处理函数
                Bitmap bitmap = client.ImageProcess(bytes);

                if (bitmap == null) 
                    continue;
                // 调用CLR的黑白处理
                Bitmap bitmap2 = client.ImageProcess2(bytes);
                Bitmap bitmap_canny = client.ImageProcess_Canny(bytes);

                if (bitmap2 == null)
                    continue;

                if (b_take_picture == true)
                {
                    b_take_picture = false;//不重复取景

                    if (b == null)
                    {
                        System.Windows.Forms.MessageBox.Show("CLR图像获取错误!");
                    }
                    else
                    {
                        string strPath;
                       
                        strPath = System.Windows.Forms.Application.StartupPath;
                        
                        b.Save(strPath + "/" + DateTime.Now.ToString("yyyyMMdd_HHmmss") + ".jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
                        //bitmap.Save(strPath + "/" + DateTime.Now.ToString("yyyyMMdd_HHmm") + "1.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
                        //bitmap2.Save(strPath + "/" + DateTime.Now.ToString("yyyyMMdd_HHmm") + "2.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
                    }
                }

                //显示结果
                try
                {
                    picPreview.Image = b;
                    
                    pictureBox1.Image = bitmap2;
                    //pictureBox1.Image = bitmap;

                    picCanny.Image = bitmap_canny;
                }
                catch
                {
                    continue;
                }
                //施放资源  
                b.Dispose();
                //bitmap.Dispose();
            }
        }
        public Form1()
        {
            InitializeComponent();

           
            //开启线程
            if (threadMain == null)
            {
                this.threadMain = new Thread(this.ThreadRun);
            }
            this.threadMain.IsBackground = true;//程序退出的时候,主动退出线程
            this.threadMain.Start();

            //构造摄像头数据
            foreach (DsDevice ds in DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice))
            {
                comboBox1.Items.Add(ds.Name);
            }
            //初始化摄像头
            InitVideoDevice(); 
            //读取数据库
            //string strtmp = inifilehelper.IniReadValue("视频采集", "摄像头序号");
            //int itmp = Convert.ToInt32(strtmp);
            //if (itmp > comboBox1.Items.Count)
            //{
            //    itmp = 0;
            //}
            //if (comboBox1.Items.Count > 0)
            //{
            //    comboBox1.SelectedIndex = itmp;
            //}

            // 选择摄像头
        }
        // 选择摄像头
        public void InitVideoDevice()
        {
            if (cam != null)
                cam.Dispose();
            //读取参数
            string strTmp = inifilehelper.IniReadValue("视频采集", "摄像头序号");
            int VIDEODEVICE = Convert.ToInt32(strTmp); // zero based index of video capture device to use
            const int VIDEOWIDTH = 640;// 是用默认(最大)分辨率
            const int VIDEOHEIGHT = 480; // Depends on video device caps
             //int VIDEOWIDTH = cam.Width;// 是用默认(最大)分辨率
             //int VIDEOHEIGHT = cam.Height; // Depends on video device caps
            const int VIDEOBITSPERPIXEL = 24; // BitsPerPixel values determined by device
            try
            {
                cam = new Capture(VIDEODEVICE, VIDEOWIDTH, VIDEOHEIGHT, VIDEOBITSPERPIXEL, picPreview);
                //this.ThreadRun();
            }
            catch
            {
                MessageBox.Show("摄像头打开错误,尝试以640*480分辨率进行打开");
                //toolStripStatusLabel1.Text = "摄像头打开错误,尝试以640*480分辨率进行打开";
                cam = new Capture(VIDEODEVICE, VIDEOWIDTH, VIDEOHEIGHT, VIDEOBITSPERPIXEL, picPreview);
            }
        }
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (components != null)
                {
                    components.Dispose();
                }
            }
            base.Dispose(disposing);

            if (m_ip != IntPtr.Zero)
            {
                Marshal.FreeCoTaskMem(m_ip);
                m_ip = IntPtr.Zero;
            }
            this.threadMain.Abort();
        }

        #region helper函数
        // 相机参数设置界面
        private void DisplayPropertyPage(IBaseFilter dev)
        {
            //Get the ISpecifyPropertyPages for the filter
            ISpecifyPropertyPages pProp = dev as ISpecifyPropertyPages;
            int hr = 0;

            if (pProp == null)
            {
                //If the filter doesn't implement ISpecifyPropertyPages, try displaying IAMVfwCompressDialogs instead!
                IAMVfwCompressDialogs compressDialog = dev as IAMVfwCompressDialogs;
                if (compressDialog != null)
                {

                    hr = compressDialog.ShowDialog(VfwCompressDialogs.Config, IntPtr.Zero);
                    DsError.ThrowExceptionForHR(hr);
                }
                else
                {
                    System.Windows.Forms.MessageBox.Show("Item has no property page", "No Property Page", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                }
                return;
            }

            //Get the name of the filter from the FilterInfo struct
            FilterInfo filterInfo;
            hr = dev.QueryFilterInfo(out filterInfo);
            DsError.ThrowExceptionForHR(hr);

            // Get the propertypages from the property bag
            DsCAUUID caGUID;
            hr = pProp.GetPages(out caGUID);
            DsError.ThrowExceptionForHR(hr);

            //Create and display the OlePropertyFrame
            object oDevice = (object)dev;
            hr = OleCreatePropertyFrame(this.Handle, 0, 0, filterInfo.achName, 1, ref oDevice, caGUID.cElems, caGUID.pElems, 0, 0, IntPtr.Zero);
            DsError.ThrowExceptionForHR(hr);

            Marshal.ReleaseComObject(oDevice);

            if (filterInfo.pGraph != null)
            {
                Marshal.ReleaseComObject(filterInfo.pGraph);
            }

            // Release COM objects
            Marshal.FreeCoTaskMem(caGUID.pElems);
        }
        // 视频设备与名字显示
        private IBaseFilter CreateFilter(Guid category, string friendlyname)
        {
            object source = null;
            Guid iid = typeof(IBaseFilter).GUID;
            foreach (DsDevice device in DsDevice.GetDevicesOfCat(category))
            {
                if (device.Name.CompareTo(friendlyname) == 0)
                {
                    device.Mon.BindToObject(null, null, ref iid, out source);
                    break;
                }
            }

            return (IBaseFilter)source;
        }
        #endregion
        private void button1_Click(object sender, EventArgs e)
        {
            DisplayPropertyPage(theDevice);
        }
        private void btnEnd_Click(object sender, EventArgs e)
        {
            if (DialogResult.Yes == System.Windows.Forms.MessageBox.Show("确认退出?", "提示", MessageBoxButtons.YesNo))
            {
                
                this.threadMain.Abort();
                Process.GetCurrentProcess().Kill();// 完全退出
                //this.Close();
            }
        }
        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            int itmp = comboBox1.SelectedIndex;
            inifilehelper.IniWriteValue("视频采集", "摄像头序号", itmp.ToString());
            //选择视频设备
            InitVideoDevice();
            //生成配套的视频控制界面
            if (theDevice != null)
            {
                Marshal.ReleaseComObject(theDevice);
                theDevice = null;
            }
            //Create the filter for the selected video input device
            string devicepath = comboBox1.SelectedItem.ToString();
            theDevice = CreateFilter(FilterCategory.VideoInputDevice, devicepath);
        }
        private void FormMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            cam.Dispose();

            if (m_ip != IntPtr.Zero)
            {
                Marshal.FreeCoTaskMem(m_ip);
                m_ip = IntPtr.Zero;
            }
            //主动退出线程
            this.threadMain.Abort();
        }
       
        private void btnCapture_Click(object sender, EventArgs e)
        {
            
            if (b_take_picture == false)
                b_take_picture = true;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //构造摄像头数据
            //foreach (DsDevice ds in DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice))
            //{
            //    comboBox1.Items.Add(ds.Name);
            //}

            string strTmp = inifilehelper.IniReadValue("视频采集", "摄像头序号");
            //comboBox1.Text = comboBox1.SelectedItem.ToString();
            comboBox1.Text = strTmp;
            //string devicepath = comboBox1.SelectedItem.ToString();
            //theDevice = CreateFilter(FilterCategory.VideoInputDevice, devicepath);
        }

        
        
    }
}

致谢:

http://edu.51cto.com/course/15717.html 

https://github.com/jsxyhelu/GOGPY 

猜你喜欢

转载自blog.csdn.net/yaked/article/details/84585426