文章目录

  • 1、添加引用
  • 2、AForge相关类库介绍
  • 3、WinForm界面实现
  • 4、属性
  • 5、窗口加载与关闭
  • 6、实例化
  • 7、 摄像头的连接读取与关闭
  • 8、拍照与保存
  • 9、录像
  • 10、计时器
  • 11、完整代码
  • 12、测试结果
  • 12、Demo下载
  • 13、踩坑经历及解决方案

1、添加引用

1、官网下载链接:http://www.aforgenet.com/framework/downloads.html
2、通过管理Nuget程序包可直接添加以下引用,当然这里并没有全部用上,而只是用上了一部分


在添加完这些引用之后VS的工具箱当中会多出AForge.NET相关的一些控件,而实现调用摄像头就需要使用到这些控件

2、AForge相关类库介绍

AForge.dll 是框架的核心基础类库,为其他类库提供服务。
AForge.Controls.dll 包含AForge.Net的UI控件,主要用于页面显示。
AForge.Imaging.dll 主要是框架中用于图像处理的类库,主要负责图像的处理
AForge.Video.dll 主要是框架中对视频处理的类库。
AForge.Video.DirectShow.dll 主要是通过DirectShow接口访问视频资源的类库。
AForge.Video.FFMPEG.dll 是一个还未正式发布的类库,通过FFMPEG类库对视频进行读写。

3、WinForm界面实现

这里解释以下界面组成及控件使用
此界面分上下两部分
上中半部分由一个GroupBox包裹一个AForge.NET工具包VideoSourcePlayer控件命名为vsp_Panel组成
中间部分由一个Label,一个ComBox下拉框cb_CameraSelect,两个Button按钮btn_Connect、btn_Close组成
下半部分由分左右俩部分
下左部分由一个GroupBox包裹一个AForge.NET工具包PictureBox控件命名为pb_BoxPanel组成
下右部分由由一个GroupBox包裹5个Button按钮btn_StartVideo、btn_PauseVideo、btn_EndVideo、btn_Capture、btn_Save。以及两个label,其中录制时间: 这个label命名无所谓后续用不到,而另外一个默认显示为00:00:00的label命名为lab_Time

4、属性

       #region 属性/// <summary>/// 设备源/// 用来操作摄像头/// </summary>private AForge.Video.DirectShow.VideoCaptureDevice videoCapture;/// <summary>/// 摄像头设备集合/// </summary>private AForge.Video.DirectShow.FilterInfoCollection infoCollection;/// <summary>/// 图片/// </summary>private System.Drawing.Bitmap imgMap;/// <summary>/// 文件保存路径/// </summary>private readonly string filePath = $"D:\\VS主题\\图片\\";/// <summary>/// 文件名称/// </summary>private readonly string fileName = $"{DateTime.Now.ToString("yyyyMMddhhmmssffff")}";/// <summary>/// 用与把每一帧图像写入到视频文件/// </summary>private AForge.Video.FFMPEG.VideoFileWriter videoWriter;/// <summary>/// 是否开始录像/// </summary>private bool IsStartVideo = false;/// <summary>/// 写入次数/// </summary>private int tick_num = 0;/// <summary>/// 录制多少小时,只是为了定时间计算录制时间使用/// </summary>private int Hour = 0;/// <summary>/// 计时器/// </summary>private System.Timers.Timer timer_count;#endregion

5、窗口加载与关闭

         #region 窗口加载与关闭/// <summary>/// 讲题加载事件/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void Form1_Load(object sender, EventArgs e){InitCamera();InitCameraSelect();this.btn_Capture.Enabled = false;this.btn_Save.Enabled = false;this.pb_BoxPanel.SizeMode = PictureBoxSizeMode.Zoom;//图片大小按比例适应控件,不加的话图片显示问题太大this.gb_CapturePanel.Visible = false;//默认不显示照片区域,拍照时在显示//秒表timer_count = new System.Timers.Timer();   //实例化Timer类,设置间隔时间为1000毫秒;timer_count.Elapsed += new System.Timers.ElapsedEventHandler(tick_count);   //到达时间的时候执行事件;timer_count.AutoReset = true;   //设置是执行一次(false)还是一直执行(true);timer_count.Interval = 1000;}/// <summary>/// 窗口关闭时/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void Form1_FormClosing(object sender, FormClosingEventArgs e){EndCamera();}#endregion

6、实例化

     #region 实例化/// <summary>/// 实例化摄像头/// </summary>public void InitCamera(){try{//检测电脑上的摄像头设备infoCollection = new AForge.Video.DirectShow.FilterInfoCollection(AForge.Video.DirectShow.FilterCategory.VideoInputDevice);}catch (Exception ex){MessageBox.Show($"没有找到设备:{ex.Message}", "Error");}}//加载摄像头选择public void InitCameraSelect(){this.cb_CameraSelect.DropDownStyle = ComboBoxStyle.DropDownList;//根据读取到的摄像头加载选择项foreach (AForge.Video.DirectShow.FilterInfo item in infoCollection){this.cb_CameraSelect.Items.Add(item.Name);}//for (int i = 1; i <= infoCollection.Count; i++)//{//    this.cb_CameraSelect.Items.Add("摄像头" + i);//}}#endregion

7、 摄像头的连接读取与关闭

         #region  摄像头的连接读取与关闭/// <summary>/// 连接按钮/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void btn_Connect_Click(object sender, EventArgs e){var CameraSelect = this.cb_CameraSelect.Text;var selectIndex = this.cb_CameraSelect.SelectedIndex;//已有连接的摄像头时先关闭if (videoCapture != null){EndCamera();}videoCapture = new AForge.Video.DirectShow.VideoCaptureDevice(infoCollection[selectIndex].MonikerString);//启动摄像头this.vsp_Panel.VideoSource = videoCapture;this.vsp_Panel.Start();this.btn_Capture.Enabled = true;this.btn_Save.Enabled = false;}/// <summary>/// 关闭按钮/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void btn_Close_Click(object sender, EventArgs e){EndCamera();}/// <summary>/// 关闭摄像头/// </summary>public void EndCamera(){if (this.vsp_Panel.VideoSource != null){//也可以用 Stop() 方法关闭//指示灯停止且等待this.vsp_Panel.SignalToStop();//停止且等待this.vsp_Panel.WaitForStop();this.vsp_Panel.VideoSource = null;}}#endregion

8、拍照与保存

          #region 拍照与保存/// <summary>/// 拍照/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void btn_Capture_Click(object sender, EventArgs e){imgMap = this.vsp_Panel.GetCurrentVideoFrame();this.gb_CapturePanel.Visible = true;this.pb_BoxPanel.Image = imgMap;this.btn_Save.Enabled = true;}/// <summary>/// 保存事件/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void btn_Save_Click(object sender, EventArgs e){var saveName = $"{filePath}{fileName}.jpg";imgMap.Save(saveName);this.btn_Save.Enabled = false;MessageBox.Show($"保存成功:{saveName}");}#endregion

9、录像

         #region 录像/// <summary>/// 开始录像/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void btn_StartVideo_Click(object sender, EventArgs e){string videoName = $"{filePath}{fileName}.MP4";IsStartVideo = true;//开始计时timer_count.Enabled = true;//配置录像参数(宽,高,帧率,比特率等参数)VideoCapabilities这个属性会返回摄像头支持哪些配置,从这里面选一个赋值接即可videoCapture.VideoResolution = videoCapture.VideoCapabilities[0];//设置回调,aforge会不断从这个回调推出图像数据videoCapture.NewFrame += Camera_NewFrame;videoWriter = new AForge.Video.FFMPEG.VideoFileWriter();//打开摄像头//videoCapture.Start();//打开录像文件(如果没有则创建,如果有也会清空),这里还有关于视频宽高、帧率、格式、比特率videoWriter.Open(videoName,videoCapture.VideoResolution.FrameSize.Width,videoCapture.VideoResolution.FrameSize.Height,videoCapture.VideoResolution.AverageFrameRate,AForge.Video.FFMPEG.VideoCodec.MPEG4,videoCapture.VideoResolution.BitCount);}//this.lab_Time//摄像头输出回调private void Camera_NewFrame(object sender, AForge.Video.NewFrameEventArgs eventArgs){imgMap = eventArgs.Frame;lock (imgMap){if (eventArgs != null && eventArgs.Frame != null){try{//写到文件videoWriter.WriteVideoFrame(eventArgs.Frame);}catch (Exception){}}}}/// <summary>/// 暂停录像/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void btn_PauseVideo_Click(object sender, EventArgs e){var stopBtnName = this.btn_PauseVideo.Text;if (stopBtnName == "暂停录像"){this.btn_PauseVideo.Text = "恢复录像";//暂停计时timer_count.Enabled = false;IsStartVideo = false;}if (stopBtnName == "恢复录像"){this.btn_PauseVideo.Text = "暂停录像";//恢复计时timer_count.Enabled = true;IsStartVideo = true;}}/// <summary>/// 停止录像/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void btn_EndVideo_Click(object sender, EventArgs e){IsStartVideo = false;timer_count.Enabled = false;videoWriter.Close();MessageBox.Show("停止录像");}#endregion

需要特别注意
videoWriter.Open(string fileName, int width, int height, int frameRate, VideoCodec codec, int bitRate);
width与height必须为偶数,否则报错Video file resolution must be a multiple of two.

10、计时器

     #region 计时器响应函数/// <summary>/// 计时器/// </summary>/// <param name="source"></param>/// <param name="e"></param>public void tick_count(object source, System.Timers.ElapsedEventArgs e){tick_num++;int Temp = tick_num;int Second = Temp % 60;int Minute = Temp / 60;if (Minute % 60 == 0){Hour = Minute / 60;Minute = 0;}else{Minute = Minute - Hour * 60;}string HourStr = Hour < 10 ? $"0{Hour}" : Hour.ToString();string MinuteStr = Minute < 10 ? $"0{Minute}" : Minute.ToString();string SecondStr = Second < 10 ? $"0{Second}" : Second.ToString();String tick = $"{HourStr}:{MinuteStr}:{SecondStr}";this.Invoke((EventHandler)(delegate{this.lab_Time.Text = tick;}));}#endregion

11、完整代码

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.Controls;
using System.Windows.Forms;namespace AForge拍照及录像
{public partial class Form1 : Form{public Form1(){InitializeComponent();}#region 属性/// <summary>/// 设备源/// 用来操作摄像头/// </summary>private AForge.Video.DirectShow.VideoCaptureDevice videoCapture;/// <summary>/// 摄像头设备集合/// </summary>private AForge.Video.DirectShow.FilterInfoCollection infoCollection;/// <summary>/// 图片/// </summary>private System.Drawing.Bitmap imgMap;/// <summary>/// 文件保存路径/// </summary>private readonly string filePath = $"D:\\VS主题\\图片\\";/// <summary>/// 文件名称/// </summary>private readonly string fileName = $"{DateTime.Now.ToString("yyyyMMddhhmmssffff")}";/// <summary>/// 用与把每一帧图像写入到视频文件/// </summary>private AForge.Video.FFMPEG.VideoFileWriter videoWriter;/// <summary>/// 是否开始录像/// </summary>private bool IsStartVideo = false;/// <summary>/// 写入次数/// </summary>private int tick_num = 0;/// <summary>/// 录制多少小时,只是为了定时间计算录制时间使用/// </summary>private int Hour = 0;/// <summary>/// 计时器/// </summary>private System.Timers.Timer timer_count;#endregion#region 窗口加载与关闭/// <summary>/// 讲题加载事件/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void Form1_Load(object sender, EventArgs e){InitCamera();InitCameraSelect();this.btn_Capture.Enabled = false;this.btn_Save.Enabled = false;this.pb_BoxPanel.SizeMode = PictureBoxSizeMode.Zoom;//图片大小按比例适应控件,不加的话图片显示问题太大this.gb_CapturePanel.Visible = false;//默认不显示照片区域,拍照时在显示//秒表timer_count = new System.Timers.Timer();   //实例化Timer类,设置间隔时间为1000毫秒;timer_count.Elapsed += new System.Timers.ElapsedEventHandler(tick_count);   //到达时间的时候执行事件;timer_count.AutoReset = true;   //设置是执行一次(false)还是一直执行(true);timer_count.Interval = 1000;}/// <summary>/// 窗口关闭时/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void Form1_FormClosing(object sender, FormClosingEventArgs e){EndCamera();}#endregion#region 实例化/// <summary>/// 实例化摄像头/// </summary>public void InitCamera(){try{//检测电脑上的摄像头设备infoCollection = new AForge.Video.DirectShow.FilterInfoCollection(AForge.Video.DirectShow.FilterCategory.VideoInputDevice);}catch (Exception ex){MessageBox.Show($"没有找到设备:{ex.Message}", "Error");}}//加载摄像头选择public void InitCameraSelect(){this.cb_CameraSelect.DropDownStyle = ComboBoxStyle.DropDownList;//根据读取到的摄像头加载选择项foreach (AForge.Video.DirectShow.FilterInfo item in infoCollection){this.cb_CameraSelect.Items.Add(item.Name);}//for (int i = 1; i <= infoCollection.Count; i++)//{//    this.cb_CameraSelect.Items.Add("摄像头" + i);//}}#endregion#region  摄像头的连接读取与关闭/// <summary>/// 连接按钮/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void btn_Connect_Click(object sender, EventArgs e){var CameraSelect = this.cb_CameraSelect.Text;var selectIndex = this.cb_CameraSelect.SelectedIndex;//已有连接的摄像头时先关闭if (videoCapture != null){EndCamera();}videoCapture = new AForge.Video.DirectShow.VideoCaptureDevice(infoCollection[selectIndex].MonikerString);//启动摄像头this.vsp_Panel.VideoSource = videoCapture;this.vsp_Panel.Start();this.btn_Capture.Enabled = true;this.btn_Save.Enabled = false;}/// <summary>/// 关闭按钮/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void btn_Close_Click(object sender, EventArgs e){EndCamera();}/// <summary>/// 关闭摄像头/// </summary>public void EndCamera(){if (this.vsp_Panel.VideoSource != null){//也可以用 Stop() 方法关闭//指示灯停止且等待this.vsp_Panel.SignalToStop();//停止且等待this.vsp_Panel.WaitForStop();this.vsp_Panel.VideoSource = null;}}#endregion#region 拍照与保存/// <summary>/// 拍照/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void btn_Capture_Click(object sender, EventArgs e){imgMap = this.vsp_Panel.GetCurrentVideoFrame();this.gb_CapturePanel.Visible = true;this.pb_BoxPanel.Image = imgMap;this.btn_Save.Enabled = true;}/// <summary>/// 保存事件/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void btn_Save_Click(object sender, EventArgs e){var saveName = $"{filePath}{fileName}.jpg";imgMap.Save(saveName);this.btn_Save.Enabled = false;MessageBox.Show($"保存成功:{saveName}");}#endregion#region 录像/// <summary>/// 开始录像/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void btn_StartVideo_Click(object sender, EventArgs e){string videoName = $"{filePath}{fileName}.MP4";IsStartVideo = true;//开始计时timer_count.Enabled = true;//配置录像参数(宽,高,帧率,比特率等参数)VideoCapabilities这个属性会返回摄像头支持哪些配置,从这里面选一个赋值接即可videoCapture.VideoResolution = videoCapture.VideoCapabilities[0];//设置回调,aforge会不断从这个回调推出图像数据videoCapture.NewFrame += Camera_NewFrame;videoWriter = new AForge.Video.FFMPEG.VideoFileWriter();//打开摄像头//videoCapture.Start();//打开录像文件(如果没有则创建,如果有也会清空),这里还有关于视频宽高、帧率、格式、比特率videoWriter.Open(videoName,videoCapture.VideoResolution.FrameSize.Width,videoCapture.VideoResolution.FrameSize.Height,videoCapture.VideoResolution.AverageFrameRate,AForge.Video.FFMPEG.VideoCodec.MPEG4,videoCapture.VideoResolution.BitCount);}//this.lab_Time//摄像头输出回调private void Camera_NewFrame(object sender, AForge.Video.NewFrameEventArgs eventArgs){imgMap = eventArgs.Frame;lock (imgMap){if (eventArgs != null && eventArgs.Frame != null){try{//写到文件videoWriter.WriteVideoFrame(eventArgs.Frame);}catch (Exception){}}}}/// <summary>/// 暂停录像/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void btn_PauseVideo_Click(object sender, EventArgs e){var stopBtnName = this.btn_PauseVideo.Text;if (stopBtnName == "暂停录像"){this.btn_PauseVideo.Text = "恢复录像";//暂停计时timer_count.Enabled = false;IsStartVideo = false;}if (stopBtnName == "恢复录像"){this.btn_PauseVideo.Text = "暂停录像";//恢复计时timer_count.Enabled = true;IsStartVideo = true;}}/// <summary>/// 停止录像/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void btn_EndVideo_Click(object sender, EventArgs e){IsStartVideo = false;timer_count.Enabled = false;videoWriter.Close();MessageBox.Show("停止录像");}#endregion#region 计时器响应函数/// <summary>/// 计时器/// </summary>/// <param name="source"></param>/// <param name="e"></param>public void tick_count(object source, System.Timers.ElapsedEventArgs e){tick_num++;int Temp = tick_num;int Second = Temp % 60;int Minute = Temp / 60;if (Minute % 60 == 0){Hour = Minute / 60;Minute = 0;}else{Minute = Minute - Hour * 60;}string HourStr = Hour < 10 ? $"0{Hour}" : Hour.ToString();string MinuteStr = Minute < 10 ? $"0{Minute}" : Minute.ToString();string SecondStr = Second < 10 ? $"0{Second}" : Second.ToString();String tick = $"{HourStr}:{MinuteStr}:{SecondStr}";this.Invoke((EventHandler)(delegate{this.lab_Time.Text = tick;}));}#endregion}
}

12、测试结果

拍照结果如下:

录像结果如下:

12、Demo下载

完整Demo下载: C# WinForm使用AForge拍照及录像

13、踩坑经历及解决方案

参考:细数AForge.Video.FFMPEG使用过程中踩的坑及解决方案

C# 使用AForge调用笔记本摄像头拍照及录像相关推荐

  1. 用matlab调用笔记本摄像头拍照程序

    前提笔记本摄像头驱动安装正常. 平时qq视频拍照没问题就ok 首先查询笔记本摄像头的具体参数(使用imaqhwinfo) 一..在命令窗口输入 imaqhwinfo,得到下图的参数: 当然这一步可以不 ...

  2. java 调用笔记本摄像头拍照_教程:如何使用Java和C++在应用程序中实现面部识别

    全文共8470字,预计学习时长25分钟 来源:xaecong HOG:梯度方向直方图(histogram of orientedgradients)是一种图片描述符格式,它能够汇总图像(例如人脸)的主 ...

  3. H5调用手机摄像头拍照,如何压缩后上传

    H5调用手机摄像头拍照后,怎样压缩再上传? 实际的压缩功能,就是利用canvas画布功能,将图片进行裁剪后保存图片的base64数据流,然后上传. 案例全部代码,示下: <!DOCTYPE ht ...

  4. JS调用本地摄像头拍照(兼容各大浏览器及IE8+)

    最近做的项目遇到了个难题,使用video+canvas+getUserMedia()写的调用本地摄像头拍照不兼容IE. 原因:IE8及以下不支持HTML5标签:video和canvas:IE11及以下 ...

  5. 利用Python+opencv进行视频文件的读取和保存,打开笔记本摄像头拍照保存、图像在窗口显示等操作

    版权声明:本文为博主原创文章,转载请附源链接 一.视频文件的读取和保存 Opencv中视频的读入是用VideoCapture函数,保存用的是VideoWriter函数.这两个函数支持的视频格式因电脑系 ...

  6. 在微信小程序中 调用前置摄像头拍照 后置摄像头拍照扫码

    1.需求:点击扫码按钮,扫描二维码识别单号    实现:  <view class="getcode" bindtap="scanCode"> &l ...

  7. ROS调用笔记本摄像头和外界摄像头问题汇总(本人亲身经历)非常好用

    ROS调用笔记本摄像头和外界摄像头问题汇总(本人亲身经历) 运行打开摄像头命令必须在主虚拟机运行 一.video0找不到 本人想要调用笔记本摄像头完成一些基本的标定时候,遇到问题: 或者执行命令: l ...

  8. 利用python调用本地摄像头拍照,对图片命名并保存到指定位置,带界面

    1.需求: 因项目需要做一个以图搜图的小程序,需要储备零件图库,约1000种 2.原计划&痛点 原本想通过手机挨个拍照,再拷贝出来,重命名,这样会耽误大量时间,且容易出错 3.解决方案 于是做 ...

  9. 原生html调手机拍照,如何让HTML5调用手机摄像头拍照——实践就是一切

    原文:如何让HTML5调用手机摄像头拍照--实践就是一切 NanShan 小编将思路提供给了大家,学编程最重要的是实践,我这虽然有完善的代码,但是希望大家都可以自己写出属于自己的代码 HTML5 Th ...

最新文章

  1. 网站性能优化的常用方法
  2. hdu 1208(简单dp)
  3. 蒙特卡洛粒子滤波定位算法_ROS -- 最简单的自主ACML定位
  4. 对类Vue的MVVM前端库的实现
  5. 【功能业务篇】APP获取用户定位、传参经纬度思考
  6. PHP自定义数组转Json字符串函数
  7. 在VC中用CMenuXP使应用程序拥有Office XP风格的界面
  8. Latex:大于等于号和小于等于号
  9. 【Spark重点难点】你的数据存在哪了?
  10. VMware的磁盘格式化
  11. 小米手机刷android one,小米手机(Mi One)刷机教程详解完整版 (刷MIUI官方刷机包)...
  12. php htmlpurifier,php – HtmlPurifier – 允许数据属性
  13. apt-get安装包失败提示The following packages have unmet dependencies
  14. Canvas流星雨特效
  15. WordSequence API
  16. 泛微OA二次开发基础培训文档
  17. 浏览器访问linux服务器上tomcat中的pdf文件时报404,无法访问的问题
  18. 净利润同比增长54%,阿里巴巴下沉市场称王?
  19. 游戏心得:解决在win7下不能安装apploc.msi(applocale)
  20. Centos6.5:NFS

热门文章

  1. 收藏了两年的嵌入式AI资源学习笔记,今天全分享给大家(附代码/资料/视频/学习规划)...
  2. 【安卓软件】KMPlayer-一款完美的媒体播放器 可以播放所有格式的字幕和视频
  3. python中join什么意思_python里join是什么意思
  4. 自动洗车机的远程监测与设备联动
  5. wireshark插件开发详细流程(含源码)
  6. source deactivate xxx:bash deactivate:没有那个文件或目录
  7. 【Java笔记+踩坑】SpringBoot——基础
  8. Google Glass 开发
  9. 如何保证进程不被杀死的几个办法
  10. win10开机显示“其他用户“”如何解决