C# 调用 Emgu.CV 显示RTSP流 + 设置程序运行超时时间
2017-08-15 20:53
525 查看
1.后台代码
2.xaml界面
using Caliburn.Micro; using Emgu.CV; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Media; using System.Windows.Media.Imaging; namespace WpfMyCapture { public class MainViewModel:PropertyChangedBase { object lockObj = new object(); private int ImgNum = 6; string url1 = "rtsp://admin:admin123@192.168.1.93:554/Streaming/Channels/102?transportmode=unicast&profile=Profile_1"; public MainViewModel() { CvInvoke.UseOpenCL = false; } public void MainLoad() { InitSource(); } public void Start_Button_Click(object sender, RoutedEventArgs e) { foreach (var img in ImageD3DList) { if (img.Capt != null) { img.Capt.Start(); } } } public void capture_ImageGrabbed(object sender, EventArgs e) { try { ImgInfo img = ImageD3DList.ToList().Find(p => p.Ptr == (sender as Capture).Ptr); if (img == null) return; Mat frame = new Mat(); lock (lockObj) { if (img.Capt != null) { if (!img.Capt.Retrieve(frame)) { frame.Dispose(); return; } if (frame.IsEmpty) return; //Emgu.CV.UI.ImageBox //显示图片 可以使用Emgu CV 提供的 ImageBox显示视频, 也可以转成 BitmapSource显示。 System.Windows.Application.Current.Dispatcher.Invoke(new System.Action(() => { BitmapSource source = BitmapSourceConvert.ToBitmapSource(frame); frame.Dispose(); img.ImgSource = source; })); GC.Collect(); } } } catch (Exception ex) { } } public void Stop_Btn_Click(object sender, System.Windows.RoutedEventArgs e) { foreach (var img in ImageD3DList) { if (img.Capt != null) { img.Capt.Dispose(); } } } public void Pause_Btn_Click(object sender, System.Windows.RoutedEventArgs e) { Task.Factory.StartNew(() => { foreach (var img in ImageD3DList) { img.Capt.Stop(); } }); } private void InitSource() { ImageD3DList = new ObservableCollection<ImgInfo>(); for (int i = 0; i < ImgNum; i++) { ImgInfo img = new ImgInfo(); FuncTimeout time = new FuncTimeout(CreatCapture, 500); var result = time.doAction(new object[] { img, i }); ImageD3DList.Add(img); } } private object CreatCapture(object[] data) { ImgInfo img = data[0] as ImgInfo; int i = int.Parse(data[1].ToString()); img.Index = i; img.Width = 0; img.Height = 0; img.RtspUri = url1;// UriChannelReplace(url1); img.Capt = new Capture(img.RtspUri); img.Ptr = img.Capt.Ptr; img.Capt.ImageGrabbed += capture_ImageGrabbed; return 1; } private ObservableCollection<ImgInfo> imageD3DList = new ObservableCollection<ImgInfo>(); public ObservableCollection<ImgInfo> ImageD3DList { get { return imageD3DList; } set { imageD3DList = value; NotifyOfPropertyChange(() => ImageD3DList); } } } public static class BitmapSourceConvert { /// <summary> /// Delete a GDI object /// </summary> /// <param name="o">The poniter to the GDI object to be deleted</param> /// <returns></returns> [System.Runtime.InteropServices.DllImport("gdi32.dll")] public static extern bool DeleteObject(IntPtr hObject); /// <summary> /// Convert an IImage to a WPF BitmapSource. The result can be used in the Set Property of Image.Source /// </summary> /// <param name="image">The Emgu CV Image</param> /// <returns>The equivalent BitmapSource</returns> public static BitmapSource ToBitmapSource(IImage image) { using (System.Drawing.Bitmap source = image.Bitmap) { IntPtr ptr = source.GetHbitmap(); //obtain the Hbitmap BitmapSource bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap( ptr, IntPtr.Zero, Int32Rect.Empty, System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions()); if (!DeleteObject(ptr)) { throw new System.ComponentModel.Win32Exception(); } return bs; } } } /// <summary> /// 控制函数执行时间,超时返回null不继续执行 /// 调用方法 /// FuncTimeout.EventNeedRun action = delegate(object[] param) /// { /// //调用自定义函数 /// return Test(param[0].ToString(), param[1].ToString(), (DateTime)param[2]); /// }; /// FuncTimeout ft = new FuncTimeout(action, 2000); /// var result = ft.doAction("1", "2", DateTime.Now); /// </summary> public class FuncTimeout { /// <summary> /// 信号量 /// </summary> public ManualResetEvent manu = new ManualResetEvent(false); /// <summary> /// 是否接受到信号 /// </summary> public bool isGetSignal; /// <summary> /// 设置超时时间 /// </summary> public int timeout; /// <summary> /// 定义一个委托 ,输入参数可选,输出object /// </summary> public delegate object EventNeedRun(params object[] param); /// <summary> /// 要调用的方法的一个委托 /// </summary> private EventNeedRun FunctionNeedRun; /// <summary> /// 构造函数,传入超时的时间以及运行的方法 /// </summary> /// <param name="_action">运行的方法 </param> /// <param name="_timeout">超时的时间</param> public FuncTimeout(EventNeedRun _action, int _timeout) { FunctionNeedRun = _action; timeout = _timeout; } /// <summary> /// 回调函数 /// </summary> /// <param name="ar"></param> public void MyAsyncCallback(IAsyncResult ar) { //isGetSignal为false,表示异步方法其实已经超出设置的时间,此时不再需要执行回调方法。 if (isGetSignal == false) { //放弃执行回调函数; Thread.CurrentThread.Abort(); } } /// <summary> /// 调用函数 /// </summary> /// <param name="input">可选个数的输入参数</param> /// <returns></returns> public object doAction(params object[] input) { EventNeedRun WhatTodo = CombineActionAndManuset; //通过BeginInvoke方法,在线程池上异步的执行方法。 var r = WhatTodo.BeginInvoke(input, MyAsyncCallback, null); //设置阻塞,如果上述的BeginInvoke方法在timeout之前运行完毕,则manu会收到信号。此时isGetSignal为true。 //如果timeout时间内,还未收到信号,即异步方法还未运行完毕,则isGetSignal为false。 isGetSignal = manu.WaitOne(timeout); if (isGetSignal == true) { return WhatTodo.EndInvoke(r); } else { return null; } } /// <summary> /// 把要传进来的方法,和 manu.Set()的方法合并到一个方法体。 /// action方法运行完毕后,设置信号量,以取消阻塞。 /// </summary> /// <param name="input">输入参数</param> /// <returns></returns> public object CombineActionAndManuset(params object[] input) { var output = FunctionNeedRun(input); manu.Set(); return output; } } public class ImgInfo : PropertyChangedBase { private string rtspUri; public string RtspUri { get { return rtspUri; } set { rtspUri = value; NotifyOfPropertyChange(() => RtspUri); } } private int index; public int Index { get { return index; } set { index = value; NotifyOfPropertyChange(() => Index); } } private IntPtr ptr; public IntPtr Ptr { get { return ptr; } set { ptr = value; NotifyOfPropertyChange(() => Ptr); } } private int width; public int Width { get { return width; } set { width = value; NotifyOfPropertyChange(() => Width); } } private int height; public int Height { get { return height; } set { height = value; NotifyOfPropertyChange(() => Height); } } private Capture capt; public Capture Capt { get { return capt; } set { capt = value; NotifyOfPropertyChange(() => Capt); } } private ImageSource imgSource; public ImageSource ImgSource { get { return imgSource; } set { imgSource = value; NotifyOfPropertyChange(() => ImgSource); } } } }
2.xaml界面
<Window x:Class="WpfMyCapture.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:cal="http://www.caliburnproject.org" xmlns:enu="clr-namespace:Emgu.CV.UI;assembly=Emgu.CV.UI" xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms" xmlns:wfi="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration" Title="MainWindow" cal:Message.Attach="[Event Loaded]=[Action MainLoad()]" Width="525" Height="350"> <Grid x:Name="myGrid"> <Grid.RowDefinitions> <RowDefinition Height="auto" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <StackPanel Grid.Row="0" Orientation="Horizontal"> <Button cal:Message.Attach="[Event Click]=[Action Start_Button_Click($view,$eventArgs)]" Content="播放" /> <Button cal:Message.Attach="[Event Click]=[Action Pause_Btn_Click($view,$eventArgs)]" Content="暂停" /> <Button cal:Message.Attach="[Event Click]=[Action Stop_Btn_Click($view,$eventArgs)]" Content="停止" /> </StackPanel> <ItemsControl ItemsSource="{Binding ImageD3DList}" Grid.Row="1"> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <UniformGrid Columns="3" /> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> <ItemsControl.ItemTemplate> <DataTemplate> <DockPanel LastChildFill="True"> <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" DockPanel.Dock="Top" Text="{Binding ImgTest}" /> <Border BorderBrush="Gray" BorderThickness="1" ClipToBounds="True"> <!--<wfi:WindowsFormsHost> <enu:ImageBox FunctionalMode="Minimum" SizeMode="StretchImage" /> </wfi:WindowsFormsHost>--> <Image Source="{Binding ImgSource}" Stretch="Fill"/> </Border> </DockPanel> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> </Grid> </Window>
相关文章推荐
- C#记录程序运行时间记录显示
- C#记录程序运行时间记录显示
- C#源码刷新网页 最小化托盘http get和post请求配置保存版权时间限制定时调用 单实例运行,如果已经运行则激活窗口到最前显示
- 调用系统时间与获得程序运行时间方法
- Axis2 客户端调用 设置超时时间
- c++ time.h显示程序运行时间
- C#测量程序运行时间及cpu使用时间实例方法
- C#.NET Form设置/取消开机自动运行,判断程序是否已经设置成开机自动启动
- c#计算程序的运行时间
- Android中设置只有程序第一次运行才显示的界面实现思路
- C# 设置程序开机自动运行/设置&获取程序的安装路径
- c#开发-计算一段程序运行的时间
- c# 仿照计划任务(定时提示、定时运行程序、定时打开url(前台/后台))/每天/每周/每月/一次 多时间段
- C#实现测量程序运行时间及cpu使用时间(转载)
- Axis2 客户端调用 设置超时时间
- C#测试程序运行时间
- C#2.0中获取程序的运行时间
- c#单一程序运行续-最小化后显示
- Apache HttpClient调用服务没有设置超时时间引起的血崩
- 【C#】对异步请求处理程序IHttpAsyncHandler的理解和分享一个易用性封装 【手记】走近科学之为什么明明实现了IEnumerable<T>的类型却不能调用LINQ扩展方法 【手记】手机网页弹出层后屏蔽底层的滑动响应 【手记】ASP.NET提示“未能创建类型”处理 【Web】一个非常简单的移动web消息框 【手记】解决EXCEL跑SQL遇“查询无法运行或数据库表无法打开...”