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文件夹下的所有文件拷贝到项目输出路径下。如:bin\x86\Debug。

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

 项目运行报错,如下:

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

如下就可以了

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

添加组件以后如下:

代码如下:

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

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值