(4opencv)如何基于GOCW,创建一个实时视频程序

时间:2023-01-21 08:05:07
直接使用提供的代码框架进行修改,是最快得到效果的方法;但是这样的灵活性较差,而且真正的程序员从来都不会停滞在这一步:我们需要的是“将框架解析到最小化、理清楚每个构建之间的关系”,只有这样才能灵活运用。

一、准备工作

1、高拍仪已经接通,如果需要的话,还要安装驱动;
2、vs2012编程环境,能够编写Csharp和OpenCV程序(具体不清楚可以回过头来看配置);
3、(4opencv)如何基于GOCW,创建一个实时视频程序是DirectShow.net(http://directshownet.sourceforge.net/docs.html)的可使用类
(4opencv)如何基于GOCW,创建一个实时视频程序
它本身包含文档,有时间可以看一下。最新更新时间2010年。
4、(4opencv)如何基于GOCW,创建一个实时视频程序是由
(4opencv)如何基于GOCW,创建一个实时视频程序
生成的。这里可以先立足修改已经编辑成功的项目(具体原理将在下一课讲解)
二、配置程序
1、添加引用
(4opencv)如何基于GOCW,创建一个实时视频程序
directshow.net的话,直接引用dll就可以了
(4opencv)如何基于GOCW,创建一个实时视频程序
2、拖动控件
使用Csharp编写界面,可以重复使用
(4opencv)如何基于GOCW,创建一个实时视频程序
的定位功能
(4opencv)如何基于GOCW,创建一个实时视频程序
以及Dock的停靠功能
(4opencv)如何基于GOCW,创建一个实时视频程序

图像显示的地方,肯定需要的是picturebox,不妨连同lena一起拷贝过来
(4opencv)如何基于GOCW,创建一个实时视频程序

由于采集处理是一个实时过程,我们采用timer控件来控制(关于是使用timer还是开线程,那种比较好,我们在框架融合的时候专门比较,并选择)
(4opencv)如何基于GOCW,创建一个实时视频程序
性Interval采用50即可,以为50*24>1000,一般来说还是有认为24帧以上比较连贯。


三、编写代码
1、添加头文件和引用,并添加capture.cs
(4opencv)如何基于GOCW,创建一个实时视频程序
(4opencv)如何基于GOCW,创建一个实时视频程序

其中,Capture是一个专门对Directshow的采集设备的封装,里面有丰富的功能;是官方提供的代码,可以较为方向应用。
注意修改命名空间
(4opencv)如何基于GOCW,创建一个实时视频程序
2、编写选择视频准备函数(注意这里默认设备为640*480),并且我在选择的时候默认选择了第2个(序号为1)的设备,因为我用的是笔记本,有内置摄像头

相关函数的操作,注意参考相关注释

  //选择视频设备
        public void InitVideoDevice()
        {
            try
            {
                if (cam != null)
                    cam.Dispose();
                //读取参数
                int VIDEODEVICE = 1; // zero based index of video capture device to use
                const int VIDEOWIDTH = 640;// 是用默认(最大)分辨率
                const int VIDEOHEIGHT = 480; // Depends on video device caps
                const int VIDEOBITSPERPIXEL = 24; // BitsPerPixel values determined by device
                cam = new Capture(VIDEODEVICE, VIDEOWIDTH, VIDEOHEIGHT, VIDEOBITSPERPIXEL, picPreview  );
            }
            catch
            {
                MessageBox.Show("摄像头打开错误,请首先确保摄像头连接并至少支持1024*768分辨率!");
            }
        }

并且在form的init中进行调用,确保不能够出错
  public FormMain()
        {
            InitializeComponent();
           
            //构造摄像头数据
            foreach (DsDevice ds in DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice))
            {
                cbCam.Items.Add(ds.Name);
            }
            //初始化摄像头

InitVideoDevice();  
        }


此时,已经可以预览,并且获得所有视频设备
(4opencv)如何基于GOCW,创建一个实时视频程序
4、编写timer事件
为了将OpenCV的函数融入进去,必须自己编写timer事件。在这个timer事件中,最重要的操作就是
读取directshow.net产生的结果
调用OpenCV的函数进行处理
将处理的结果反馈到directshow.net中去显示出来

 private void timer_Tick(object sender, EventArgs e)
        {
            // Release any previous buffer
            if (m_ip != IntPtr.Zero)
            {
                Marshal.FreeCoTaskMem(m_ip);
                m_ip = IntPtr.Zero;
            }
            // capture image
            try
            {
                m_ip = cam.Click();
            }
            catch
            {
                //do nothing,允许丢帧 TODO:是否改成继承上一帧更好
            }
            Bitmap b = new Bitmap(cam.Width, cam.Height, cam.Stride, PixelFormat.Format24bppRgb, m_ip);
            // If the image is upsidedown
            b.RotateFlip(RotateFlipType.RotateNoneFlipY);
            srcImage = b;
            if (picPreview.Image != null)
                picPreview.Image.Dispose();
            //调用clr+opencv图像处理模块
            MemoryStream ms = new MemoryStream();
            b.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
            byte[] bytes = ms.GetBuffer();
            Bitmap bitmap = client.testMethod(bytes);
            //显示结果
            picPreview.Image = bitmap;
        }


这段代码比较关键
 // Release any previous buffer
            if (m_ip != IntPtr.Zero)
            {
                Marshal.FreeCoTaskMem(m_ip);
                m_ip = IntPtr.Zero;
            }

首先判断指针是否为空

  // capture image
            try
            {
                m_ip = cam.Click();
            }
            catch
            {
                //do nothing,允许丢帧 TODO:是否改成继承上一帧更好
            }
   Bitmap b = new Bitmap(cam.Width, cam.Height, cam.Stride, PixelFormat.Format24bppRgb, m_ip);
            // If the image is upsidedown
            b.RotateFlip(RotateFlipType.RotateNoneFlipY);
            srcImage = b;

而后通过调用Click()获得当前视频数据,并且将其转换为BitMap格式

   if (picPreview.Image != null)
                picPreview.Image.Dispose();
            //调用clr+opencv图像处理模块
            MemoryStream ms = new MemoryStream();
            b.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
            byte[] bytes = ms.GetBuffer();
            Bitmap bitmap = client.testMethod(bytes);

最为关键的调用client.testMethod方法来进行图像处理,并将结果直接转换为bitmap,最后这个结果显示在另外一个picturebox上面。

如果你去看这个testMethod,是一个非常典型的“三明治”结构:包括将<byte>结构转换为Mat,调用OpenCV函数对Mat进行处理,将Mat结果返回出来。
Bitmap^  GOClrClass::testMethod(cli::array<unsigned char>^ pCBuf1)
{
    ////////////////////////////////将输入cli::array<unsigned char>转换为cv::Mat/////////////////////////
    pin_ptr<System::Byte> p1 = &pCBuf1[0];
    unsigned char* pby1 = p1;
    cv::Mat img_data1(pCBuf1->Length,1,CV_8U,pby1);
    cv::Mat img_object = cv::imdecode(img_data1,IMREAD_UNCHANGED);
    if (!img_object.data)
        return nullptr;
    ////////////////////////////////////////////OpenCV的算法处理过程////////////////////////////////////
    cvtColor(img_object,img_object,COLOR_BGR2GRAY);
    cvtColor(img_object,img_object,COLOR_GRAY2BGR);
    Mat drawing = img_object.clone();
    
    /////////////////////////将cv::Mat转换为Bitmap(只能传输cv_8u3格式数据)///////////////////////////////
    if (!drawing.data)
        return nullptr;
    Bitmap^ bitmap = MatToBitmap(drawing);
    return bitmap;
}

而主要算法,只是一个灰度处理。(我首先将彩色图像转换为灰度,然后再将灰度转换为彩色,是为了保持3通道)

四、测试结果

为了显示结果,我添加了一个picResult的picturebox,则调用OpenCV的处理结果显示在右侧。
(4opencv)如何基于GOCW,创建一个实时视频程序


(4opencv)如何基于GOCW,创建一个实时视频程序

到此为止,基于GOCW,创建一个实时视频程序的基本流程已经明晰了,如果感兴趣,相关的原理请关注后续博客。
感谢阅读至此,
希望有所帮助。
P.S小技巧:在tab选择到预览窗口的时候,才打开timer,这样能够保证最好效率。

   private void tabControl_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (tabControl.SelectedIndex == 1)//只有在预览的时候打开图像处理
                timer.Enabled = true;
            else
                timer.Enabled = false;
        }

(4opencv)如何基于GOCW,创建一个实时视频程序的更多相关文章

  1. SpringMVC基础入门,创建一个HelloWorld程序

    ref:http://www.admin10000.com/document/6436.html 一.SpringMVC基础入门,创建一个HelloWorld程序 1.首先,导入SpringMVC需要 ...

  2. Django 创建一个应用程序

    1. 认识Django Django是一个高级的Python Web框架,它鼓励快速开发和清洁,务实的设计. 由经验丰富的开发人员构建,它负责Web开发的许多麻烦,因此您可以专注于编写应用程序,而无需 ...

  3. Win32 程序开发:创建一个应用程序窗口

    一.创建一个应用程序窗口 代码如下: // 头文件 #include <windows.h> // 全局变量 WCHAR g_lpszClassName[] = L"CLASSN ...

  4. IoC COntainer Create Javabeans 可以通过读取beans&period;xml 文件来创建一个应用程序上下文对象 依赖反转

    Spring初学快速入门 - Spring教程™ https://www.yiibai.com/spring/spring-tutorial-for-beginners.html# pom <? ...

  5. 用html5的canvas和JavaScript创建一个绘图程序

    本文将引导你使用canvas和JavaScript创建一个简单的绘图程序. 创建canvas元素 首先准备容器Canvas元素,接下来所有的事情都会在JavaScript里面. <canvas ...

  6. DirectX游戏编程(一):创建一个Direct3D程序

    一.环境 Visual Studio 2012,DirectX SDK (June 2010) 二.准备 1.环境变量(如没有配置请添加) 变量名:DXSDK_DIR 变量值:D:\Software\ ...

  7. 如何用java创建一个jdbc程序

    第一个jdbc程序 JDBC简介 Java数据库连接(Java Database Connectivity,JDBC),是一种用于执行SQL语句的Java API,它由一组用Java编程语言编写的类和 ...

  8. 用MyEclipse2016 CI版创建一个SpringBoot程序

    之前先要在Eclipse里安装STS,步骤如下: 1.点击菜单Help->Install from Catalog 2.在弹出的对话框中点击Popular选项卡,在STS旁边点Install按钮 ...

  9. 基于centos 创建一个stress镜像

    最近需要学习docker的Cgroups机制,需要用到stress进行测试,前期工作就是自己创建一个stress镜像. 新建一个 Dockerfile 文件 [vagrant@localhost ~] ...

随机推荐

  1. java程序转换excel中科学记数法的数据为date类型

    今天出于某些原因从mongodb数据库中导出了一些数据,为了更直观的发送给其他人查阅,便使用mongoVUE的导出为excel功能.   但是导出后出现了一个问题,里边有一列存储时间的,存储的是lon ...

  2. Js脚本选取iframe中的元素

    遇到个小问题,需要用到原生Js处理页面中的元素,以往一个document.getElementById就完活的选取元素,这次却不好使了.. 仔细看代码发现要选取元素外面多了一个iframe标签 &lt ...

  3. windows系统下的文件夹链接功能mklink&sol;linkd

    vista及以上系统的mklink命令可以创建文件夹的链接(感觉像是文件夹的映射).因为是从底层实现文件夹链接,所以这个链接是对应用程序透明的. (windows 2000,xp,server 200 ...

  4. NET Core控制反转(IoC)

    ASP.NET Core中的依赖注入(1):控制反转(IoC)   ASP.NET Core在启动以及后续针对每个请求的处理过程中的各个环节都需要相应的组件提供相应的服务,为了方便对这些组件进行定制, ...

  5. OpenGL&plus;VS2013&plus;WIN7&lpar;64&rpar;组态

    1.下载windows在下面glut安装文件:http://www.opengl.org/resources/libraries/glut/glutdlls37beta.zip 2. 拆开发现五个文件 ...

  6. dfs Codeforces Round &num;356 &lpar;Div&period; 2&rpar; D

    http://codeforces.com/contest/680/problem/D 题目大意:给你一个大小为X的空间(X<=m),在该空间内,我们要尽量的放一个体积为a*a*a的立方体,且每 ...

  7. Exif Info 隐私政策

    隐私政策 本应用尊重并保护所有使用服务用户的个人隐私权.为了给您提供更准确.更有个性化的服务,本应用会按照本隐私权政策的规定使用和披露您的个人信息.但本应用将以高度的勤勉.审慎义务对待这些信息.除本隐 ...

  8. subsets&lpar;子集&rpar;

    Given a set of distinct integers, nums, return all possible subsets (the power set). Note: The solut ...

  9. Myeclipse按包装SVN

    最简单步骤:把features和plugins直接放到Myeclipse安装包的dropins中,从新启动eclipse即可 features和plugins下载地址:http://pan.baidu ...

  10. Elasticsearch最佳实践之分片使用优化

    本文由云+社区发表 作者:老生姜 一.遇到的问题 与大多数分布式系统一样,Elasticsearch按照一定的Hash规则把用户数据切分成多个分片,然后打散到不同机器进行存储,从而实现大规模数据的分布 ...