您的位置:首页 > 编程语言 > C#

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

2017-08-15 20:53 525 查看
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>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐