0
点赞
收藏
分享

微信扫一扫

AForge处理视频和拍照(暂时没有音频)

gy2006_sw 2022-06-28 阅读 23

AForge处理视频和拍照

下载AForge相关的dll: AForge, AForge.Controls ,AForge.Video ,AForge.Video.DirectShow, AForge.Video.FFMPEG

包括如下:

using AForge;
using AForge.Controls;
using AForge.Video;
using AForge.Video.DirectShow;
using AForge.Video.FFMPEG;

AForge处理视频和拍照(暂时没有音频)_ide

 

相关dll类库下载地址:​​http://www.aforgenet.com/framework/downloads.htm​​

 

 AForge处理视频和拍照(暂时没有音频)_数据_02

 

 通过下载地址下载,显示如下,提示下载错误,食了很多次都是如此,因此我是用了nuget package下载,就是上图 右小角标记的 NuGet packages 通过指令安装(注:本人在NuGet 包管理器界面中输入搜索AForge.Video.FFMPEG,却无法搜索到对应的包,但在程序包管理器控制台中去可以安装)

)

AForge处理视频和拍照(暂时没有音频)_非托管_03

 

  在下载界面http://www.aforgenet.com/framework/downloads.html,右下角 点击NuGet packages,或者直接使用网址(AForge.Video.FFMPEG下载地址:​​https://www.nuget.org/packages?q=AForge.NET​​)也可以,打开以后下划找到ffmpeg,点击即可。

AForge处理视频和拍照(暂时没有音频)_数据_04

 AForge处理视频和拍照(暂时没有音频)_ide_05

  

AForge处理视频和拍照(暂时没有音频)_数据_06

  

AForge处理视频和拍照(暂时没有音频)_ide_07

 

 AForge处理视频和拍照(暂时没有音频)_ide_08

 

 安装以后界面

AForge处理视频和拍照(暂时没有音频)_非托管_09

 

注意:使用前,需要将Externals文件夹下的所有文件拷贝到项目输出路径下。如:bin\x86\Debug。

 

AForge处理视频和拍照(暂时没有音频)_数据_10

 

 

下面只要在项目中添加引用即可使用对应的dll进行音视频的开发了

AForge处理视频和拍照(暂时没有音频)_数据_11

 

 项目运行报错,如下:

AForge处理视频和拍照(暂时没有音频)_数据_12

 

 是因为虽然将Externals文件夹下的所有文件拷贝到项目输出路径下,本人是吧需要的库放到Library中了,然后设置了覅知道输出目录:始终复制,并没有放到bin\Debug下

AForge处理视频和拍照(暂时没有音频)_ide_13

如下就可以了

AForge处理视频和拍照(暂时没有音频)_ide_14

 

添加视频播放控件,操作如下:

AForge处理视频和拍照(暂时没有音频)_非托管_15

 

添加组件以后如下:

AForge处理视频和拍照(暂时没有音频)_ide_16

 

 

AForge处理视频和拍照(暂时没有音频)_ide_17

 

 

代码如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using AForge;
using AForge.Controls;
using AForge.Video;
using AForge.Video.DirectShow;
using AForge.Video.FFMPEG;

namespace WindowsFormsTestVideo
{
/// <summary>
/// 测试视频和拍照
/// </summary>
public partial class Frmmain : Form
{
/// <summary>
/// 构造函数
/// </summary>
public Frmmain()
{
InitializeComponent();
}

#region Fields and Propertities 字段和属性
/// <summary>
/// 摄像头实时显示控件对象,窗体上没有控件,只是用了该对象来截图
/// </summary>
private VideoSourcePlayer VideoSourcePlayerTest = null;

/// <summary>
/// 摄像头捕获对象
/// </summary>
private VideoCaptureDevice videoCaptureDevice = null;

/// <summary>
/// 摄像头图片写入文件对象,其实视频写入只不过是是写入的一张张图片而已
/// </summary>
private VideoFileWriter videoFileWriter = null;

/// <summary>
/// 摄像头设备集合
/// </summary>
FilterInfoCollection filterInfoCollection = null;

/// <summary>
/// 是否开始录像,开始录像标记
/// </summary>
bool isStartRecordVideo = false;

/// <summary>
/// 图像分辨率
/// </summary>
VideoCapabilities[] videoCapabilities = null;
#endregion

#region Methods 方法

/// <summary>
/// 记录日志
/// </summary>
/// <param name="message">日志信息</param>
private static void Log(string message, MessageType messageType = MessageType.info)
{
try
{
switch (messageType)
{
default:
case MessageType.info:
//WindowsFormsTestVideo.exe Information: 0 : 启动日志记录
Trace.TraceInformation($"{DateTime.Now}:{message}");
break;
case MessageType.error:
//WindowsFormsTestVideo.exe Error: 启动日志记录
Trace.TraceError($"{DateTime.Now}:{message}");
break;
case MessageType.fail:
//失败: 启动日志记录
Trace.Fail($"{DateTime.Now}:{message}");
break;
}
}
catch (Exception ex)
{
Log(ex.Message, MessageType.error);
}
}
#endregion

#region Events 事件
private void Frmmain_Load(object sender, EventArgs e)
{
#region log日志
System.Diagnostics.Trace.Listeners.Clear();
System.Diagnostics.Trace.AutoFlush = true;
System.Diagnostics.Trace.Listeners.Add(new System.Diagnostics.TextWriterTraceListener("log日志.log"));
Log($"{DateTime.Now}:启动日志记录");
#endregion

//初始化
//摄像头捕获器
videoCaptureDevice = new VideoCaptureDevice();
//视频录像器
videoFileWriter = new VideoFileWriter();


#region 添加摄像头,添加添加分辨率,添加视频格式
try
{
//清空摄像头,视频格式,分辨率集合
cbxSelectVideoCapture.Items.Clear();
cbxSelectVideoSaveFormat.Items.Clear();
cbxSelectResolution.Items.Clear();
//分辨率集合
videoCapabilities = null;

//添加摄像头
filterInfoCollection = new FilterInfoCollection(FilterCategory.VideoInputDevice);
foreach (FilterInfo item in filterInfoCollection)
{
cbxSelectVideoCapture.Items.Add(item.Name);
}

//默认选择第一个摄像头设备
cbxSelectVideoCapture.SelectedIndex = 0;

//添加视频格式
foreach (var item in Enum.GetNames(typeof(VideoCodec)))
{
cbxSelectVideoSaveFormat.Items.Add(item);
}
cbxSelectVideoSaveFormat.SelectedIndex = 0;
}
catch (Exception ex)
{
Log(ex.Message, MessageType.error);
}
#endregion
}

/// <summary>
/// 选择不同的摄像头
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void cbxSelectVideoCapture_SelectedIndexChanged(object sender, EventArgs e)
{
try
{
//添加添加分辨率
videoCaptureDevice = new VideoCaptureDevice(filterInfoCollection[cbxSelectVideoCapture.SelectedIndex].MonikerString);
videoCaptureDevice.NewFrame += VideoCaptureDevice_NewFrame;

//分辨率集合
videoCapabilities = videoCaptureDevice.VideoCapabilities;
//清空,不同的摄像头有不同的分辨率
cbxSelectResolution.Items.Clear();

foreach (var item in videoCapabilities)
{
cbxSelectResolution.Items.Add(item.FrameSize);
}
//默认当前摄像头的第一个分辨率
cbxSelectResolution.SelectedIndex = 0;

//videoCaptureDevice.VideoResolution = videoCaptureDevice.VideoCapabilities[1];
//videoCaptureDevice.Start();
////视频显示
//vspPlayer.VideoSource = videoCaptureDevice;
//vspPlayer.Start();
}
catch (Exception ex)
{
Log(ex.Message, MessageType.error);
}
}

/// <summary>
/// 选择不同的分辨率
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void cbxSelectResolution_SelectedIndexChanged(object sender, EventArgs e)
{
try
{
if (videoCaptureDevice.IsRunning || vspPlayer.IsRunning)
{
videoCaptureDevice.SignalToStop();
videoCaptureDevice.WaitForStop();
vspPlayer.SignalToStop();
vspPlayer.WaitForStop();
VideoSourcePlayerTest.SignalToStop();
VideoSourcePlayerTest.WaitForStop();
}
videoCaptureDevice.VideoResolution = videoCaptureDevice.VideoCapabilities[cbxSelectResolution.SelectedIndex];
videoCaptureDevice.Start();
//视频显示
vspPlayer.VideoSource = videoCaptureDevice;
vspPlayer.Start();

VideoSourcePlayerTest = new AForge.Controls.VideoSourcePlayer();
VideoSourcePlayerTest.VideoSource = videoCaptureDevice;
VideoSourcePlayerTest.Start();
}
catch (Exception ex)
{
Log(ex.Message, MessageType.error);
}
}

/// <summary>
/// 获取摄像头的当前帧,可以属实现实时动态的效果
/// </summary>
/// <param name="sender"></param>
/// <param name="eventArgs"></param>
private void VideoCaptureDevice_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
try
{
//eventArgs.Frame; 获取摄像头的每一帧图像


//pbxPicture.Image = eventArgs.Frame;//直接复制报错
//1、克隆
//this.Invoke(new MethodInvoker(delegate ()
//{
// Bitmap image = (Bitmap)eventArgs.Frame.Clone();
// pbxPicture.Image = image;
// pbxPicture.Refresh();
//}));

//2、根据句柄创建
Bitmap bitmap = eventArgs.Frame;
//pbxPicture.Image = Bitmap.FromHbitmap(bitmap.GetHbitmap());


if (isStartRecordVideo)
{
//视频录像---向文件中写入摄像头的每一帧
videoFileWriter.WriteVideoFrame(bitmap);
}
}
catch (Exception ex)
{
Log(ex.Message, MessageType.error);
}


#region 测试Bitmap和Marshal.Copy
////测试Bitmap和Marshal.Copy
//Bitmap bitmap1 = new Bitmap("./123456.jpg");
//Rectangle rectangle = new Rectangle(0, 0, bitmap1.Width, bitmap1.Height);
////锁定bitmap到系统内存
//System.Drawing.Imaging.BitmapData bitmapData = bitmap1.LockBits(rectangle, System.Drawing.Imaging.ImageLockMode.ReadWrite, bitmap1.PixelFormat);
////BitmapData 指定 Bitmap 的特性,如大小、像素格式、像素数据在内存中的起始地址以及每个扫描行的长度(步幅)。
//var pixel = bitmapData.PixelFormat; //Bitmap 的特性 宽度
//var Width = bitmapData.Width;//Bitmap 的特性 宽度
//var Height = bitmapData.Height; //Bitmap 的特性 高度
//var firstStartAddress = bitmapData.Scan0;//像素数据在内存中的起始地址
//var Stride = bitmapData.Stride;//像素数据在内存中的每个扫描行的长度(步幅)
//var leength = Math.Abs(bitmapData.Stride) * bitmapData.Height;
//byte[] bts = new byte[leength];
//// 将数据从非托管内存指针复制到托管 8 位无符号整数数组
//System.Runtime.InteropServices.Marshal.Copy(firstStartAddress, bts, 0, bts.Length);
////使rgb图片变红色
//for (int i = 2; i < bts.Length; i += 3)
//{
// bts[i] = 255;
//}
////将数据从一维托管 8 位无符号整数数组复制到非托管内存指针。
//System.Runtime.InteropServices.Marshal.Copy(bts, 0, firstStartAddress, bts.Length);
//bitmap1.UnlockBits(bitmapData);

//bitmap1.Save("./123456new.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
//bitmap1.Dispose();

////测试托管内存到非托管内存
//string a = "123456";
//IntPtr dd = System.Runtime.InteropServices.Marshal.AllocHGlobal(10);
//char[] chars = a.ToCharArray();
//// 将数据从一维托管字符数组复制到非托管内存指针。
//System.Runtime.InteropServices.Marshal.Copy(chars, 0, dd, chars.Length);
////修改
////
//char[] chars1 = new char[chars.Length];
////将数据从非托管内存指针复制到托管字符数组。
//System.Runtime.InteropServices.Marshal.Copy(dd, chars1, 0, chars.Length);
//System.Runtime.InteropServices.Marshal.FreeHGlobal(dd);
#endregion
}

/// <summary>
/// 选择不同的视频格式
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void cbxSelectVideoSaveFormat_SelectedIndexChanged(object sender, EventArgs e)
{
//try
//{
// //cbxSelectVideoSaveFormat.SelectedIndex = 0;
//}
//catch (Exception ex)
//{
// Log(ex.Message, MessageType.error);
//}
}

/// <summary>
/// 开始录像
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnStartVideo_Click(object sender, EventArgs e)
{
try
{
if (cbxSelectVideoSaveFormat.SelectedIndex < 0 || !Enum.TryParse(cbxSelectVideoSaveFormat.SelectedItem.ToString(), out VideoCodec videoCodec))
{
MessageBox.Show("请选择视频格式", "提示:");
cbxSelectVideoSaveFormat.Focus();
return;
}

//创建具有指定名称和属性的视频文件。
//文件名:要创建的视频文件名称。
//宽度:视频文件的帧宽。
//高:视频文件的帧高。
//帧速率:视频文件的帧率。
//编码:视频编解码器用于压缩
VideoCapabilities capabilities = videoCapabilities[cbxSelectResolution.SelectedIndex];
int height = capabilities.FrameSize.Height;// 720;//高:视频文件的帧高。
int width = capabilities.FrameSize.Width;// 1280;//宽度:视频文件的帧宽。
//int frameRate = capabilities.FrameRate;// 30;//帧速率:视频文件的帧率。
int frameRate = capabilities.AverageFrameRate;// 30;//帧速率:视频文件的帧率。

switch (cbxSelectVideoSaveFormat.SelectedIndex)
{
case 0://MPEG-4 part 2.
case 3:// MSMPEG4v2 = 3,MPEG-4 part 2 Microsoft variant version 2.
case 4:// MSMPEG4v3 = 4,MPEG - 4 part 2 Microsoft variant version 3.
case 7://MPEG2 = 7,MPEG-2 part 2.
//创建具有指定名称和属性的视频文件,文件名:要创建的视频文件名称,宽度:视频文件的帧宽,高:视频文件的帧高,帧速率:视频文件的帧率,编码:视频编解码器用于压缩
videoFileWriter.Open("video.mp4", width, height, frameRate, videoCodec);
break;
case 1:// WMV1 = 1 Windows Media Video 7
case 2:// WMV2 = 2,Windows Media Video 8.
videoFileWriter.Open("video.wmv", width, height, frameRate, videoCodec);
break;
case 5://H263P = 5, H.263+ / H.263-1998 / H.263 version 2.
videoFileWriter.Open("video.mp4", width, height, frameRate, videoCodec);
break;
case 6://FLV1 = 6, Flash Video (FLV) / Sorenson Spark / Sorenson H.263.
videoFileWriter.Open("video.flv", width, height, frameRate, videoCodec);
break;
case 8://Raw = 8,Raw (uncompressed) video.
videoFileWriter.Open("video.mp4", width, height, frameRate, videoCodec);
break;
case -1:
//摘要: Default = -1 Default video codec, which FFmpeg library selects for the specified file format.
default:
videoFileWriter.Open("video.mkv", width, height, frameRate, videoCodec);
break;
}
isStartRecordVideo = true;//开始录像标记
lblRecord.ForeColor = Color.Red;
lblRecord.Text = "录像中......";
}
catch (Exception ex)
{
Log(ex.Message, MessageType.error);
}
}

/// <summary>
/// 停止录像
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnStopVideo_Click(object sender, EventArgs e)
{
try
{
//关闭录像
isStartRecordVideo = false;
videoFileWriter.Close();
lblRecord.ForeColor = DefaultForeColor;
lblRecord.Text = "";
}
catch (Exception ex)
{
Log(ex.Message, MessageType.error);
}
}

/// <summary>
/// 拍照
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnTakePhoto_Click(object sender, EventArgs e)
{
try
{
if (vspPlayer.IsRunning && videoCaptureDevice.IsRunning)
{
//拍照成功,照片保存路径
var path = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "takephoto.jpg");
//使用实时显示摄像头控件
//Bitmap image = vspPlayer.GetCurrentVideoFrame();
//AForge.Controls.VideoSourcePlayer
Bitmap image = VideoSourcePlayerTest.GetCurrentVideoFrame();
image.Save(path, System.Drawing.Imaging.ImageFormat.Jpeg);
lblTakephotoSavePath.Text = $"拍照成功,照片保存路径:{path}";
pbxPicture.SizeMode = PictureBoxSizeMode.Zoom;
pbxPicture.Image = Bitmap.FromHbitmap(image.GetHbitmap());
image.Dispose();
}
}
catch (Exception ex)
{
Log(ex.Message, MessageType.error);
}
}

private void Frmmain_FormClosed(object sender, FormClosedEventArgs e)
{
try
{
videoCaptureDevice.SignalToStop();
videoCaptureDevice.WaitForStop();
vspPlayer.SignalToStop();
vspPlayer.WaitForStop();

VideoSourcePlayerTest.SignalToStop();
VideoSourcePlayerTest.WaitForStop();

//videoCaptureDevice.Stop();
//vspPlayer.Stop();
//VideoSourcePlayerTest.Stop();
}
catch (Exception ex)
{
Log(ex.Message, MessageType.error);
}
}
#endregion
}

/// <summary>
/// 信息的类型
/// </summary>
public enum MessageType
{
/// <summary>
///正常记录信息
/// </summary>
info = 0,
/// <summary>
/// 错误信息
/// </summary>
error,
/// <summary>
/// 失败信息
/// </summary>
fail,
}
}

 

 

运行效果如下:

AForge处理视频和拍照(暂时没有音频)_非托管_18

 

 

龙腾一族至尊龙骑

举报

相关推荐

0 条评论