我正在使用这个类成功地录制网络摄像头视频.但这段代码的问题是,我无法将实时视频显示到PictureBox中

using System;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
using OpenCvSharp;
using OpenCvSharp.Extensions;
using Size = OpenCvSharp.Size;

namespace Video_capture_23_08_2022
{
    public class Recorder : IDisposable
    {
        private readonly VideoCaptureAPIs _videoCaptureApi = VideoCaptureAPIs.DSHOW;
        private readonly ManualResetEventSlim _threadStopEvent = new ManualResetEventSlim(false);
        private readonly VideoCapture _videoCapture;
        private VideoWriter _videoWriter;

        private Mat _capturedFrame = new Mat();
        private Thread _captureThread;
        private Thread _writerThread;
        //private OutputArray frame;

        private bool IsVideoCaptureValid => _videoCapture is not null && _videoCapture.IsOpened();

        public Recorder(int deviceIndex, int frameWidth, int frameHeight, double fps, PictureBox pictureBox)
        {
            _videoCapture = VideoCapture.FromCamera(deviceIndex, _videoCaptureApi);
            _videoCapture.Open(deviceIndex, _videoCaptureApi);

            _videoCapture.FrameWidth = frameWidth;
            _videoCapture.FrameHeight = frameHeight;
            _videoCapture.Fps = fps;

             // Custom Function to show the webcam view into picturebox  
            _videoCapture.Read(_capturedFrame);
            if (!(_capturedFrame.Empty()))
            { 
            pictureBox.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(_capturedFrame);

            }

        }

        /// <inheritdoc />
        public void Dispose()
        {
            GC.SuppressFinalize(this);
            Dispose(true);
        }

        ~Recorder()
        {
            Dispose(false);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                StopRecording();

                _videoCapture?.Release();
                _videoCapture?.Dispose();
            }
        }

        public void StartRecording(string path)
        {
            if (_writerThread is not null)
                return;

            if (!IsVideoCaptureValid)
                ThrowHelper.ThrowVideoCaptureNotReadyException();

            _videoWriter = new VideoWriter(path, FourCC.XVID, _videoCapture.Fps, new Size(_videoCapture.FrameWidth, _videoCapture.FrameHeight));

            _threadStopEvent.Reset();

            _captureThread = new Thread(CaptureFrameLoop);
            _captureThread.Start();

            _writerThread = new Thread(AddCameraFrameToRecordingThread);
            _writerThread.Start();
        }

        public void StopRecording()
        {
            _threadStopEvent.Set();

            _writerThread?.Join();
            _writerThread = null;

            _captureThread?.Join();
            _captureThread = null;

            _threadStopEvent.Reset();

            _videoWriter?.Release();
            _videoWriter?.Dispose();
            _videoWriter = null;
        }

        private void CaptureFrameLoop()
        {
            while (!_threadStopEvent.Wait(0))
            {
                _videoCapture.Read(_capturedFrame);
            }
        }

        private void AddCameraFrameToRecordingThread()
        {
            var waitTimeBetweenFrames = 1_000 / _videoCapture.Fps;
            var lastWrite = DateTime.Now;

            while (!_threadStopEvent.Wait(0))
            {
                if (DateTime.Now.Subtract(lastWrite).TotalMilliseconds < waitTimeBetweenFrames)
                    continue;
                lastWrite = DateTime.Now;
                _videoWriter.Write(_capturedFrame);
            }
        }

        public Bitmap GetFrameBitmap()
        {
            if (!IsVideoCaptureValid)
                ThrowHelper.ThrowVideoCaptureNotReadyException();

            using (Mat frame = new Mat())
                return !_videoCapture.Read(frame) ? null : frame.ToBitmap();
        }
    }
}

但我想对它进行一些修改,以将网络摄像头视图显示到PictureBox中,但这个自定义部分

 // Custom Function to show the webcam view into picturebox  
 _videoCapture.Read(_capturedFrame);
 if (!(_capturedFrame.Empty()))
  { 
   pictureBox.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(_capturedFrame); 
  }

只显示静止图像,而不是实况视频. 请帮我弄清楚这个问题.

推荐答案

您的实现中缺少的部分是捕获网络摄像头图像并在构造函数中以pictureBox的速度重复显示它,而不是在CaptureFrameLoop()中重复显示一次.因此,您需要将此街区移至CaptureFrameLoop()号.

_videoCapture.Read(_capturedFrame);
if (!(_capturedFrame.Empty()))
{ 
   pictureBox.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(_capturedFrame); 
}

此外,您应该使用Control.Invoke从非UI线程修改PictureBox的图像.

private void CaptureFrameLoop()
{
   while (!_threadStopEvent.Wait(0))
   {
        _videoCapture.Read(_capturedFrame);
        if (!(_capturedFrame.Empty()))
        { 
            pictureBox.Invoke(new Action(() => pictureBox.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(_capturedFrame))); 
        }
   }
}

Csharp相关问答推荐

如何使用Automapper映射两个嵌套列表

使用C#中的Shape API从Azure目录获取所有用户

如何在Reflection. Emit中使用具有运行时定义的类型参数的泛型类型

AsNoTrackingWithIdentitySolutions()似乎不起作用?

返回TyedResults.BadRequest<;字符串>;时问题详细信息不起作用

只有第一个LINQ.Count()语句有效

在C#中,有没有一种方法可以集中定义跨多个方法使用的XML参数描述符?

MS Graph v5.42.0:在寻呼消息时更改页面大小

Cosmos SDK和Newtonsoft对静态只读记录的可能Mutations

异步实体框架核心查询引发InvalidOperation异常

如何在NET 8最小API中自动记录TypedResults.Stream响应

C#中Java算法的类似功能

MSTest--将消息直接写入StdOut和使用TestContext有什么不同?

如何在不复制或使用输出的情况下定义项目依赖

如何使用用于VS代码的.NET Maui扩展在我的iOS/Android设备或模拟器上进行调试?

如何使用Npgsql从SELECT获得所有查询结果

C# Winforms:从对象树到TreeView的递归转换重复条目

工厂类是如何在.NET 8中注册的?

使用C#12中的主构造函数进行空判断

C#-如何将int引用获取到byte[]