好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

C# WPF使用AForge类库操作USB摄像头拍照并保存

项目中用到 usb 摄像头,需要根据情况进行图像抓拍,查了半天资料,比较多的是使用 wpfmediakit 和 aforge 。
但是由于项目要求不显示 usb 摄像头拍摄的画面,最终确定使用 aforge 解决。
下面用一个测试程序记录一下。

一、无预览拍照

首先建立一个 wpf 项目,我的就叫 aforgetest,你们随意就好:

然后在 nuget 包管理器中安装 aforge 库:

我只安装了图中打勾的几个库,这个根据自己项目需要安装就好。
不过用 usb 摄像头拍照必须安装:
aforge.video
aforge.control
aforge.video.directshow
这三个库文件。

不习惯使用 nuget 也可以到 aforge 的 .net lib 下载页面下载。

在 mainwindow.xaml 文件中添加两个按钮:

?

< window x:class = "aforgetest.mainwindow"

   xmlns = "http://schemas.microsoft测试数据/winfx/2006/xaml/presentation"

   xmlns:x = "http://schemas.microsoft测试数据/winfx/2006/xaml"

   xmlns:d = "http://schemas.microsoft测试数据/expression/blend/2008"

   xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"

   xmlns:local = "clr-namespace:aforgetest"

   mc:ignorable = "d"

   title = "mainwindow" height = "300" width = "300"

   closing = "window_closing" >

  < stackpanel >

   < button name = "btncapture" click = "btncapture_click" >拍照</ button >

   < button name = "btnopencamera" click = "btnopencamera_click" >打开</ button >

  </ stackpanel >

</ window >

后台交互逻辑如下:

?

using system;

using system.windows;

 

namespace aforgetest

{

  /// <summary>

  /// mainwindow.xaml 的交互逻辑

  /// </summary>

  public partial class mainwindow : window

  {

   public mainwindow()

   {

    initializecomponent();

   }

 

   private void btnopencamera_click( object sender, eventargs e)

   {

    camerahelper.updatecameradevices();

    if (camerahelper.cameradevices.count > 0)

    {

     camerahelper.setcameradevice(0);

    }

   }

 

   private void btncapture_click( object sender, eventargs e)

   {

    camerahelper.captureimage( @"e:\1" );

   }

 

   private void window_closing( object sender, system测试数据ponentmodel.canceleventargs e)

   {

    camerahelper.closedevice();

   }

  }

}

camerahelper 类代码如下:

?

using system;

using aforge.video.directshow;

using aforge.controls;

using system.windows;

using system.io;

using system.drawing;

using system.drawing.imaging;

 

namespace aforgetest

{

  public static class camerahelper

  {

   private static filterinfocollection _cameradevices;

   private static videocapturedevice div = null ;

   private static videosourceplayer sourceplayer = new videosourceplayer();

   private static bool _isdisplay = false ;

   //指示_isdisplay设置为true后,是否设置了其他的sourceplayer,若未设置则_isdisplay重设为false

   private static bool isset = false ;

 

   /// <summary>

   /// 获取或设置摄像头设备,无设备为null

   /// </summary>

   public static filterinfocollection cameradevices

   {

    get

    {

     return _cameradevices;

    }

    set

    {

     _cameradevices = value;

    }

   }

   /// <summary>

   /// 指示是否显示摄像头视频画面

   /// 默认false

   /// </summary>

   public static bool isdisplay

   {

    get { return _isdisplay; }

    set { _isdisplay = value; }

   }

   /// <summary>

   /// 获取或设置videosourceplayer控件,

   /// 只有当isdisplay设置为true时,该属性才可以设置成功

   /// </summary>

   public static videosourceplayer sourceplayer

   {

    get { return sourceplayer; }

    set

    {

     if (_isdisplay)

     {

      sourceplayer = value;

      isset = true ;

     }

 

    }

   }

   /// <summary>

   /// 更新摄像头设备信息

   /// </summary>

   public static void updatecameradevices()

   {

    _cameradevices = new filterinfocollection(filtercategory.videoinputdevice);

   }

   /// <summary>

   /// 设置使用的摄像头设备

   /// </summary>

   /// <param name="index">设备在cameradevices中的索引</param>

   /// <returns><see cref="bool"/></returns>

   public static bool setcameradevice( int index)

   {

    if (!isset) _isdisplay = false ;

    //无设备,返回false

    if (_cameradevices.count <= 0 || index < 0) return false ;

    if (index > _cameradevices.count - 1) return false ;

    // 设定初始视频设备

    div = new videocapturedevice(_cameradevices[index].monikerstring);

    sourceplayer.videosource = div;

    div.start();

    sourceplayer.start();

    return true ;

   }

   /// <summary>

   /// 截取一帧图像并保存

   /// </summary>

   /// <param name="filepath">图像保存路径</param>

   /// <param name="filename">保存的图像文件名</param>

   public static void captureimage( string filepath, string filename = null )

   {

    if (sourceplayer.videosource == null ) return ;

    if (!directory.exists(filepath))

    {

     directory.createdirectory(filepath);

    }

    try

    {

     //sourceplayer.start();

     image bitmap = sourceplayer.getcurrentvideoframe();

     if (filename == null ) filename = datetime.now.tostring( "yyyy-mm-dd-hh-mm-ss" );

     bitmap.save(filepath + @"\" + filename + "-cap.jpg", imageformat.jpeg);

     bitmap.dispose();

     //sourceplayer.stop();

    }

    catch (exception e)

    {

     messagebox.show(e.message.tostring());

    }

   }

   /// <summary>

   /// 关闭摄像头设备

   /// </summary>

   public static void closedevice()

   {

    if (div != null && div.isrunning)

    {

     sourceplayer.stop();

     div.signaltostop();

     div = null ;

     _cameradevices = null ;

    }

   }

  }

}

最终效果如下:

首先单击打开按钮,然后单击拍照按钮,就会在指定路径下生成一个 jpg 文件。

单击打开按钮之后需要等待 2s 以上才能点击拍照(需要等待连接到摄像头),否则会报出异常,如下图:

二、显示摄像头拍摄画面和截取的图片

首先添加 system.windows.forms 和 windowsformsintegration 的引用。
然后在 mainwindows.xmal 文件中加命名空间:

?

xmlns:wfi ="clr-namespace:system.windows.forms.integration;assembly=windowsformsintegration"

xmlns:aforge ="clr-namespace:aforge.controls;assembly=aforge.controls"12

添加 videosourceplayer 和 image 控件:

?

< wfi:windowsformshost grid.row = "0" >

  < aforge:videosourceplayer x:name = "player" height = "480" width = "640" />

</ wfi:windowsformshost >

?

< image grid.row = "0" grid.column = "1" name = "imgcapture" stretch = "fill" height = "480" width = "640" />

这里有个小细节,注意对 videosourceplayer 命名时,一定要使用 x:name 不要省略 x: ,否则无法在后台代码中使用(不要问我是怎么知道的)。

对 camerahelper.cs 中的 captureimage 函数做一点修改:

?

/// <summary>

/// 截取一帧图像并保存

/// </summary>

/// <param name="filepath">图像保存路径</param>

/// <param name="filename">保存的图像文件名</param>

/// <returns>如果保存成功,则返回完整路径,否则为 null</returns>

  public static string captureimage( string filepath, string filename = null )

   {

    if (sourceplayer.videosource == null ) return null ;

    if (!directory.exists(filepath))

    {

     directory.createdirectory(filepath);

    }

    try

    {

     image bitmap = sourceplayer.getcurrentvideoframe();

     if (filename == null ) filename = datetime.now.tostring( "yyyy-mm-dd-hh-mm-ss" );

     string fullpath = path测试数据bine(filepath, filename + "-cap.jpg" );

     bitmap.save(fullpath, imageformat.jpeg);

     bitmap.dispose();

     return fullpath;

    }

    catch (exception e)

    {

     messagebox.show(e.message.tostring());

     return null ;

    }

}

修改后台代码如下:

?

using system;

using system.windows;

using system.windows.media.imaging;

 

namespace aforgetest

{

  /// <summary>

  /// mainwindow.xaml 的交互逻辑

  /// </summary>

  public partial class mainwindow : window

  {

   public mainwindow()

   {

    initializecomponent();

    camerahelper.isdisplay = true ;

    camerahelper.sourceplayer = player;

    camerahelper.updatecameradevices();

   }

 

   private void btnopencamera_click( object sender, eventargs e)

   {

    if (camerahelper.cameradevices.count > 0)

    {

     camerahelper.setcameradevice(0);

    }

   }

 

   private void btncapture_click( object sender, eventargs e)

   {

    string fullpath = camerahelper.captureimage(appdomain.currentdomain.basedirectory + @"\capture" );

 

    bitmapimage bit = new bitmapimage();

    bit.begininit();

    bit.urisource = new uri(fullpath);

    bit.endinit();

    imgcapture.source = bit;

   }

 

   private void window_closing( object sender, system测试数据ponentmodel.canceleventargs e)

   {

    camerahelper.closedevice();

   }

  }

}

最终结果如下:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://blog.csdn.net/luo_5458/article/details/74452534

dy("nrwz");

查看更多关于C# WPF使用AForge类库操作USB摄像头拍照并保存的详细内容...

  阅读:57次