本文概述
如果你正在使用某个与数据库一起使用的应用程序或与存储数据有关的应用程序, 则可能需要存储某些图片, 一个人或一个产品。用户不一定总是将其图片作为文件保存, 相反, 他可能想立即进行拍照, 最好在正在使用的同一应用程序中进行拍照。使用正确的工具可以在WinForms应用程序中拍照。最简单的方法是通过OpenCVSharp库, 该库将允许你在Picture Box元素内显示来自网络摄像头的视频。
在本文中, 我们将向你介绍如何使用OpenCVSharp库轻松地从WinForms应用程序中的网络摄像机拍摄快照。
1.安装OpenCVSharp
OpenCVSharp是适用于.NET Framework的OpenCV的跨平台包装。 OpenCV(开源计算机视觉库)是一个开源计算机视觉和机器学习软件库。 OpenCV的构建旨在为计算机视觉应用程序提供通用的基础结构, 并加速在商业产品中使用机器感知。作为BSD许可的产品, OpenCV使企业可以轻松地使用和修改代码。包装功能:
- OpenCvSharp尽可能以本机OpenCV C / C ++ API样式为模型。
- OpenCvSharp的许多类都实现IDisposable。无需管理不安全的资源。
- OpenCvSharp不会强制你采用面向对象的编程风格。你还可以调用本机样式的OpenCV函数。
- OpenCvSharp提供了将Mat / IplImage转换为Bitmap(GDI +)或WriteableBitmap(WPF)的功能。
- OpenCvSharp可以在Mono上运行。它可以在Mono支持的任何平台上运行(例如Linux)。
首先使用NuGet软件包管理器在你的项目中安装此库。打开你的Winforms C#项目, 然后在解决方案资源管理器中打开NuGet程序包管理器:
转到浏览选项卡, 然后搜索OpenCVSharp3:
只需单击安装以获取第一个软件包, 即shimat的OpenCVSharp3-AnyCpu。有关此包装的更多信息, 请访问Github上的官方存储库。安装库后, 你将可以轻松地从网络摄像机获取图像。
2.捕获单个快照
对于我们的方法, 我们将做一些非常基本的事情, 我们将允许用户预览从相机收到的图像, 并且他将能够为当前图片拍摄快照。第一步, 你需要设计一个包含3个元素的基本表单:
- 图片框(pictureBox1)
- 启动相机的按钮(button1)
- 拍摄快照的按钮(button2)
该表格将如下所示:
此外, 如果你想要响应式设计, 因此在调整窗口大小时图片框也会随之调整大小, 你可能还需要添加2个面板, 将第一个面板放置在图片框的相同位置, 但图片框应位于其中在底部, 包含两个按钮的面板:
pictureBox1将需要设置Dock属性以与包含它的panel1大小相同。 panel1的锚点需要设置为”上, 下, 左, 右”。 panel2的锚点需要设置为” Bottom, Left, Right”, 面板内部的按钮将将Dock属性设置为侧面, 例如, 将button1 Dock设置为左侧, 将button2 Dock设置为右侧。你可以通过Visual Studio的”属性”框设置提到的属性, 也可以在组件初始化期间使用代码设置属性。这个想法基本上是在用户单击”开始”并拍摄快照时启动相机。
代码逻辑的工作方式如下:包含OpenCvSharp库及其扩展名的名称空间。在表单的类中, 声明5个变量, 而无需初始化以下类型:
- 视频截取
- 垫
- 位图
- 线
- boolean
这些变量将用于存储记录器的实例和一些标志, 以了解记录器是否处于活动状态。创建2个方法, 即CaptureCamera和CaptureCameraCallback。回调过程在另一个线程上运行, 因此你的应用程序在执行期间不会冻结。在”启动/停止”按钮中, 使用标记验证是否应该启动实例或应该停止实例。在捕获快照按钮中, 只需访问图片框的Image属性, 该属性会不断更新并将其存储在位图中, 然后使用你喜欢的格式保存位图, 就是这样:
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Threading;
using System.Windows.Forms;
// Important: include the opencvsharp library in your code
using OpenCvSharp;
using OpenCvSharp.Extensions;
namespace Sandbox
{
public partial class Form1 : Form
{
// Create class-level accesible variables
VideoCapture capture;
Mat frame;
Bitmap image;
private Thread camera;
bool isCameraRunning = false;
// Declare required methods
private void CaptureCamera()
{
camera = new Thread(new ThreadStart(CaptureCameraCallback));
camera.Start();
}
private void CaptureCameraCallback()
{
frame = new Mat();
capture = new VideoCapture(0);
capture.Open(0);
if (capture.IsOpened())
{
while (isCameraRunning)
{
capture.Read(frame);
image = BitmapConverter.ToBitmap(frame);
if (pictureBox1.Image != null)
{
pictureBox1.Image.Dispose();
}
pictureBox1.Image = image;
}
}
}
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
// When the user clicks on the start/stop button, start or release the camera and setup flags
private void button1_Click(object sender, EventArgs e)
{
if (button1.Text.Equals("Start"))
{
CaptureCamera();
button1.Text = "Stop";
isCameraRunning = true;
}
else
{
capture.Release();
button1.Text = "Start";
isCameraRunning = false;
}
}
// When the user clicks on take snapshot, the image that is displayed in the pictureBox will be saved in your computer
private void button2_Click(object sender, EventArgs e)
{
if (isCameraRunning)
{
// Take snapshot of the current image generate by OpenCV in the Picture Box
Bitmap snapshot = new Bitmap(pictureBox1.Image);
// Save in some directory
// in this example, we'll generate a random filename e.g 47059681-95ed-4e95-9b50-320092a3d652.png
// snapshot.Save(@"C:\Users\sdkca\Desktop\mysnapshot.png", ImageFormat.Png);
snapshot.Save(string.Format(@"C:\Users\sdkca\Desktop\{0}.png", Guid.NewGuid()), ImageFormat.Png);
}
else
{
Console.WriteLine("Cannot take picture if the camera isn't capturing image!");
}
}
}
}
在我们的示例中, 我们将生成的屏幕快照存储在计算机的Desktop目录中, 因此你需要将其更改为PC的已知位置。
编码愉快!
评论前必须登录!
注册