zoukankan      html  css  js  c++  java
  • AForge处理视频和拍照(暂时没有音频)

    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;

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

     

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

    )

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

     

      

      

     

     安装以后界面

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

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

     项目运行报错,如下:

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

    如下就可以了

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

    添加组件以后如下:

    代码如下:

    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.2.2.5.zip库连接地址:https://download.csdn.net/download/LongtengGensSupreme/21057551

    龙腾一族至尊龙骑
  • 相关阅读:
    jQuery的版本兼容问题
    web页面锁屏初级尝试
    mvc5之文件上传
    魔方基础入门教程
    XCube和X组件的入门级使用教程
    蔬菜大棚监控与管理 1.0版本(未完善)
    蔬菜大棚 数据库设计 0.5版本()
    记录一段存储过程
    MPU9250九轴陀螺仪--读接口数据
    MPU9250九轴陀螺仪--连接MPU9250
  • 原文地址:https://www.cnblogs.com/1175429393wljblog/p/15132141.html
Copyright © 2011-2022 走看看