需求
C# winform中调用摄像头 抓到图片转成 Base64
//得到机器所有接入的摄像设备
FilterInfoCollection videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
if (videoDevices.Count == 0)
{
WriteLog("没有找到摄像头");
}
//获取摄像头
VideoCaptureDevice videoDevice = new VideoCaptureDevice(videoDevices[0].MonikerString);
//摄像头分辨率 和 设备的摄像头分辨率数组
VideoCapabilities[] videoCapabilities = videoDevice.VideoCapabilities;
if (videoDevice != null)//如果摄像头不为空
{
if ((videoCapabilities != null) && (videoCapabilities.Length != 0))
{
//摄像头分辨率
videoDevice.VideoResolution = videoCapabilities[0];
}
}
因为是C# 后台代码,没有VideoSourcePlayer 控件。
需要直接从摄像头,里面生成图片,转成 Base64。
引用chatgpt部分指引作答:
要在C# WinForms中调用摄像头并将捕获的图像转换为Base64编码,您可以使用AForge.Video.DirectShow库来实现。以下是一个示例代码,展示了如何完成这个过程:
using AForge.Video;
using AForge.Video.DirectShow;
using System;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
namespace WebcamCapture
{
public partial class Form1 : Form
{
private FilterInfoCollection videoDevices;
private VideoCaptureDevice videoDevice;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
if (videoDevices.Count == 0)
{
MessageBox.Show("没有找到摄像头");
return;
}
videoDevice = new VideoCaptureDevice(videoDevices[0].MonikerString);
videoDevice.NewFrame += VideoDevice_NewFrame;
videoDevice.Start();
}
private void VideoDevice_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
// 捕获新的图像帧
Bitmap frame = (Bitmap)eventArgs.Frame.Clone();
// 将图像转换为Base64编码
string base64Image = ConvertToBase64(frame);
// 在这里使用base64Image进行进一步的处理,例如保存到文件或发送到远程服务器
}
private string ConvertToBase64(Bitmap image)
{
using (MemoryStream ms = new MemoryStream())
{
image.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
byte[] imageBytes = ms.ToArray();
return Convert.ToBase64String(imageBytes);
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (videoDevice != null && videoDevice.IsRunning)
videoDevice.SignalToStop();
}
}
}
在上述示例代码中,我们使用AForge.Video.DirectShow库来调用摄像头。在窗体加载时,我们获取第一个摄像设备并启动视频捕获。每当摄像头捕获到新的帧时,我们会触发VideoDevice_NewFrame事件,将捕获的图像转换为Base64编码。
请确保在项目中引用AForge.Video和AForge.Video.DirectShow库,并添加相应的命名空间引用。
来自NewBing和LP的编写:
为了满足你的需求,要用AForge.NET库。首先要安装AForge.NET Framework库,你可以通过NuGet Package Manager来安装。以下是一个简单的例子,展示了如何捕捉摄像头的图像,并将其转换为Base64字符串:
先要添加以下的命名空间:
using AForge.Video;
using AForge.Video.DirectShow;
using System.IO;
using System.Drawing;
using System;
using System.Drawing.Imaging;
以下是一个示例代码:
private void CaptureImage()
{
FilterInfoCollection videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
if (videoDevices.Count == 0)
{
Console.WriteLine("没有找到摄像头");
return;
}
VideoCaptureDevice videoDevice = new VideoCaptureDevice(videoDevices[0].MonikerString);
VideoCapabilities[] videoCapabilities = videoDevice.VideoCapabilities;
if (videoDevice != null)
{
if ((videoCapabilities != null) && (videoCapabilities.Length != 0))
{
videoDevice.VideoResolution = videoCapabilities[0];
}
videoDevice.NewFrame += new NewFrameEventHandler(videoDevice_NewFrame);
videoDevice.Start();
}
}
void videoDevice_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
// process new video frame and create bitmap from it
Bitmap bitmap = eventArgs.Frame.Clone() as Bitmap;
// process the bitmap to Base64 string
string base64String;
using (MemoryStream memory = new MemoryStream())
{
bitmap.Save(memory, ImageFormat.Jpeg);
byte[] byteImage = memory.ToArray();
base64String = Convert.ToBase64String(byteImage);
}
Console.WriteLine(base64String);
// you should stop capturing video after getting one frame
VideoCaptureDevice videoDevice = sender as VideoCaptureDevice;
if (videoDevice != null && videoDevice.IsRunning)
{
videoDevice.SignalToStop();
videoDevice.WaitForStop();
}
}
例子中定义了一个名为CaptureImage的方法来初始化并启动摄像头。然后定义了一个事件处理程序videoDevice_NewFrame,当摄像头捕获到新的帧时,它将被调用。在这个事件处理程序中,创建了一个位图对象,并将其转换为Base64字符串。
注意,此代码会在捕获第一帧后停止摄像头。如果你想要连续捕获,要调整代码以满足你的需求。
现在我们是没有这个控件的,所以我们要先导包,点击我们的工具选项卡,选择NuGet包管理器,管理解决方案的NuGet程序包,安装一下的包:
然后我们就能看到videoSourcePlayer控件,把它绘制在窗体上就好了。
该回答通过自己思路及引用到GPTᴼᴾᴱᴺᴬᴵ搜索,得到内容具体如下:
可以使用C#中的DirectShow.NET库来调用摄像头,并使用System.Drawing.Bitmap来处理图像数据,最后将图像数据转换成Base64。
以下是一个可能的实现代码:
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using DirectShowLib;
namespace CameraDemo
{
public class CameraManager
{
private IFilterGraph2 graphBuilder;
private ICaptureGraphBuilder2 captureGraphBuilder;
private IBaseFilter captureFilter;
private IAMVideoControl videoControl;
private IAMStreamConfig streamConfig;
private int width = 640;
private int height = 480;
private int fps = 30;
public bool Initialize()
{
try
{
// 创建 Filter Graph Manager
graphBuilder = (IFilterGraph2)new FilterGraph();
captureGraphBuilder = (ICaptureGraphBuilder2)new CaptureGraphBuilder2();
// 创建摄像头过滤器
captureFilter = CreateCaptureFilter();
// 添加过滤器到 Filter Graph
graphBuilder.AddFilter(captureFilter, "Capture Filter");
// 创建 Sample Grabber Filter
var sampleGrabber = (ISampleGrabber)new SampleGrabber();
var baseGrabFlt = (IBaseFilter)sampleGrabber;
graphBuilder.AddFilter(baseGrabFlt, "Sample Grabber");
// 设置 Sample Grabber 的回调函数
var mediaEventEx = (IMediaEventEx)graphBuilder;
var mediaControl = (IMediaControl)graphBuilder;
var mediaEvent = (IMediaEvent)graphBuilder;
var callback = new SampleGrabberCallback();
sampleGrabber.SetCallback(callback, 1);
// 连接摄像头和 Sample Grabber
var sourceOutPin = GetOutputPin(captureFilter, 0);
var destInPin = GetInputPin(baseGrabFlt, 0);
graphBuilder.Connect(sourceOutPin, destInPin);
// 设置视频格式
streamConfig = (IAMStreamConfig)sourceOutPin;
AMMediaType mediaType = new AMMediaType();
streamConfig.GetFormat(out mediaType);
var videoInfo = (VideoInfoHeader)Marshal.PtrToStructure(mediaType.formatPtr, typeof(VideoInfoHeader));
videoInfo.BmiHeader.Width = width;
videoInfo.BmiHeader.Height = height;
videoInfo.AvgTimePerFrame = (long)(10000000.0 / fps);
Marshal.StructureToPtr(videoInfo, mediaType.formatPtr, false);
streamConfig.SetFormat(mediaType);
// 运行 Filter Graph
mediaControl.Run();
return true;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return false;
}
}
public void ShutDown()
{
if (graphBuilder != null)
{
graphBuilder.Stop();
Marshal.ReleaseComObject(graphBuilder);
graphBuilder = null;
}
}
public Bitmap Capture()
{
var sampleGrabber = (ISampleGrabber)graphBuilder.FilterCollection[1];
var mediaEventEx = (IMediaEventEx)graphBuilder;
var mediaControl = (IMediaControl)graphBuilder;
// 设置 Sample Grabber 的参数
var mediaType = new AMMediaType();
sampleGrabber.GetConnectedMediaType(mediaType);
var videoInfo = (VideoInfoHeader)Marshal.PtrToStructure(mediaType.formatPtr, typeof(VideoInfoHeader));
var bufferSize = videoInfo.BmiHeader.ImageSize;
var buffer = Marshal.AllocHGlobal(bufferSize);
sampleGrabber.SetBufferSamples(false);
sampleGrabber.SetOneShot(false);
sampleGrabber.SetCallback(null, 1);
// 抓取图像
mediaControl.Pause();
mediaControl.Run();
mediaEventEx.WaitForCompletion(-1, out _);
sampleGrabber.GetCurrentBuffer(ref bufferSize, buffer);
mediaControl.Stop();
// 将图像数据转换为 Bitmap
var bitmap = new Bitmap(width, height, PixelFormat.Format24bppRgb);
var bitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
var data = bitmapData.Scan0;
var src = buffer;
for (int y = 0; y < height; y++)
{
var dest = (IntPtr)(data.ToInt64() + y * bitmapData.Stride);
NativeMethods.CopyMemory(dest, src, width * 3);
src = (IntPtr)(src.ToInt64() + videoInfo.BmiHeader.Pitch);
}
bitmap.UnlockBits(bitmapData);
Marshal.FreeHGlobal(buffer);
mediaType.Dispose();
return bitmap;
}
public string CaptureAsBase64()
{
var bitmap = Capture();
var stream = new MemoryStream();
bitmap.Save(stream, ImageFormat.Png);
var bytes = stream.ToArray();
var base64 = Convert.ToBase64String(bytes);
stream.Dispose();
bitmap.Dispose();
return base64;
}
private IBaseFilter CreateCaptureFilter()
{
var devices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
if (devices.Count == 0)
throw new Exception("No video devices found");
var moniker = devices[0].MonikerString;
var filterGraph = new FilterGraph() as IFilterGraph2;
var captureFilter = filterGraph.AddSourceFilter(moniker, "Video Capture");
return captureFilter;
}
private IPin GetOutputPin(IBaseFilter filter, int pinIndex)
{
var pinEnum = (IEnumPins)filter.EnumPins();
var pins = new IPin[1];
pinEnum.Next(pins.Length, pins, out _);
return pins[pinIndex];
}
private IPin GetInputPin(IBaseFilter filter, int pinIndex)
{
var pinEnum = (IEnumPins)filter.EnumPins();
var pins = new IPin[1];
pinEnum.Next(pins.Length, pins, out _);
IPin connectedPin = null;
var pinDir = new PinDirection();
pins[pinIndex].QueryDirection(out pinDir);
if (pinDir == PinDirection.Output)
{
var pinInfo = new PinInfo();
pins[pinIndex].QueryPinInfo(out pinInfo);
var pinConnectedTo = pinInfo.pFilter.FindPin(pinInfo.achName);
connectedPin = GetInputPin(pinConnectedTo, 0);
Marshal.ReleaseComObject(pinConnectedTo);
}
else
{
pins[pinIndex].ConnectedTo(out connectedPin);
}
return connectedPin;
}
private class SampleGrabberCallback : ISampleGrabberCB
{
public int SampleCB(double sampleTime, IMediaSample pSample)
{
return 0;
}
public int BufferCB(double sampleTime, IntPtr pBuffer, int bufferLen)
{
return 0;
}
}
}
internal static class NativeMethods
{
[DllImport("Kernel32.dll", EntryPoint = "RtlMoveMemory")]
public static extern void CopyMemory(IntPtr dest, IntPtr src, int length);
}
}
在使用摄像头之前,需要在项目中添加对DirectShow.NET库的引用。可以通过NuGet包管理器来添加DirectShowLib库的引用。
如果以上回答对您有所帮助,点击一下采纳该答案~谢谢
videoDevice.NewFrame += new NewFrameEventHandler(VideoNewFrame);
private void VideoNewFrame(object sender, NewFrameEventArgs eventArgs)
{
var bitmap = (Bitmap)eventArgs.Frame.Clone();
var base64String = ImageToBase64(bitmap);
}
private string ImageToBase64(Image image)
{
using (MemoryStream memoryStream = new MemoryStream())
{
image.Save(memoryStream, image.RawFormat);
byte[] imageBytes = memoryStream.ToArray();
string base64String = Convert.ToBase64String(imageBytes);
return base64String;
}
}