Skip to content

Commit

Permalink
Added simple webcam demo
Browse files Browse the repository at this point in the history
  • Loading branch information
NickSwardh committed Dec 7, 2024
1 parent 25feaa6 commit 82b2770
Show file tree
Hide file tree
Showing 7 changed files with 235 additions and 0 deletions.
9 changes: 9 additions & 0 deletions WebcamDemo/App.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Application x:Class="WebcamDemo.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WebcamDemo"
StartupUri="MainWindow.xaml">
<Application.Resources>

</Application.Resources>
</Application>
14 changes: 14 additions & 0 deletions WebcamDemo/App.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System.Configuration;
using System.Data;
using System.Windows;

namespace WebcamDemo
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
}

}
10 changes: 10 additions & 0 deletions WebcamDemo/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System.Windows;

[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]
47 changes: 47 additions & 0 deletions WebcamDemo/MainWindow.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<Window x:Class="WebcamDemo.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:WebcamDemo"
xmlns:skia="clr-namespace:SkiaSharp.Views.WPF;assembly=SkiaSharp.Views.WPF"
mc:Ignorable="d"
Title="Webcam Demo | YoloDotNet" Height="645" Width="1080"
Background="Black" ResizeMode="NoResize" Closing="WindowClosing">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>

<!-- Webcam -->
<skia:SKElement x:Name="WebCamFrame"
Grid.Row="0"
Width="1080"
PaintSurface="UpdateWebcamFrame" />

<!-- Buttons -->
<StackPanel Grid.Row="1"
Orientation="Horizontal"
HorizontalAlignment="Center"
Margin="20">

<Button x:Name="Start"
Content="Start Detection"
Width="120"
Height="30"
Padding="10,0,10,0"
Margin="0,0,10,0"
Click="StartClick" />

<Button x:Name="Stop"
Content="Stop Detection"
Width="120"
Height="30"
Padding="10,0,10,0"
Click="StopClick" />

</StackPanel>

</Grid>
</Window>
125 changes: 125 additions & 0 deletions WebcamDemo/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Util;
using SkiaSharp;
using SkiaSharp.Views.Desktop;
using System.Windows;
using System.Windows.Threading;
using YoloDotNet;
using YoloDotNet.Enums;
using YoloDotNet.Extensions;
using YoloDotNet.Models;
using YoloDotNet.Test.Common;

namespace WebcamDemo
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
#region Fields

private readonly Yolo _yolo = default!;
private SKImage _currentFrame = default!;
private Dispatcher _dispatcher = default!;

private bool _runDetection = false;

private SKRect _rect;

#endregion

#region Constants

const int WEBCAM_WIDTH = 1080;
const int WEBCAM_HEIGHT = 608;
const int FPS = 30;
const string FRAME_FORMAT_EXTENSION = ".png";

#endregion

public MainWindow()
{
InitializeComponent();

// Instantiate yolo
_yolo = new Yolo(new YoloOptions()
{
OnnxModel = SharedConfig.GetTestModelV11(ModelType.ObjectDetection),
ModelType = ModelType.ObjectDetection,
Cuda = true,
PrimeGpu = false
});

_dispatcher = Dispatcher.CurrentDispatcher;

_currentFrame = SKImage.FromBitmap(new SKBitmap(WEBCAM_WIDTH, WEBCAM_HEIGHT));
_rect = new SKRect(0, 0, WEBCAM_WIDTH, bottom: WEBCAM_HEIGHT);

// Start webcam on a separate thread
Task.Run(() => WebcamAsync());
}

private async Task WebcamAsync()
{
// Configure webcam
using var capture = new VideoCapture(0, VideoCapture.API.DShow);
capture.Set(CapProp.FrameCount, FPS);
capture.Set(CapProp.FrameWidth, WEBCAM_WIDTH);
capture.Set(CapProp.FrameHeight, WEBCAM_HEIGHT);

using var mat = new Mat();
using var buffer = new VectorOfByte();

while (true)
{
// Capture current frame from webcam
capture.Read(mat);

// Encode mat to a valid image format and to a buffer
CvInvoke.Imencode(FRAME_FORMAT_EXTENSION, mat, buffer);

// "Rewind" buffer
buffer.Position = 0;

// Read buffer to an SKImage
_currentFrame = SKImage.FromEncodedData(buffer);

// Clean up
buffer.Clear();

if (_runDetection)
{
// Run inference on frame
var results = _yolo.RunObjectDetection(_currentFrame);

// Draw results
_currentFrame = _currentFrame.Draw(results);
}

// Update GUI
await _dispatcher.InvokeAsync(() => WebCamFrame.InvalidateVisual());
}
}

private void UpdateWebcamFrame(object sender, SKPaintSurfaceEventArgs e)
{
using var canvas = e.Surface.Canvas;
canvas.DrawImage(_currentFrame, _rect);
canvas.Flush();
}

private void StartClick(object sender, RoutedEventArgs e)
=> _runDetection = true;

private void StopClick(object sender, RoutedEventArgs e)
=> _runDetection = false;

private void WindowClosing(object sender, System.ComponentModel.CancelEventArgs e)
{
_yolo?.Dispose();
_currentFrame?.Dispose();
}
}
}
23 changes: 23 additions & 0 deletions WebcamDemo/WebcamDemo.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UseWPF>true</UseWPF>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Emgu.CV.Bitmap" Version="4.9.0.5494" />
<PackageReference Include="Emgu.CV.runtime.windows" Version="4.9.0.5494" />
<PackageReference Include="SkiaSharp.Views.WPF" Version="2.88.9" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\test\YoloDotNet.Test.Common\YoloDotNet.Test.Common.csproj" />
<ProjectReference Include="..\YoloDotNet\YoloDotNet.csproj" />
</ItemGroup>

</Project>
7 changes: 7 additions & 0 deletions YoloDotNet.sln
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{5FF17268-4
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{C5DF82EF-FED8-4308-A10F-F34E9B714CCF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebcamDemo", "WebcamDemo\WebcamDemo.csproj", "{96728CA4-2237-42B2-A251-F701AA146508}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -48,6 +50,10 @@ Global
{086DFB71-ACF4-4856-A73E-F20B9DB8775A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{086DFB71-ACF4-4856-A73E-F20B9DB8775A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{086DFB71-ACF4-4856-A73E-F20B9DB8775A}.Release|Any CPU.Build.0 = Release|Any CPU
{96728CA4-2237-42B2-A251-F701AA146508}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{96728CA4-2237-42B2-A251-F701AA146508}.Debug|Any CPU.Build.0 = Debug|Any CPU
{96728CA4-2237-42B2-A251-F701AA146508}.Release|Any CPU.ActiveCfg = Release|Any CPU
{96728CA4-2237-42B2-A251-F701AA146508}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -58,6 +64,7 @@ Global
{8DB429FE-35C1-4879-9FF1-9811AFF808C5} = {5FF17268-47B9-4137-B45E-428D17702834}
{6E2C70F1-F107-4C39-817E-CD21AD460B54} = {5FF17268-47B9-4137-B45E-428D17702834}
{086DFB71-ACF4-4856-A73E-F20B9DB8775A} = {5FF17268-47B9-4137-B45E-428D17702834}
{96728CA4-2237-42B2-A251-F701AA146508} = {C5DF82EF-FED8-4308-A10F-F34E9B714CCF}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C3673E62-2658-4C27-9C6A-A3215F416E05}
Expand Down

0 comments on commit 82b2770

Please sign in to comment.