C#调用摄像头录制视频
2021 年 06 月 11 日 6695 386 字 暂无评论

前言:

最近项目需求,在C#平台上调用外接USB摄像头,做一系列操作,其中包括视频录制,保存视频。

看起来简单的一个操作,但感觉还是有点复杂的,经过查询资料最终完成,所以有必要做个记录。

1、首先需要添加两个动态链接库引用:DShowNET.dll 和 ICameraDII.dll

2、直接上代码

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.Forms;
using OpenCvSharp;
using System.Threading;
using OpenCvSharp.Flann;
using System.IO;
using ICameraDll.DirectX.Capture;

namespace UGV
{
    public partial class Image_processing : Form
    {
        private Thread Image_processThread;
        static string fileName = "D:\\sorfware\\C#project\\UGV2020-11-12\\UGV\\p";

        Capture capture;                  //摄像头操作
        Filters filters = new Filters();  //Filter集合
        public Image_processing()
        {
            InitializeComponent();
        }

        private int GetffshowIndex()
        {
            FilterCollection videoCompressors = this.filters.VideoCompressors;
            for (var i = 0; i < videoCompressors.Count; i++)
            {
                if ((videoCompressors[i] != null) && videoCompressors[i].Name.Equals("ffdshow video encoder"))
                {
                    return i;
                }
            }
            return -1;
        }

        private void CreateFilepath(string FilePath)
        {
            var dir = FilePath.Remove(FilePath.LastIndexOf("\\"));
            if (!Directory.Exists(dir)) 
            {
                Directory.CreateDirectory(dir);
            }
        }


        //录制视频
        private void Record_Video(object sender, EventArgs e)
        {
            //设置承载控件
            Control videoControl = pictureBox1;
            //设置文件路径
            string filePath = "D:\\sorfware\\C#project\\UGV2020-11-12\\UGV\\";
            string fileName = "test.mp4";

            //检测摄像头是否被占用
            if (capture != null)
            {
                capture.Stop();
                capture.DisposeCapture();
            }
            //获取ffshow视频解码器索引
            var ffshowIndex = GetffshowIndex();

            if (ffshowIndex > 0)
            {
                var File = filePath + fileName;
                CreateFilepath(File);
                //这里0为电脑本机摄像头,后面按序为外接摄像头
                capture = new Capture(new Filters().VideoInputDevices[1], null);

                //设置承载控件
                capture.PreviewWindow = videoControl;

                //设置视频解码器
                capture.VideoCompressor = filters.VideoCompressors[ffshowIndex];

                //设置保存的文件路径和文件名
                capture.Filename = File;

                //设置帧
                capture.FrameRate = 60;

                //设置分辨率
                capture.FrameSize = new System.Drawing.Size(1920, 1080);

                //开始录制
                capture.Start();
            }
        }

        private void Run_cap() 
        {
            var capture = new VideoCapture(0);
            int sleepTime = (int)Math.Round(1000 / capture.Fps);

            Mat image = new Mat();
            Mat image1 = new Mat();


            while (true)
            {
                capture.Read(image);
                if (image.Empty())
                    break;
                pictureBox1.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(image);



                Cv2.MedianBlur(image, image1, 5);
                Cv2.Flip(image1, image1, FlipMode.XY); //翻转图片

                image1 = image.CvtColor(ColorConversionCodes.BGR2GRAY);//灰度图片
                //pictureBox2.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(image1);

                Cv2.Threshold(image1, image1, 155, 255, ThresholdTypes.BinaryInv);//二值化图片
                //pictureBox2.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(image1);

                Cv2.Blur(image1, image1, new OpenCvSharp.Size(3, 3));//滤波
                //pictureBox2.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(image1);

                //Cv2.Canny(image1, image1, 100, 200);//边缘检测
                //pictureBox2.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(image1);

                OpenCvSharp.Point[][] contours;//获得轮廓
                HierarchyIndex[] hierarchly;
                Cv2.FindContours(image1, out contours, out hierarchly, RetrievalModes.Tree, ContourApproximationModes.ApproxSimple, new OpenCvSharp.Point(0, 0));

                //将结果画出并返回结果
                Mat image2 = Mat.Zeros(image.Size(), image.Type());
                double[] center = new double[2];
                for (int i = 0; i < contours.Length; i++)
                {
                    if (Cv2.ContourArea(contours[i]) > 1000)  //去掉小轮廓
                    {
                        int num = 0;
                        Scalar color = new Scalar(0, 0, 255);
                        Cv2.DrawContours(image2, contours, i, color, 2, LineTypes.Link8, hierarchly);
                        for (int j = 0; j < contours[i].Length; j++)
                        {
                            num = j + 1;
                            int xx = contours[i][j].X;
                            int yy = contours[i][j].Y;
                            center[0] += xx;
                            center[1] += yy;
                        }
                        center[0] = center[0] / num;
                        center[1] = center[1] / num;
                        Console.WriteLine("X:" + center[0].ToString() + " Y:" + center[1].ToString());

                        Cv2.Circle(image2, (int)(center[0]), (int)(center[1]), 4, new Scalar(255, 0, 0), -1, LineTypes.Link8, 0);
                    }

                }
                pictureBox2.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(image2);


                Cv2.Threshold(image1, image1, 155, 255, ThresholdTypes.BinaryInv);//二值化图片
                pictureBox2.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(image1);
                Cv2.WaitKey(sleepTime);
            }
        }

        private void Stop_Record_Video(object sender, EventArgs e)
        {
            if (capture != null)
            {
                //停止录制
                capture.Stop();
                capture.DisposeCapture();
                capture = null;
            }
        }

        private void Image_Process(object sender, EventArgs e)
        {
            Image_processThread = new Thread(Run_cap);
            if ((Image_processThread.ThreadState & ThreadState.AbortRequested) == 0)
            {

                Image_processThread.Start();
                //button1.Text = "关闭摄像头";
            }
            else
            {
                Image_processThread.Abort();
                //button1.Text = "打开摄像头";
            }
        }
    }
}

3、界面以及效果图

  • 目前简单的界面设计(还未完善)

  • 录制视频界面

  • 简单图像处理界面(后续很多功能未完成,需要继续添加完善)

  • 可以看到录制视频成功了,且能够播放

总结:

虽然是个没多大技术含量的东西,但工程项目就是考一点点积累学习才能进步。

当然想要更深一层的进步,还需要深挖底层原理,这将是我后续学习目标。


版权属于:zfh

本文链接:http://121.36.166.89/index.php/archives/228/



评论已关闭