C# 调用 Emgu.CV 显示RTSP流 + 设置程序运行超时时间

来源:互联网 发布:淘宝上什么祛痘产品好 编辑:程序博客网 时间:2024/05/20 07:15

1.后台代码

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>
原创粉丝点击