成果展示
背景
这边有这样的需求,需要对特定的生产片段进行录像,由我系统进行控制。最开始测试了AForge的开源库,但发现x64的情况下,有些类库不能正常运行,才有了现在用的OpenCvSharp3的方式实现。程序的界面参考了网上找的一个AForge的项目界面,感谢!
开发运行环境
win10 x64
.Net Framework 4.6.1
摄像头:海康威视 DS-UVC-U64 Pro
实现方式
首先,nuget OpenCvSharp3
主要代码
class UvcCamera : CameraInterface
{
//标识:是否开始录制,是否暂停
private bool gIsStartRecord = false;
private bool gIsPauseRecord = false;
VideoCapture _gVideoCapture;
private VideoCapture gVideoCapture { get => _gVideoCapture; set => _gVideoCapture = value; }
VideoWriter _gVideoWriter;
private VideoWriter gVideoWriter { get => _gVideoWriter; set => _gVideoWriter = value; }
private Bitmap _CurrentDisplay;
public override Bitmap CurrentDisplay { get => _CurrentDisplay; set => _CurrentDisplay=value; }
/// <summary>
/// 录制线程
/// </summary>
private Thread gRecordThread;
public override bool Connect(int index)
{
try
{
gVideoCapture = new VideoCapture(index);
if (gVideoCapture.IsOpened())
return true;
else
return false;
}
catch
{
return false;
}
}
public override void DisConnect()
{
gVideoWriter?.Dispose();
gVideoCapture?.Release();
}
public override void PauseRecordVideo()
{
if(gIsStartRecord)
{
gIsPauseRecord = true;
gIsStartRecord = false;
}
}
public override void StartRecordVideo()
{
if (!gIsStartRecord)
{
if (gIsPauseRecord)
{
gIsStartRecord = true;
gIsPauseRecord = false;
}
else
{
// 设置输出文件名及格式为MP4
string outputFilePath = System.IO.Path.Combine(System.IO.Directory.GetCurrentDirectory(),"Camera",DateTime.Now.ToString("yyyyMMddHHmmss")+".avi");
double fps = 30.0;
gVideoWriter = new VideoWriter(outputFilePath, FourCC.MP43, fps, new OpenCvSharp.Size(gVideoCapture.FrameWidth, gVideoCapture.FrameHeight), true);
//FourCC.MP43
gIsStartRecord = true;
gRecordThread = new Thread(Record);
gRecordThread.Start();
}
}
}
public override void StopRecordVideo()
{
gIsStartRecord = false;
gIsPauseRecord = false;
}
public override Bitmap TakePhoto()
{
Mat photo = new Mat();
gVideoCapture.Read(photo);
return BitmapConverter.ToBitmap(photo);
}
private void Record()
{
Mat frame = new Mat();
while (true)
{
// 读取当前帧图像
gVideoCapture.Read(frame);
//把当前帧转成Bitmap,供前端页面显示
CurrentDisplay = BitmapConverter.ToBitmap(frame);
// 将图像显示在窗口中
//Cv2.ImShow("Camera", frame);
if (gIsStartRecord)
{
// 将当前帧写入输出文件
gVideoWriter.Write(frame);
}
else if (!gIsPauseRecord) //如果没有开启录制,也不是暂停状态,则退出循环
break;
Thread.Sleep(10);
}
}
}
界面代码
public VideoForm()
{
InitializeComponent();
}
private void btn_Connect_Click(object sender, EventArgs e)
{
bool result=gUvc.Connect(0); //默认连接第一个摄像头
if (result)
ShowMsg("摄像头连接成功!");
else
ShowMsg("摄像头连接失败!");
}
private void ShowMsg(string msg)
{
System.Windows.Forms.MessageBox.Show(msg);
}
private void btn_Close_Click(object sender, EventArgs e)
{
gUvc.DisConnect();
}
private void btn_StartVideo_Click(object sender, EventArgs e)
{
timer_count.Enabled = true;
gUvc.StartRecordVideo();
}
private void btn_PauseVideo_Click(object sender, EventArgs e)
{
timer_count.Enabled = false;
gUvc.PauseRecordVideo();
}
private void btn_EndVideo_Click(object sender, EventArgs e)
{
timer_count.Enabled = false;
tick_num = 0;
gUvc.StopRecordVideo();
}
private void timer1_Tick(object sender, EventArgs e)
{
pictureBox1.Image = gUvc.CurrentDisplay;
}
private void btn_Capture_Click(object sender, EventArgs e)
{
pictureBoxPhoto.Image = gUvc.TakePhoto();
}
private void btn_Save_Click(object sender, EventArgs e)
{
if(pictureBoxPhoto.Image != null)
{
string path = Path.Combine(Directory.GetCurrentDirectory(), "Camera", DateTime.Now.ToString("yyyyMMddHHmmssfff") + ".png");
pictureBoxPhoto.Image.Save(path);
}
}