mirror of
https://github.com/cosyneco/MediaPipe.NET.git
synced 2025-05-20 08:55:54 +08:00

* Add paths for Linux in BlazePose example * Add BlazePose example to VSCode debug launchers * Use `pose_landmark` instead of `pose_tracking_*` * Pluralize `SidePacket` The correct way to call it is actually `SidePackets`, as it is internally a `map<string, Packet>`. * Little XML doc * Consolidate `StartRun` method parameters * Add `SidePackets` property to `Calculator` * Add side packet arguments to `BlazePose` * Use the `pose_tracking` graph Let's try specifying side packets there instead. * Use asynchronous SeeShark frame input Looks like that doesn't fix the FPS... * Remove unnecessary `unsafe` * Better error handling in example program * Uncomment additional SidePacket * Implement new Packet API * Rename `Packet` namespace to `OldPacket` * Rename `NewPacket` namespace to `Packet` * Actually, `Packets` is better... * Delete old Packet API * Replace Calculators with Solutions Solutions are written in a way to imitate the MediaPipe Python API as much as possible. * Remove Old Packet API tests * Fix remaining tests * No more `SignalAbort` :0 * Revert "No more `SignalAbort` :0" This reverts commit dd63b53fb53590560188d652346130ff31c74c62. * Create `FaceMeshCpuSolution` * Add interface * Temporarily remove non-compiling example projects * This solution produces segfaults... * Create `PacketType` enum Store packet outputs instead of packets in solution No segfault now :D * Use an `IDictionary` for outputs * Create a `Hands` example * Hand tracking is 10 times slower... * No threading T-T * Add `FaceMeshGpu` solution * Avoid `free(): invalid pointer` error * Implement `HandsGpu` solution It works perfectly fine :D * Start reimplementing Pose example * Pose landmarks CPU (it's very slow) * Just correcting some things in the examples * Implement `PoseGpuSolution` (it's decently fast) * `OsuFrameworkVisualTests` example works too Though we need a way to make solutions multithreaded. * Attempt at thread-safe `Solution` implementation * There is no thread-safe solution. :') This reverts commit 6e9ccca3deebf3ca74ed25c41e619c07c5febd94. * Fix duplicate project in solution How the fuck did that happen???
118 lines
4.0 KiB
C#
118 lines
4.0 KiB
C#
// Copyright (c) homuler and The Vignette Authors
|
|
// This file is part of MediaPipe.NET.
|
|
// MediaPipe.NET is licensed under the MIT License. See LICENSE for details.
|
|
|
|
using System;
|
|
using CommandLine;
|
|
using FFmpeg.AutoGen;
|
|
using Mediapipe.Net.External;
|
|
using Mediapipe.Net.Framework.Format;
|
|
using Mediapipe.Net.Solutions;
|
|
using Mediapipe.Net.Util;
|
|
using SeeShark;
|
|
using SeeShark.Device;
|
|
using SeeShark.FFmpeg;
|
|
|
|
namespace Mediapipe.Net.Examples.Pose
|
|
{
|
|
public static class Program
|
|
{
|
|
private static Camera? camera;
|
|
private static FrameConverter? converter;
|
|
private static readonly PoseCpuSolution calculator =
|
|
new PoseCpuSolution(modelComplexity: 2, smoothLandmarks: false);
|
|
|
|
private static ResourceManager? resourceManager;
|
|
|
|
public static void Main(string[] args)
|
|
{
|
|
// Get and parse command line arguments
|
|
Options parsed = Parser.Default.ParseArguments<Options>(args).Value;
|
|
|
|
(int, int)? videoSize = null;
|
|
if (parsed.Width != null && parsed.Height != null)
|
|
videoSize = ((int)parsed.Width, (int)parsed.Height);
|
|
else if (parsed.Width != null && parsed.Height == null)
|
|
Console.Error.WriteLine("Specifying width requires to specify height");
|
|
else if (parsed.Width == null && parsed.Height != null)
|
|
Console.Error.WriteLine("Specifying height requires to specify width");
|
|
|
|
FFmpegManager.SetupFFmpeg(@"C:\ffmpeg\v5.0_x64\", @"/usr/lib");
|
|
Glog.Initialize("stuff");
|
|
if (parsed.UseResourceManager)
|
|
resourceManager = new DummyResourceManager();
|
|
|
|
// Get a camera device
|
|
using (CameraManager manager = new CameraManager())
|
|
{
|
|
try
|
|
{
|
|
camera = manager.GetDevice(parsed.CameraIndex,
|
|
new VideoInputOptions
|
|
{
|
|
InputFormat = parsed.InputFormat,
|
|
Framerate = parsed.Framerate == null ? null : new AVRational
|
|
{
|
|
num = (int)parsed.Framerate,
|
|
den = 1,
|
|
},
|
|
VideoSize = videoSize,
|
|
});
|
|
Console.WriteLine($"Using camera {camera.Info}");
|
|
}
|
|
catch (Exception)
|
|
{
|
|
Console.Error.WriteLine($"No camera exists at index {parsed.CameraIndex}.");
|
|
return;
|
|
}
|
|
}
|
|
|
|
camera.OnFrame += onFrameEventHandler;
|
|
camera.StartCapture();
|
|
|
|
Console.CancelKeyPress += (sender, eventArgs) => exit();
|
|
}
|
|
|
|
private static int frameCount = 0;
|
|
private static void onFrameEventHandler(object? sender, FrameEventArgs e)
|
|
{
|
|
if (calculator == null)
|
|
return;
|
|
|
|
Frame frame = e.Frame;
|
|
if (frame.Width == 0 || frame.Height == 0)
|
|
return;
|
|
|
|
converter ??= new FrameConverter(frame, PixelFormat.Rgba);
|
|
Frame cFrame = converter.Convert(frame);
|
|
|
|
ImageFrame imgframe = new ImageFrame(ImageFormat.Srgba,
|
|
cFrame.Width, cFrame.Height, cFrame.WidthStep, cFrame.RawData);
|
|
|
|
PoseOutput handsOutput = calculator.Compute(imgframe);
|
|
|
|
if (handsOutput.PoseLandmarks != null)
|
|
{
|
|
var landmarks = handsOutput.PoseLandmarks.Landmark;
|
|
Console.WriteLine($"Got pose output with {landmarks.Count} landmarks"
|
|
+ $" at frame {frameCount}");
|
|
}
|
|
else
|
|
{
|
|
Console.WriteLine("No pose landmarks");
|
|
}
|
|
|
|
frameCount++;
|
|
}
|
|
|
|
// Dispose everything on exit
|
|
private static void exit()
|
|
{
|
|
Console.WriteLine("Exiting...");
|
|
camera?.Dispose();
|
|
converter?.Dispose();
|
|
calculator?.Dispose();
|
|
}
|
|
}
|
|
}
|