您现在的位置是:网站首页> 编程资料编程资料
ASP.Net Core对USB摄像头进行截图_实用技巧_
2023-05-24
309人已围观
简介 ASP.Net Core对USB摄像头进行截图_实用技巧_
最近想把之前一个USB摄像头拍照的winform程序迁移到.net 5下,首先找了一下,网上有通过DirectShow.NET读取摄像头的例子,Read Barcode from Webcam Viewer with DirectShow.NET。
这个程序依赖着DirectShow.NET的,虽然它是.net framework版本的。试了一下,迁移到.net 5还是无任何障碍的。但我觉得这些原始api使用起来还是不是很方便,便继续找了一下,找到了一个更加简单的类
class UsbCamera:IDisposable { /// Usb camera image size. public Size Size { get; private set; } /// Start. public Action Start { get; private set; } /// Stop. public Action Stop { get; private set; } /// Release resource. public Action Release { get; private set; } /// Get image. /// Immediately after starting, fails because image buffer is not prepared yet. public Func GetBitmap { get; private set; } /// /// Get available USB camera list. /// /// Array of camera name, or if no device found, zero length array. public static string[] FindDevices() { return DirectShow.GetFiltes(DirectShow.DsGuid.CLSID_VideoInputDeviceCategory).ToArray(); } /// /// Get video formats. /// public static VideoFormat[] GetVideoFormat(int cameraIndex) { var filter = DirectShow.CreateFilter(DirectShow.DsGuid.CLSID_VideoInputDeviceCategory, cameraIndex); var pin = DirectShow.FindPin(filter, 0, DirectShow.PIN_DIRECTION.PINDIR_OUTPUT); return GetVideoOutputFormat(pin); } /// /// Create USB Camera. If device do not support the size, default size will applied. /// /// Camera index in FindDevices() result. /// /// Size you want to create. Normally use Size property of VideoFormat in GetVideoFormat() result. /// public UsbCamera(int cameraIndex, Size size) : this(cameraIndex, new VideoFormat() { Size = size }) { } /// /// Create USB Camera. If device do not support the format, default format will applied. /// /// Camera index in FindDevices() result. /// /// Normally use GetVideoFormat() result. /// You can change TimePerFrame value from Caps.MinFrameInterval to Caps.MaxFrameInterval. /// TimePerFrame = 10,000,000 / frame duration. (ex: 333333 in case 30fps). /// You can change Size value in case Caps.MaxOutputSize > Caps.MinOutputSize and OutputGranularityX/Y is not zero. /// Size = any value from Caps.MinOutputSize to Caps.MaxOutputSize step with OutputGranularityX/Y. /// public UsbCamera(int cameraIndex, VideoFormat format) { var camera_list = FindDevices(); if (cameraIndex >= camera_list.Length) throw new ArgumentException("USB camera is not available.", "cameraIndex"); Init(cameraIndex, format); } private void Init(int index, VideoFormat format) { //---------------------------------- // Create Filter Graph //---------------------------------- // +--------------------+ +----------------+ +---------------+ // |Video Capture Source|→| Sample Grabber |→| Null Renderer | // +--------------------+ +----------------+ +---------------+ // ↓GetBitmap() var graph = DirectShow.CreateGraph(); //---------------------------------- // VideoCaptureSource //---------------------------------- var vcap_source = CreateVideoCaptureSource(index, format); graph.AddFilter(vcap_source, "VideoCapture"); //------------------------------ // SampleGrabber //------------------------------ var grabber = CreateSampleGrabber(); graph.AddFilter(grabber, "SampleGrabber"); var i_grabber = (DirectShow.ISampleGrabber)grabber; i_grabber.SetBufferSamples(true); //--------------------------------------------------- // Null Renderer //--------------------------------------------------- var renderer = DirectShow.CoCreateInstance(DirectShow.DsGuid.CLSID_NullRenderer) as DirectShow.IBaseFilter; graph.AddFilter(renderer, "NullRenderer"); //--------------------------------------------------- // Create Filter Graph //--------------------------------------------------- var builder = DirectShow.CoCreateInstance(DirectShow.DsGuid.CLSID_CaptureGraphBuilder2) as DirectShow.ICaptureGraphBuilder2; builder.SetFiltergraph(graph); var pinCategory = DirectShow.DsGuid.PIN_CATEGORY_CAPTURE; var mediaType = DirectShow.DsGuid.MEDIATYPE_Video; builder.RenderStream(ref pinCategory, ref mediaType, vcap_source, grabber, renderer); // SampleGrabber Format. { var mt = new DirectShow.AM_MEDIA_TYPE(); i_grabber.GetConnectedMediaType(mt); var header = (DirectShow.VIDEOINFOHEADER)Marshal.PtrToStructure(mt.pbFormat, typeof(DirectShow.VIDEOINFOHEADER)); var width = header.bmiHeader.biWidth; var height = header.bmiHeader.biHeight; var stride = width * (header.bmiHeader.biBitCount / 8); DirectShow.DeleteMediaType(ref mt); Size = new Size(width, height); // fix screen tearing problem(issure #2) // you can use previous method if you swap the comment line below. // GetBitmap = () => GetBitmapFromSampleGrabberBuffer(i_grabber, width, height, stride); GetBitmap = GetBitmapFromSampleGrabberCallback(i_grabber, width, height, stride); } // Assign Delegates. Start = () => DirectShow.PlayGraph(graph, DirectShow.FILTER_STATE.Running); Stop = () => DirectShow.PlayGraph(graph, DirectShow.FILTER_STATE.Stopped); Release = () => { Stop(); DirectShow.ReleaseInstance(ref i_grabber); DirectShow.ReleaseInstance(ref builder); DirectShow.ReleaseInstance(ref graph); }; // Properties. Properties = new PropertyItems(vcap_source); } public void Dispose() { Release?.Invoke(); } /// Properties user can adjust. public PropertyItems Properties { get; private set; } public class PropertyItems { public PropertyItems(DirectShow.IBaseFilter vcap_source) { // Pan, Tilt, Roll, Zoom, Exposure, Iris, Focus this.CameraControl = Enum.GetValues(typeof(DirectShow.CameraControlProperty)).Cast() .Select(item => { PropertyItems.Property prop = null; try { var cam_ctrl = vcap_source as DirectShow.IAMCameraControl; if (cam_ctrl == null) throw new NotSupportedException("no IAMCameraControl Interface."); // will catched. int min = 0, max = 0, step = 0, def = 0, flags = 0; cam_ctrl.GetRange(item, ref min, ref max, ref step, ref def, ref flags); // COMException if not supports. prop = new Property(min, max, step, def, flags, (flag, value) => cam_ctrl.Set(item, value, (int)flag)); } catch (Exception) { prop = new Property(); } // available = false return new { Key = item, Value = prop }; }).ToDictionary(x => x.Key, x => x.Value); // Brightness, Contrast, Hue, Saturation, Sharpness, Gamma, ColorEnable, WhiteBalance, BacklightCompensation, Gain this.VideoProcAmp = Enum.GetValues(typeof(DirectShow.VideoProcAmpProperty)).Cast() .Select(item => { PropertyItems.Property prop = null; try { var vid_ctrl = vcap_source as DirectShow.IAMVideoProcAmp; if (vid_ctrl == null) throw new NotSupportedException("no IAMVideoProcAmp Interface."); // will catched. int min = 0, max = 0, step = 0, def = 0, flags = 0; vid_ctrl.GetRange(item, ref min, ref max, ref step, ref def, ref flags); // COMException if not supports. prop = new Property(min, max, step, def, flags, (flag, value) => vid_ctrl.Set(item, value, (int)flag)); } catch (Exception) { prop = new Property(); } // available = false return new { Key = item, Value = prop }; }).ToDictionary(x => x.Key, x => x.Value); } /// Camera Control properties. private Dictionary CameraControl; /// Video Processing Amplifier properties. private Dictionary VideoProcAmp; /// Get CameraControl Property. Check Available before use. public Property this[DirectShow.CameraControlProperty item] { get { return CameraControl[item]; } } /// Get VideoProcAmp Property. Check Available before use. public Property this[DirectShow.VideoProcAmpProperty item] { get { return VideoProcAmp[item]; } } public class Property { public int Min { get; private set; } public int Max { get; private set; } public int Step { get; private set; } public int Default { get; private set; } public DirectShow.CameraControlFlags Flags { get; private set; } public Action SetValue { get; private set; } public bool Available { get; private set; } public bool CanAuto { get; private set; } public Property() { this.SetValue = (flag, value) => { }; this.Available = false; } public Property(int min, int max, int step, int @default, int flags, Action set) { this.Min = min; this.Max = max; this.Step = step; this.Default = @default; this.Flags = (DirectShow.CameraControlFlags)flags; this.CanAuto = (Flags & DirectShow.CameraControlFlags.Auto) == DirectShow.CameraControlFlags.Auto; this.SetValue = set; this.Available = true; } public override string ToString() { return string.Format("Available={0}, Min={1}, Max={2}, Step={3}, Default={4}, Flags={5}", Available, Min, Max, Step, Default, Flags); } } } private class SampleGrabberCallback : DirectShow.ISampleGrabberCB { private byte[] Buffer; private object BufferLock = new object(); public Bitmap GetBitmap(int width, int height, int stride) { var result = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb); if (Buffer == null) return result; var bmp_data = result.LockBits(new Rectangle(Point.Empty, result.Size), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb); lock (BufferLock) { // copy from last row. for (int y = 0; y < height; y++) { var src_idx = Buffer.Length - (stride * (y + 1)); var dst = IntPtr.Add(bmp_data.Scan0, stride * y); Marshal.Copy(Buffer, src_idx, dst, stride); } } result.UnlockBits(bmp_data); return result; } // called when each sample completed. // The data processing thre
相关内容
- .Net中Task Parallel Library的基本用法_基础应用_
- 通用 HTTP 签名组件的另类实现方式_实用技巧_
- ASP.NET MVC遍历验证ModelState的错误信息_实用技巧_
- 如何使用ASP.NET Core 配置文件_实用技巧_
- .NETCore基于RabbitMQ实现延时队列的两方法_实用技巧_
- .Net反向代理组件Yarp用法详解_实用技巧_
- .NET使用YARP通过编码方式配置域名转发实现反向代理_实用技巧_
- .NET使用YARP根据域名转发实现反向代理_实用技巧_
- 微信小程序实现一键回到顶部功能_javascript技巧_
- TypeScript保姆级基础教程_js其它_
点击排行
本栏推荐
