EmguCV 3.x – Read and display local video file (C# .NET Visual Studio)

We are going to create a GUI application on Windows desktop using WPF on Visual Studio that reads and displays video file.

Firstly, let’s create a Window and put the following codes into its .xaml file:

< Window x:Class="NaimIbrahim.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:NaimIbrahim"
        mc:Ignorable="d"
        Title="MainWindow" 
        WindowState="Maximized"
        >
    < Grid>
        < Grid.RowDefinitions>
            < RowDefinition Height="*"/>
            < RowDefinition Height="Auto"/>
            < RowDefinition Height="Auto"/>
        < /Grid.RowDefinitions>
        < Grid.ColumnDefinitions>
            < ColumnDefinition Width="*"/>
            < ColumnDefinition Width="0"/>
        < /Grid.ColumnDefinitions>
        < Image x:Name="imageBox" HorizontalAlignment="Center" Grid.Row="0" Grid.Column="0"/>
        < StackPanel Grid.Row="1" Grid.Column="0" Orientation="Horizontal" Margin="0,20,0,20" HorizontalAlignment="Center">
            < Button x:Name="btnOpen" Content="Open" Width="75" Margin="0,0,20,0" Click="btnOpen_Click"/>
            < Button x:Name="btnPause" Content="Pause" Width="75" Click="btnPause_Click"/>
        < /StackPanel>
    < /Grid>
< /Window>

The window will be on maximized screen, and it will have two buttons: Open and Pause.

Next, we will need to install EmguCV library or dependencies into our project solution. Right click on project solution, click ‘Manage NuGet packages for solution’. Search ‘EmguCV’ and install the NuGet package into your project. You can verify that EmguCV DLLs are installed to your project by browsing on the References menu. You can also manually download and install the EmguCV DLLs by following the instruction on EmguCV official website.

In the .cs file of the window, add the following objects into our class:

private Emgu.CV.Capture capture;
System.Windows.Threading.DispatcherTimer dispatcherTimer = new System.Windows.Threading.DispatcherTimer();

The capture object is to capture video from file, and dispatcherTimer object is to continuously read the video at every defined interval.

public MainWindow()
{
	InitializeComponent();
	Loaded += MainWindow_Loaded;

	dispatcherTimer.Tick += dispatcherTimer_Tick;
	dispatcherTimer.Interval = TimeSpan.FromMilliseconds(1000.0 / 60.0);
}

Line #4 is to read some codes once the window is loaded. Line #6 is to re-read our dispatcher function at every tick. Line #7 is to set the interval at 60 FPS (frames per second, a standard value)

void MainWindow_Loaded(object sender, EventArgs e)
{
	btnOpen.IsEnabled = true;
	btnPause.IsEnabled = false;
}

Once window is loaded, we disable the Pause button because no video is being played yet.

private void dispatcherTimer_Tick(object sender, EventArgs e)
{
	if (capture != null)
	{
		Mat mat = capture.QueryFrame();
		if (mat != null)
		{
			Image img = mat.ToImage();
			imageBox.Source = BitmapSourceConvert.ToBitmapSource(img);
		}
	}
}

The above function gets executed at every tick, that is 60 FPS. If a video file is captured, then read its frame and convert the frame to ImageSource by using a class I put at the bottom of this post.

private void btnOpen_Click(object sender, RoutedEventArgs e)
{
	OpenFileDialog openFileDialog = new OpenFileDialog();
	if (openFileDialog.ShowDialog() == true)
	{
		capture = new Emgu.CV.Capture(openFileDialog.FileName.ToString());
		dispatcherTimer.Start();
		btnPause.IsEnabled = true;
	}
}

A user clicks on the Open button and will be asked to choose a video file. Once a video is selected, we start the dispatcher timer and set the Pause button to be enabled.

private void btnPause_Click(object sender, RoutedEventArgs e)
{
	if (dispatcherTimer.IsEnabled)
	{
		dispatcherTimer.Stop();
		btnPause.Content = "Resume";
	} else
	{
		dispatcherTimer.Start();
		btnPause.Content = "Pause";
	}
	
}

And finally, the function invoked when the Pause button is clicked.

private System.Drawing.Bitmap BitmapFromSource(BitmapSource bitmapsource)
{
	System.Drawing.Bitmap bitmap;
	using (MemoryStream outStream = new MemoryStream())
	{
		BitmapEncoder enc = new BmpBitmapEncoder();
		enc.Frames.Add(BitmapFrame.Create(bitmapsource));
		enc.Save(outStream);
		bitmap = new System.Drawing.Bitmap(outStream);
	}
	return bitmap;
}

Leave a Reply