Commit: b4f58a7
Parent: ea3af18

Face detection with "raw" ONNX

Mårten Åsberg committed on 2026-06-09 at 18:33
Much, much, lighter, and works in the container
.containerfile +5 -2
diff --git a/.containerfile b/.containerfile
index e979309..c5fd6d2 100644
@@ -14,6 +14,9 @@ COPY ./src/Integrations/Vasttrafik/ ./src/Integrations/Vasttrafik/
COPY ./src/Integrations/FaceCamera/ ./src/Integrations/FaceCamera/
COPY ./src/App/ ./src/App/
ARG SixLaborsLicenseKey
ENV SixLaborsLicenseKey=${SixLaborsLicenseKey}
RUN dotnet build ./src/App/App.csproj --no-restore --configuration Release --runtime linux-arm64
RUN dotnet publish ./src/App/App.csproj --no-build --configuration Release --runtime linux-arm64 --output /output
@@ -25,8 +28,8 @@ WORKDIR /app
# Install DRM/KMS dependencies
RUN apt-get update && apt-get install -y kmscube libinput-tools
# Install OpenCV dependencies
RUN apt-get update && apt-get install -y build-essential libtiff-dev libgeotiff-dev libgtk-4-dev libgstreamer1.0-dev libavcodec-dev libswscale-dev libavformat-dev libopenexr-dev libdc1394-dev libv4l-dev libeigen3-dev libopengl-dev cmake-curses-gui freeglut3-dev git libvtk9-dev qt6-base-dev
# Install ONNX dependencies
RUN apt-get update && apt-get install -y libgomp1
COPY --from=build /output ./
.dockerignore +3 -0
diff --git a/.dockerignore b/.dockerignore
index f032f37..31e5cb1 100644
@@ -492,3 +492,6 @@ git-daemon-export-ok
# Development files
*.db*
# SixLabors license
**/sixlabors.lic
.gitignore +3 -0
diff --git a/.gitignore b/.gitignore
index 17916b9..4df2f3c 100644
@@ -488,3 +488,6 @@ git-daemon-export-ok
# Development files
*.db*
# SixLabors license
sixlabors.lic
Directory.Packages.props +4 -4
diff --git a/Directory.Packages.props b/Directory.Packages.props
index c1413d0..b1dc875 100644
@@ -15,15 +15,15 @@
<PackageVersion Include="Avalonia.Fonts.Inter" Version="12.0.4" />
<PackageVersion Include="AvaloniaUI.DiagnosticsSupport" Version="2.2.2" />
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.2" />
<PackageVersion Include="Emgu.CV" Version="4.13.0.5924" />
<PackageVersion Include="Emgu.CV.runtime.mini.debian-arm64" Version="4.12.0.5764" />
<PackageVersion Include="Emgu.CV.runtime.windows" Version="4.13.0.5924" />
<PackageVersion Include="FlashCap" Version="1.11.0" />
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="11.0.0-preview.4.26230.115" />
<PackageVersion Include="Microsoft.Extensions.Http.Resilience" Version="10.6.0" />
<PackageVersion
Include="Microsoft.Extensions.Options.ConfigurationExtensions"
Version="11.0.0-preview.4.26230.115"
/>
<PackageVersion Include="Microsoft.ML.OnnxRuntime" Version="1.26.0" />
<PackageVersion Include="Microsoft.ML.OnnxRuntime.Managed" Version="1.26.0" />
<PackageVersion Include="MSTest" Version="4.2.3" />
<PackageVersion
Include="Microsoft.Extensions.DependencyInjection"
@@ -34,8 +34,8 @@
Include="Microsoft.Extensions.Caching.Memory"
Version="11.0.0-preview.4.26230.115"
/>
<PackageVersion Include="OpenCvSharp4" Version="4.13.0.20260602" />
<PackageVersion Include="Shouldly" Version="4.3.0" />
<PackageVersion Include="SixLabors.ImageSharp" Version="4.0.0" />
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="8.19.1" />
</ItemGroup>
</Project>
src/App/App.csproj +1 -2
diff --git a/src/App/App.csproj b/src/App/App.csproj
index 02f39b2..44dd362 100644
@@ -27,8 +27,7 @@
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
</PackageReference>
<PackageReference Include="CommunityToolkit.Mvvm" />
<PackageReference Include="Emgu.CV.runtime.mini.debian-arm64" />
<PackageReference Include="Emgu.CV.runtime.windows" />
<PackageReference Include="Microsoft.Extensions.Hosting" />
<PackageReference Include="Microsoft.ML.OnnxRuntime" />
</ItemGroup>
</Project>
src/App/ViewModels/MainViewModel.cs +1 -1
diff --git a/src/App/ViewModels/MainViewModel.cs b/src/App/ViewModels/MainViewModel.cs
index 076b296..40acc5a 100644
@@ -44,7 +44,7 @@ public partial class MainViewModel : ViewModelBase
faceDetectionService.FaceDetected += OnFaceDetected;
}
private void OnFaceDetected(ReadOnlySpan<FaceDetection> faces) => FaceNear = faces.Length > 0;
private void OnFaceDetected(bool isFaceDetected) => FaceNear = isFaceDetected;
public void UnWatch()
{
src/App/packages.lock.json +81 -232
diff --git a/src/App/packages.lock.json b/src/App/packages.lock.json
index 7870687..89f1b8d 100644
@@ -76,27 +76,6 @@
"resolved": "1.2.6",
"contentHash": "KMSJG+jfk7vjP52QkWB99qWespXCPAzG/IaMCMRHYWumJEAGKQYm2HtyWG6eqnOwDitH96i1cqq5EVesyOtPmg=="
},
"Emgu.CV.runtime.mini.debian-arm64": {
"type": "Direct",
"requested": "[4.12.0.5764, )",
"resolved": "4.12.0.5764",
"contentHash": "bE7RsR4BMiu3vOIF1aex6+GgIA2taXUYN7Wqo/5l2QUr9sSGal6kxc2ypLVFJxy0YxJXxWRbFtJtuk02e1wCeQ==",
"dependencies": {
"Emgu.CV": "4.12.0.5764"
}
},
"Emgu.CV.runtime.windows": {
"type": "Direct",
"requested": "[4.13.0.5924, )",
"resolved": "4.13.0.5924",
"contentHash": "J072mACLTy3R1Y5kqit4IM3LqMoz1g0szIr/MT+qJVOA3RTvwnfyCTTZ6tQnvZLfbvk58PoxZmaU1J6MraeKoQ==",
"dependencies": {
"Emgu.CV": "4.13.0",
"Emgu.runtime.windows.msvc.rt.arm64": "19.44.35224",
"Emgu.runtime.windows.msvc.rt.x64": "19.44.35224",
"Emgu.runtime.windows.msvc.rt.x86": "19.44.35224"
}
},
"Microsoft.Extensions.Hosting": {
"type": "Direct",
"requested": "[11.0.0-preview.4.26230.115, )",
@@ -121,6 +100,15 @@
"Microsoft.Extensions.Logging.EventSource": "11.0.0-preview.4.26230.115"
}
},
"Microsoft.ML.OnnxRuntime": {
"type": "Direct",
"requested": "[1.26.0, )",
"resolved": "1.26.0",
"contentHash": "wiylawSnyspmJdZxilJUuUq3Tp/nT9BsngHHKvrCGWsADo15Z7y0G6kYAU0Pqb5af+f/EzwIi2aHaNUlzp/eww==",
"dependencies": {
"Microsoft.ML.OnnxRuntime.Managed": "1.26.0"
}
},
"Avalonia.Angle.Windows.Natives": {
"type": "Transitive",
"resolved": "2.1.27548.20260419",
@@ -206,20 +194,10 @@
"Avalonia.Skia": "12.0.4"
}
},
"Emgu.runtime.windows.msvc.rt.arm64": {
"FlashCap.Core": {
"type": "Transitive",
"resolved": "19.44.35224",
"contentHash": "+805ha7RSJDZ437VekFsju55p4onRbT7as9nT6KHQdR72AQQ8rj3uFzMYu36zDB8hyq2xBWEXCTk4KJuO+rBug=="
},
"Emgu.runtime.windows.msvc.rt.x64": {
"type": "Transitive",
"resolved": "19.44.35224",
"contentHash": "IMJsBnqobR4UM21vLNayY+8GlVRpgQHlRC1q6/iI1wbyejrEfWeWUyNVILj/tgmo8r0CgzOAJgR0jZcZGsPuNw=="
},
"Emgu.runtime.windows.msvc.rt.x86": {
"type": "Transitive",
"resolved": "19.44.35224",
"contentHash": "h8WzBTKDC3k34LOO4wkeHhq3ltpE3sbpk/2lOoKvTLKROJ/EcNqsYuGSwum8aYCeoMabucMqlbC/mV49uPng5Q=="
"resolved": "1.11.0",
"contentHash": "vEEUwQmpITV2iBgRU+YYl+Dr+Tm/1T/nXfnSLyLQSbBIWMlF/NO22OqU4ysfSNEb9TN6w+QK0bqGFMmnN13+Ag=="
},
"HarfBuzzSharp": {
"type": "Transitive",
@@ -558,6 +536,16 @@
"resolved": "11.0.0-preview.4.26230.115",
"contentHash": "/o76q92uK1eaosCQrIjp/V4OBHs9zIXxH+8ZEMFZg1GVH7fI24GUPx1BLawLCmdq/U1AdGeoto716k4BJEhi2g=="
},
"System.IO.Hashing": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "ne1843evDugl0md7Fjzy6QjJrzsjh46ZKbhf8GwBXb5f/gw97J4bxMs0NQKifDuThh/f0bZ0e62NPl1jzTuRqA=="
},
"System.Numerics.Tensors": {
"type": "Transitive",
"resolved": "9.0.0",
"contentHash": "hyJB4UlpAi19Xr9AXzu2NuagKC4lPfHObNMEAA0HmqFz2rX7wKgzeYzO/jM/eBHDhnUGFFEjk5cOoJaxqg5J4A=="
},
"System.Threading.RateLimiting": {
"type": "Transitive",
"resolved": "8.0.0",
@@ -571,8 +559,10 @@
"MMirror.Integrations.FaceCamera": {
"type": "Project",
"dependencies": {
"Emgu.CV": "[4.13.0.5924, )",
"Microsoft.Extensions.Options.ConfigurationExtensions": "[11.0.0-preview.4.26230.115, )"
"FlashCap": "[1.11.0, )",
"Microsoft.Extensions.Options.ConfigurationExtensions": "[11.0.0-preview.4.26230.115, )",
"Microsoft.ML.OnnxRuntime.Managed": "[1.26.0, )",
"SixLabors.ImageSharp": "[4.0.0, )"
}
},
"MMirror.Integrations.Vasttrafik": {
@@ -584,11 +574,14 @@
"System.IdentityModel.Tokens.Jwt": "[8.19.1, )"
}
},
"Emgu.CV": {
"FlashCap": {
"type": "CentralTransitive",
"requested": "[4.13.0.5924, )",
"resolved": "4.13.0.5924",
"contentHash": "st6Jux7EAlK2/LvG/aPaRLElFf54o0UrtCXU5ZEhGLRGeF8W/NW0j1x6MuRXur0DWJni++LsWInUDC6e4MtG5Q=="
"requested": "[1.11.0, )",
"resolved": "1.11.0",
"contentHash": "XwH9DHLKGUTciHat2D7GgsUegAOErJAyZHX+3H5gHX70Ipds7Zv2/q3T9/f0KkIh2A5P6WCg+lFwVxMgLERCKA==",
"dependencies": {
"FlashCap.Core": "1.11.0"
}
},
"Microsoft.Extensions.Caching.Memory": {
"type": "CentralTransitive",
@@ -632,6 +625,24 @@
"Microsoft.Extensions.Configuration.Binder": "11.0.0-preview.4.26230.115"
}
},
"Microsoft.ML.OnnxRuntime.Managed": {
"type": "CentralTransitive",
"requested": "[1.26.0, )",
"resolved": "1.26.0",
"contentHash": "hEmwYh5WL8n1xjNvmfdSUOqGGXAKCLtxfgUfGZRRAen9IWuSk7ieoBFH08+wlrYp1Vma80HtAirL3QLDbTeEzQ==",
"dependencies": {
"System.Numerics.Tensors": "9.0.0"
}
},
"SixLabors.ImageSharp": {
"type": "CentralTransitive",
"requested": "[4.0.0, )",
"resolved": "4.0.0",
"contentHash": "6Ft5sclM1t5bY+P0SsLLGwXIAgmDASFFD9hD0tlEcfFCU8Yj9nR7ZzaqCL/p+SIfqoe8jLKFHD7LFPRJPGXZ5w==",
"dependencies": {
"System.IO.Hashing": "8.0.0"
}
},
"System.IdentityModel.Tokens.Jwt": {
"type": "CentralTransitive",
"requested": "[8.19.1, )",
@@ -644,25 +655,13 @@
}
},
"net11.0/linux-arm64": {
"Emgu.CV.runtime.mini.debian-arm64": {
"type": "Direct",
"requested": "[4.12.0.5764, )",
"resolved": "4.12.0.5764",
"contentHash": "bE7RsR4BMiu3vOIF1aex6+GgIA2taXUYN7Wqo/5l2QUr9sSGal6kxc2ypLVFJxy0YxJXxWRbFtJtuk02e1wCeQ==",
"dependencies": {
"Emgu.CV": "4.12.0.5764"
}
},
"Emgu.CV.runtime.windows": {
"Microsoft.ML.OnnxRuntime": {
"type": "Direct",
"requested": "[4.13.0.5924, )",
"resolved": "4.13.0.5924",
"contentHash": "J072mACLTy3R1Y5kqit4IM3LqMoz1g0szIr/MT+qJVOA3RTvwnfyCTTZ6tQnvZLfbvk58PoxZmaU1J6MraeKoQ==",
"requested": "[1.26.0, )",
"resolved": "1.26.0",
"contentHash": "wiylawSnyspmJdZxilJUuUq3Tp/nT9BsngHHKvrCGWsADo15Z7y0G6kYAU0Pqb5af+f/EzwIi2aHaNUlzp/eww==",
"dependencies": {
"Emgu.CV": "4.13.0",
"Emgu.runtime.windows.msvc.rt.arm64": "19.44.35224",
"Emgu.runtime.windows.msvc.rt.x64": "19.44.35224",
"Emgu.runtime.windows.msvc.rt.x86": "19.44.35224"
"Microsoft.ML.OnnxRuntime.Managed": "1.26.0"
}
},
"Avalonia.Angle.Windows.Natives": {
@@ -678,21 +677,6 @@
"Avalonia": "12.0.4"
}
},
"Emgu.runtime.windows.msvc.rt.arm64": {
"type": "Transitive",
"resolved": "19.44.35224",
"contentHash": "+805ha7RSJDZ437VekFsju55p4onRbT7as9nT6KHQdR72AQQ8rj3uFzMYu36zDB8hyq2xBWEXCTk4KJuO+rBug=="
},
"Emgu.runtime.windows.msvc.rt.x64": {
"type": "Transitive",
"resolved": "19.44.35224",
"contentHash": "IMJsBnqobR4UM21vLNayY+8GlVRpgQHlRC1q6/iI1wbyejrEfWeWUyNVILj/tgmo8r0CgzOAJgR0jZcZGsPuNw=="
},
"Emgu.runtime.windows.msvc.rt.x86": {
"type": "Transitive",
"resolved": "19.44.35224",
"contentHash": "h8WzBTKDC3k34LOO4wkeHhq3ltpE3sbpk/2lOoKvTLKROJ/EcNqsYuGSwum8aYCeoMabucMqlbC/mV49uPng5Q=="
},
"HarfBuzzSharp.NativeAssets.Linux": {
"type": "Transitive",
"resolved": "8.3.1.3",
@@ -730,25 +714,13 @@
}
},
"net11.0/linux-x64": {
"Emgu.CV.runtime.mini.debian-arm64": {
"Microsoft.ML.OnnxRuntime": {
"type": "Direct",
"requested": "[4.12.0.5764, )",
"resolved": "4.12.0.5764",
"contentHash": "bE7RsR4BMiu3vOIF1aex6+GgIA2taXUYN7Wqo/5l2QUr9sSGal6kxc2ypLVFJxy0YxJXxWRbFtJtuk02e1wCeQ==",
"requested": "[1.26.0, )",
"resolved": "1.26.0",
"contentHash": "wiylawSnyspmJdZxilJUuUq3Tp/nT9BsngHHKvrCGWsADo15Z7y0G6kYAU0Pqb5af+f/EzwIi2aHaNUlzp/eww==",
"dependencies": {
"Emgu.CV": "4.12.0.5764"
}
},
"Emgu.CV.runtime.windows": {
"type": "Direct",
"requested": "[4.13.0.5924, )",
"resolved": "4.13.0.5924",
"contentHash": "J072mACLTy3R1Y5kqit4IM3LqMoz1g0szIr/MT+qJVOA3RTvwnfyCTTZ6tQnvZLfbvk58PoxZmaU1J6MraeKoQ==",
"dependencies": {
"Emgu.CV": "4.13.0",
"Emgu.runtime.windows.msvc.rt.arm64": "19.44.35224",
"Emgu.runtime.windows.msvc.rt.x64": "19.44.35224",
"Emgu.runtime.windows.msvc.rt.x86": "19.44.35224"
"Microsoft.ML.OnnxRuntime.Managed": "1.26.0"
}
},
"Avalonia.Angle.Windows.Natives": {
@@ -764,21 +736,6 @@
"Avalonia": "12.0.4"
}
},
"Emgu.runtime.windows.msvc.rt.arm64": {
"type": "Transitive",
"resolved": "19.44.35224",
"contentHash": "+805ha7RSJDZ437VekFsju55p4onRbT7as9nT6KHQdR72AQQ8rj3uFzMYu36zDB8hyq2xBWEXCTk4KJuO+rBug=="
},
"Emgu.runtime.windows.msvc.rt.x64": {
"type": "Transitive",
"resolved": "19.44.35224",
"contentHash": "IMJsBnqobR4UM21vLNayY+8GlVRpgQHlRC1q6/iI1wbyejrEfWeWUyNVILj/tgmo8r0CgzOAJgR0jZcZGsPuNw=="
},
"Emgu.runtime.windows.msvc.rt.x86": {
"type": "Transitive",
"resolved": "19.44.35224",
"contentHash": "h8WzBTKDC3k34LOO4wkeHhq3ltpE3sbpk/2lOoKvTLKROJ/EcNqsYuGSwum8aYCeoMabucMqlbC/mV49uPng5Q=="
},
"HarfBuzzSharp.NativeAssets.Linux": {
"type": "Transitive",
"resolved": "8.3.1.3",
@@ -816,25 +773,13 @@
}
},
"net11.0/osx-arm64": {
"Emgu.CV.runtime.mini.debian-arm64": {
"type": "Direct",
"requested": "[4.12.0.5764, )",
"resolved": "4.12.0.5764",
"contentHash": "bE7RsR4BMiu3vOIF1aex6+GgIA2taXUYN7Wqo/5l2QUr9sSGal6kxc2ypLVFJxy0YxJXxWRbFtJtuk02e1wCeQ==",
"dependencies": {
"Emgu.CV": "4.12.0.5764"
}
},
"Emgu.CV.runtime.windows": {
"Microsoft.ML.OnnxRuntime": {
"type": "Direct",
"requested": "[4.13.0.5924, )",
"resolved": "4.13.0.5924",
"contentHash": "J072mACLTy3R1Y5kqit4IM3LqMoz1g0szIr/MT+qJVOA3RTvwnfyCTTZ6tQnvZLfbvk58PoxZmaU1J6MraeKoQ==",
"requested": "[1.26.0, )",
"resolved": "1.26.0",
"contentHash": "wiylawSnyspmJdZxilJUuUq3Tp/nT9BsngHHKvrCGWsADo15Z7y0G6kYAU0Pqb5af+f/EzwIi2aHaNUlzp/eww==",
"dependencies": {
"Emgu.CV": "4.13.0",
"Emgu.runtime.windows.msvc.rt.arm64": "19.44.35224",
"Emgu.runtime.windows.msvc.rt.x64": "19.44.35224",
"Emgu.runtime.windows.msvc.rt.x86": "19.44.35224"
"Microsoft.ML.OnnxRuntime.Managed": "1.26.0"
}
},
"Avalonia.Angle.Windows.Natives": {
@@ -850,21 +795,6 @@
"Avalonia": "12.0.4"
}
},
"Emgu.runtime.windows.msvc.rt.arm64": {
"type": "Transitive",
"resolved": "19.44.35224",
"contentHash": "+805ha7RSJDZ437VekFsju55p4onRbT7as9nT6KHQdR72AQQ8rj3uFzMYu36zDB8hyq2xBWEXCTk4KJuO+rBug=="
},
"Emgu.runtime.windows.msvc.rt.x64": {
"type": "Transitive",
"resolved": "19.44.35224",
"contentHash": "IMJsBnqobR4UM21vLNayY+8GlVRpgQHlRC1q6/iI1wbyejrEfWeWUyNVILj/tgmo8r0CgzOAJgR0jZcZGsPuNw=="
},
"Emgu.runtime.windows.msvc.rt.x86": {
"type": "Transitive",
"resolved": "19.44.35224",
"contentHash": "h8WzBTKDC3k34LOO4wkeHhq3ltpE3sbpk/2lOoKvTLKROJ/EcNqsYuGSwum8aYCeoMabucMqlbC/mV49uPng5Q=="
},
"HarfBuzzSharp.NativeAssets.Linux": {
"type": "Transitive",
"resolved": "8.3.1.3",
@@ -902,25 +832,13 @@
}
},
"net11.0/osx-x64": {
"Emgu.CV.runtime.mini.debian-arm64": {
"Microsoft.ML.OnnxRuntime": {
"type": "Direct",
"requested": "[4.12.0.5764, )",
"resolved": "4.12.0.5764",
"contentHash": "bE7RsR4BMiu3vOIF1aex6+GgIA2taXUYN7Wqo/5l2QUr9sSGal6kxc2ypLVFJxy0YxJXxWRbFtJtuk02e1wCeQ==",
"requested": "[1.26.0, )",
"resolved": "1.26.0",
"contentHash": "wiylawSnyspmJdZxilJUuUq3Tp/nT9BsngHHKvrCGWsADo15Z7y0G6kYAU0Pqb5af+f/EzwIi2aHaNUlzp/eww==",
"dependencies": {
"Emgu.CV": "4.12.0.5764"
}
},
"Emgu.CV.runtime.windows": {
"type": "Direct",
"requested": "[4.13.0.5924, )",
"resolved": "4.13.0.5924",
"contentHash": "J072mACLTy3R1Y5kqit4IM3LqMoz1g0szIr/MT+qJVOA3RTvwnfyCTTZ6tQnvZLfbvk58PoxZmaU1J6MraeKoQ==",
"dependencies": {
"Emgu.CV": "4.13.0",
"Emgu.runtime.windows.msvc.rt.arm64": "19.44.35224",
"Emgu.runtime.windows.msvc.rt.x64": "19.44.35224",
"Emgu.runtime.windows.msvc.rt.x86": "19.44.35224"
"Microsoft.ML.OnnxRuntime.Managed": "1.26.0"
}
},
"Avalonia.Angle.Windows.Natives": {
@@ -936,21 +854,6 @@
"Avalonia": "12.0.4"
}
},
"Emgu.runtime.windows.msvc.rt.arm64": {
"type": "Transitive",
"resolved": "19.44.35224",
"contentHash": "+805ha7RSJDZ437VekFsju55p4onRbT7as9nT6KHQdR72AQQ8rj3uFzMYu36zDB8hyq2xBWEXCTk4KJuO+rBug=="
},
"Emgu.runtime.windows.msvc.rt.x64": {
"type": "Transitive",
"resolved": "19.44.35224",
"contentHash": "IMJsBnqobR4UM21vLNayY+8GlVRpgQHlRC1q6/iI1wbyejrEfWeWUyNVILj/tgmo8r0CgzOAJgR0jZcZGsPuNw=="
},
"Emgu.runtime.windows.msvc.rt.x86": {
"type": "Transitive",
"resolved": "19.44.35224",
"contentHash": "h8WzBTKDC3k34LOO4wkeHhq3ltpE3sbpk/2lOoKvTLKROJ/EcNqsYuGSwum8aYCeoMabucMqlbC/mV49uPng5Q=="
},
"HarfBuzzSharp.NativeAssets.Linux": {
"type": "Transitive",
"resolved": "8.3.1.3",
@@ -988,25 +891,13 @@
}
},
"net11.0/win-arm64": {
"Emgu.CV.runtime.mini.debian-arm64": {
"type": "Direct",
"requested": "[4.12.0.5764, )",
"resolved": "4.12.0.5764",
"contentHash": "bE7RsR4BMiu3vOIF1aex6+GgIA2taXUYN7Wqo/5l2QUr9sSGal6kxc2ypLVFJxy0YxJXxWRbFtJtuk02e1wCeQ==",
"dependencies": {
"Emgu.CV": "4.12.0.5764"
}
},
"Emgu.CV.runtime.windows": {
"Microsoft.ML.OnnxRuntime": {
"type": "Direct",
"requested": "[4.13.0.5924, )",
"resolved": "4.13.0.5924",
"contentHash": "J072mACLTy3R1Y5kqit4IM3LqMoz1g0szIr/MT+qJVOA3RTvwnfyCTTZ6tQnvZLfbvk58PoxZmaU1J6MraeKoQ==",
"requested": "[1.26.0, )",
"resolved": "1.26.0",
"contentHash": "wiylawSnyspmJdZxilJUuUq3Tp/nT9BsngHHKvrCGWsADo15Z7y0G6kYAU0Pqb5af+f/EzwIi2aHaNUlzp/eww==",
"dependencies": {
"Emgu.CV": "4.13.0",
"Emgu.runtime.windows.msvc.rt.arm64": "19.44.35224",
"Emgu.runtime.windows.msvc.rt.x64": "19.44.35224",
"Emgu.runtime.windows.msvc.rt.x86": "19.44.35224"
"Microsoft.ML.OnnxRuntime.Managed": "1.26.0"
}
},
"Avalonia.Angle.Windows.Natives": {
@@ -1022,21 +913,6 @@
"Avalonia": "12.0.4"
}
},
"Emgu.runtime.windows.msvc.rt.arm64": {
"type": "Transitive",
"resolved": "19.44.35224",
"contentHash": "+805ha7RSJDZ437VekFsju55p4onRbT7as9nT6KHQdR72AQQ8rj3uFzMYu36zDB8hyq2xBWEXCTk4KJuO+rBug=="
},
"Emgu.runtime.windows.msvc.rt.x64": {
"type": "Transitive",
"resolved": "19.44.35224",
"contentHash": "IMJsBnqobR4UM21vLNayY+8GlVRpgQHlRC1q6/iI1wbyejrEfWeWUyNVILj/tgmo8r0CgzOAJgR0jZcZGsPuNw=="
},
"Emgu.runtime.windows.msvc.rt.x86": {
"type": "Transitive",
"resolved": "19.44.35224",
"contentHash": "h8WzBTKDC3k34LOO4wkeHhq3ltpE3sbpk/2lOoKvTLKROJ/EcNqsYuGSwum8aYCeoMabucMqlbC/mV49uPng5Q=="
},
"HarfBuzzSharp.NativeAssets.Linux": {
"type": "Transitive",
"resolved": "8.3.1.3",
@@ -1074,25 +950,13 @@
}
},
"net11.0/win-x64": {
"Emgu.CV.runtime.mini.debian-arm64": {
"type": "Direct",
"requested": "[4.12.0.5764, )",
"resolved": "4.12.0.5764",
"contentHash": "bE7RsR4BMiu3vOIF1aex6+GgIA2taXUYN7Wqo/5l2QUr9sSGal6kxc2ypLVFJxy0YxJXxWRbFtJtuk02e1wCeQ==",
"dependencies": {
"Emgu.CV": "4.12.0.5764"
}
},
"Emgu.CV.runtime.windows": {
"Microsoft.ML.OnnxRuntime": {
"type": "Direct",
"requested": "[4.13.0.5924, )",
"resolved": "4.13.0.5924",
"contentHash": "J072mACLTy3R1Y5kqit4IM3LqMoz1g0szIr/MT+qJVOA3RTvwnfyCTTZ6tQnvZLfbvk58PoxZmaU1J6MraeKoQ==",
"requested": "[1.26.0, )",
"resolved": "1.26.0",
"contentHash": "wiylawSnyspmJdZxilJUuUq3Tp/nT9BsngHHKvrCGWsADo15Z7y0G6kYAU0Pqb5af+f/EzwIi2aHaNUlzp/eww==",
"dependencies": {
"Emgu.CV": "4.13.0",
"Emgu.runtime.windows.msvc.rt.arm64": "19.44.35224",
"Emgu.runtime.windows.msvc.rt.x64": "19.44.35224",
"Emgu.runtime.windows.msvc.rt.x86": "19.44.35224"
"Microsoft.ML.OnnxRuntime.Managed": "1.26.0"
}
},
"Avalonia.Angle.Windows.Natives": {
@@ -1108,21 +972,6 @@
"Avalonia": "12.0.4"
}
},
"Emgu.runtime.windows.msvc.rt.arm64": {
"type": "Transitive",
"resolved": "19.44.35224",
"contentHash": "+805ha7RSJDZ437VekFsju55p4onRbT7as9nT6KHQdR72AQQ8rj3uFzMYu36zDB8hyq2xBWEXCTk4KJuO+rBug=="
},
"Emgu.runtime.windows.msvc.rt.x64": {
"type": "Transitive",
"resolved": "19.44.35224",
"contentHash": "IMJsBnqobR4UM21vLNayY+8GlVRpgQHlRC1q6/iI1wbyejrEfWeWUyNVILj/tgmo8r0CgzOAJgR0jZcZGsPuNw=="
},
"Emgu.runtime.windows.msvc.rt.x86": {
"type": "Transitive",
"resolved": "19.44.35224",
"contentHash": "h8WzBTKDC3k34LOO4wkeHhq3ltpE3sbpk/2lOoKvTLKROJ/EcNqsYuGSwum8aYCeoMabucMqlbC/mV49uPng5Q=="
},
"HarfBuzzSharp.NativeAssets.Linux": {
"type": "Transitive",
"resolved": "8.3.1.3",
src/Integrations/FaceCamera/CameraOptions.cs +14 -3
diff --git a/src/Integrations/FaceCamera/CameraOptions.cs b/src/Integrations/FaceCamera/CameraOptions.cs
index 277e7b3..6326888 100644
@@ -1,3 +1,4 @@
using System;
using System.ComponentModel.DataAnnotations;
using Microsoft.Extensions.Options;
@@ -5,12 +6,22 @@ namespace MMirror.Integrations.FaceCamera;
public sealed class CameraOptions
{
public int Index { get; set; } = 0;
[Required]
public required string Model { get; set; }
public string Config { get; set; } = "";
[Required]
public required string Name { get; set; }
[Range(0, int.MaxValue)]
public int Width { get; set; } = 640;
[Range(0, int.MaxValue)]
public int Height { get; set; } = 480;
[Range(0.0f, 1.0f)]
public float Threshold { get; set; } = 0.7f;
public TimeSpan Interval { get; set; } = TimeSpan.FromSeconds(1);
}
[OptionsValidator]
src/Integrations/FaceCamera/FaceCamera.csproj +3 -1
diff --git a/src/Integrations/FaceCamera/FaceCamera.csproj b/src/Integrations/FaceCamera/FaceCamera.csproj
index 7202818..f8c503c 100644
@@ -4,7 +4,9 @@
<AssemblyName>MMirror.Integrations.FaceCamera</AssemblyName>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Emgu.CV" />
<PackageReference Include="FlashCap" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" />
<PackageReference Include="Microsoft.ML.OnnxRuntime.Managed" />
<PackageReference Include="SixLabors.ImageSharp" />
</ItemGroup>
</Project>
src/Integrations/FaceCamera/FaceDetectionService.cs +129 -27
diff --git a/src/Integrations/FaceCamera/FaceDetectionService.cs b/src/Integrations/FaceCamera/FaceDetectionService.cs
index 1dd7534..93ae5e8 100644
@@ -1,27 +1,63 @@
using System;
using System.Linq;
using System.Threading;
using Emgu.CV;
using FlashCap;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.ML.OnnxRuntime;
using Microsoft.ML.OnnxRuntime.Tensors;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
namespace MMirror.Integrations.FaceCamera;
public sealed class FaceDetectionService : IDisposable
{
private readonly ILogger<FaceDetectionService> logger;
private readonly VideoCapture videoCapture;
private readonly FaceDetectorYN faceDetector;
private readonly TimeProvider timeProvider;
private readonly Size targetSize;
private Size videoSize;
private readonly float threshold;
private readonly CaptureDeviceDescriptor videoDeviceDescriptor;
private CaptureDevice? videoDevice;
private readonly InferenceSession session;
private readonly TimeSpan interval;
private DateTimeOffset nextCheckTime;
private readonly Lock watchLock = new();
private Action<ReadOnlySpan<FaceDetection>>? faceDetected;
public event Action<ReadOnlySpan<FaceDetection>> FaceDetected
private Action<bool>? faceDetected;
public event Action<bool> FaceDetected
{
add
{
using var scope = watchLock.EnterScope();
if (faceDetected is null)
{
videoCapture.Start();
var characteristics =
videoDeviceDescriptor
.Characteristics.Where(c =>
c.PixelFormat is PixelFormats.YUYV
&& c.Width >= targetSize.Width
&& c.Height >= targetSize.Height
)
.MinBy(c => c.Width * c.Height)
?? throw new Exception(
$"No viable output format from camera available, options are {string.Join(", ", videoDeviceDescriptor.Characteristics.Select(c => $"{c.PixelFormat} {c.Width}x{c.Height}"))}."
);
videoSize = new(characteristics.Width, characteristics.Height);
videoDeviceDescriptor
.OpenAsync(characteristics, TranscodeFormats.DoNotTranscode, OnPixelBufferArrived)
.ContinueWith(t =>
{
videoDevice = t.Result;
videoDevice.StartAsync().ContinueWith(t => logger.LogInformation("Video capture has started"));
});
}
faceDetected += value;
}
@@ -31,48 +67,114 @@ public sealed class FaceDetectionService : IDisposable
faceDetected -= value;
if (faceDetected is null)
{
videoCapture.Stop();
videoDevice?.StopAsync().GetAwaiter().GetResult();
videoDevice?.Dispose();
}
}
}
public FaceDetectionService(ILogger<FaceDetectionService> logger, IOptions<CameraOptions> options)
public FaceDetectionService(
ILogger<FaceDetectionService> logger,
IOptions<CameraOptions> options,
TimeProvider timeProvider
)
{
this.logger = logger;
this.timeProvider = timeProvider;
videoCapture = new(options.Value.Index);
videoCapture.ImageGrabbed += OnImageGrabbed;
interval = options.Value.Interval;
nextCheckTime = timeProvider.GetUtcNow();
faceDetector = new FaceDetectorYN(
model: options.Value.Model,
config: options.Value.Config,
inputSize: new(videoCapture.Width, videoCapture.Height)
);
targetSize = new(options.Value.Width, options.Value.Height);
threshold = options.Value.Threshold;
var descriptors = new CaptureDevices().GetDescriptors();
videoDeviceDescriptor =
descriptors.FirstOrDefault(d => d.Identity as string == options.Value.Name)
?? throw new Exception(
$"No video device named {options.Value.Name} available, options are {string.Join(", ", descriptors.Select(d => d.Identity))}."
);
session = new(options.Value.Model);
}
private void OnImageGrabbed(object? sender, EventArgs e)
private void OnPixelBufferArrived(PixelBufferScope bufferScope)
{
using var frame = new Mat();
if (!videoCapture.Retrieve(frame))
if (timeProvider.GetUtcNow() < nextCheckTime)
{
logger.LogError("Could not retrieve frame on frame event.");
return;
}
using var detections = new Mat();
if (faceDetector.Detect(frame, detections) is not 1)
var data = bufferScope.Buffer.ReferImage();
var tensor = new DenseTensor<float>([1, 3, targetSize.Height, targetSize.Width]);
using (var image = new Image<Rgb24>(videoSize.Width, videoSize.Height))
{
logger.LogError("Facial detection failed.");
return;
var pixels = new ArraySegment<byte>(data.Array!, data.Offset + 54, videoSize.Width * videoSize.Height * 2);
image.ProcessPixelRows(accessor =>
{
for (var y = 0; y < videoSize.Height; y++)
{
var row = accessor.GetRowSpan(y);
for (var x = 0; x < videoSize.Width; x += 2)
{
var y1 = pixels[y * videoSize.Width * 2 + x * 2];
var u = pixels[y * videoSize.Width * 2 + x * 2 + 1];
var y2 = pixels[y * videoSize.Width * 2 + x * 2 + 2];
var v = pixels[y * videoSize.Width * 2 + x * 2 + 3];
row[x] = new(
(byte)float.Clamp(y1 + 1.402f * (v - 128), 0.0f, 256.0f),
(byte)float.Clamp(y1 - 0.344136f * (u - 128) - 0.714136f * (v - 128), 0.0f, 256.0f),
(byte)float.Clamp(y1 + 1.772f * (u - 128), 0.0f, 256.0f)
);
row[x + 1] = new(
(byte)float.Clamp(y2 + 1.402f * (v - 128), 0.0f, 256.0f),
(byte)float.Clamp(y2 - 0.344136f * (u - 128) - 0.714136f * (v - 128), 0.0f, 256.0f),
(byte)float.Clamp(y2 + 1.772f * (u - 128), 0.0f, 256.0f)
);
}
}
});
image.Mutate(o => o.Resize(options: new() { Mode = ResizeMode.Crop, Size = targetSize }));
image.ProcessPixelRows(accessor =>
{
for (var y = 0; y < image.Height; y++)
{
var row = accessor.GetRowSpan(y);
for (var x = 0; x < image.Width; x++)
{
tensor[0, 2, y, x] = row[x].R;
tensor[0, 1, y, x] = row[x].G;
tensor[0, 0, y, x] = row[x].B;
}
}
});
}
using (var outputs = session.Run([NamedOnnxValue.CreateFromTensor("input", tensor)]))
{
faceDetected?.Invoke(DetectedFace(outputs));
}
var faces = detections.GetSpan<FaceDetection>();
faceDetected?.Invoke(faces);
nextCheckTime = timeProvider.GetUtcNow() + interval;
}
private bool DetectedFace(IDisposableReadOnlyCollection<DisposableNamedOnnxValue> outputs) =>
DetectedFace(outputs, 8) || DetectedFace(outputs, 16) || DetectedFace(outputs, 32);
private bool DetectedFace(IDisposableReadOnlyCollection<DisposableNamedOnnxValue> outputs, int stride)
{
var clsData = outputs.First(o => o.Name == $"cls_{stride}").AsTensor<float>();
var objData = outputs.First(o => o.Name == $"obj_{stride}").AsTensor<float>();
return clsData
.Zip(objData, (cls, obj) => float.Sqrt(float.Clamp(cls, 0.0f, 1.0f) * float.Clamp(obj, 0.0f, 1.0f)))
.Any(s => s > threshold);
}
public void Dispose()
{
videoCapture.Dispose();
faceDetector.Dispose();
videoDevice?.Dispose();
session.Dispose();
}
}
src/Integrations/FaceCamera/packages.lock.json +40 -4
diff --git a/src/Integrations/FaceCamera/packages.lock.json b/src/Integrations/FaceCamera/packages.lock.json
index 44af7f7..3701291 100644
@@ -8,11 +8,14 @@
"resolved": "1.2.6",
"contentHash": "KMSJG+jfk7vjP52QkWB99qWespXCPAzG/IaMCMRHYWumJEAGKQYm2HtyWG6eqnOwDitH96i1cqq5EVesyOtPmg=="
},
"Emgu.CV": {
"FlashCap": {
"type": "Direct",
"requested": "[4.13.0.5924, )",
"resolved": "4.13.0.5924",
"contentHash": "st6Jux7EAlK2/LvG/aPaRLElFf54o0UrtCXU5ZEhGLRGeF8W/NW0j1x6MuRXur0DWJni++LsWInUDC6e4MtG5Q=="
"requested": "[1.11.0, )",
"resolved": "1.11.0",
"contentHash": "XwH9DHLKGUTciHat2D7GgsUegAOErJAyZHX+3H5gHX70Ipds7Zv2/q3T9/f0KkIh2A5P6WCg+lFwVxMgLERCKA==",
"dependencies": {
"FlashCap.Core": "1.11.0"
}
},
"Microsoft.Extensions.Options.ConfigurationExtensions": {
"type": "Direct",
@@ -23,6 +26,29 @@
"Microsoft.Extensions.Configuration.Binder": "11.0.0-preview.4.26230.115"
}
},
"Microsoft.ML.OnnxRuntime.Managed": {
"type": "Direct",
"requested": "[1.26.0, )",
"resolved": "1.26.0",
"contentHash": "hEmwYh5WL8n1xjNvmfdSUOqGGXAKCLtxfgUfGZRRAen9IWuSk7ieoBFH08+wlrYp1Vma80HtAirL3QLDbTeEzQ==",
"dependencies": {
"System.Numerics.Tensors": "9.0.0"
}
},
"SixLabors.ImageSharp": {
"type": "Direct",
"requested": "[4.0.0, )",
"resolved": "4.0.0",
"contentHash": "6Ft5sclM1t5bY+P0SsLLGwXIAgmDASFFD9hD0tlEcfFCU8Yj9nR7ZzaqCL/p+SIfqoe8jLKFHD7LFPRJPGXZ5w==",
"dependencies": {
"System.IO.Hashing": "8.0.0"
}
},
"FlashCap.Core": {
"type": "Transitive",
"resolved": "1.11.0",
"contentHash": "vEEUwQmpITV2iBgRU+YYl+Dr+Tm/1T/nXfnSLyLQSbBIWMlF/NO22OqU4ysfSNEb9TN6w+QK0bqGFMmnN13+Ag=="
},
"Microsoft.Extensions.Configuration": {
"type": "Transitive",
"resolved": "11.0.0-preview.4.26230.115",
@@ -35,6 +61,16 @@
"dependencies": {
"Microsoft.Extensions.Configuration": "11.0.0-preview.4.26230.115"
}
},
"System.IO.Hashing": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "ne1843evDugl0md7Fjzy6QjJrzsjh46ZKbhf8GwBXb5f/gw97J4bxMs0NQKifDuThh/f0bZ0e62NPl1jzTuRqA=="
},
"System.Numerics.Tensors": {
"type": "Transitive",
"resolved": "9.0.0",
"contentHash": "hyJB4UlpAi19Xr9AXzu2NuagKC4lPfHObNMEAA0HmqFz2rX7wKgzeYzO/jM/eBHDhnUGFFEjk5cOoJaxqg5J4A=="
}
},
"net11.0/linux-arm64": {},
tests/Integrations/FaceCamera/FaceCamera.csproj +1 -1
diff --git a/tests/Integrations/FaceCamera/FaceCamera.csproj b/tests/Integrations/FaceCamera/FaceCamera.csproj
index 28e7f93..c0d0963 100644
@@ -12,8 +12,8 @@
<ProjectReference Include="..\..\..\src\Integrations\FaceCamera\FaceCamera.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Emgu.CV.runtime.windows" />
<PackageReference Include="Microsoft.Extensions.Hosting" />
<PackageReference Include="Microsoft.ML.OnnxRuntime" />
<PackageReference Include="MSTest" />
<PackageReference Include="Shouldly" />
</ItemGroup>
tests/Integrations/FaceCamera/FaceDetectionServiceTests/IntegrationTests.cs +5 -6
diff --git a/tests/Integrations/FaceCamera/FaceDetectionServiceTests/IntegrationTests.cs b/tests/Integrations/FaceCamera/FaceDetectionServiceTests/IntegrationTests.cs
index 2b960aa..375c7de 100644
@@ -1,4 +1,3 @@
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
@@ -19,15 +18,15 @@ public sealed class IntegrationTests
host.Services.AddFaceCameraServices();
var app = host.Build();
var faceDetectionService = app.Services.GetRequiredService<FaceDetectionService>();
var tcs = new TaskCompletionSource<FaceDetection[]>();
var tcs = new TaskCompletionSource<bool>();
faceDetectionService.FaceDetected += OnFaceDetected;
var faces = await tcs.Task;
faces.Length.ShouldBeGreaterThan(0);
var faceDetected = await tcs.Task;
faceDetected.ShouldBeTrue();
void OnFaceDetected(ReadOnlySpan<FaceDetection> faces)
void OnFaceDetected(bool faceDetected)
{
faceDetectionService.FaceDetected -= OnFaceDetected;
tcs.SetResult(faces.ToArray());
tcs.SetResult(faceDetected);
}
}
}
tests/Integrations/FaceCamera/README.md +1 -1
diff --git a/tests/Integrations/FaceCamera/README.md b/tests/Integrations/FaceCamera/README.md
index 91bc0d9..8867ce1 100644
@@ -4,7 +4,7 @@ These are integration tests for the face detection service.
## Setup
If no setup is performed the "default" camera will be used. To specify which camera to use, set the `Camera.Index` value as a User Secret before running the tests.
You need to specify which camera to use, set the `Camera.Name` value as a User Secret before running the tests.
You also need to download the facial detection model [face_detection_yunet_2026may.onnx](https://github.com/opencv/opencv_zoo/blob/47534e27c9851bb1128ccc0102f1145e27f23f98/models/face_detection_yunet/face_detection_yunet_2026may.onnx) and reference to it from `Camera.Model` in the User Secrets.
tests/Integrations/FaceCamera/packages.lock.json +83 -171
diff --git a/tests/Integrations/FaceCamera/packages.lock.json b/tests/Integrations/FaceCamera/packages.lock.json
index d4e12aa..90e2956 100644
@@ -8,18 +8,6 @@
"resolved": "1.2.6",
"contentHash": "KMSJG+jfk7vjP52QkWB99qWespXCPAzG/IaMCMRHYWumJEAGKQYm2HtyWG6eqnOwDitH96i1cqq5EVesyOtPmg=="
},
"Emgu.CV.runtime.windows": {
"type": "Direct",
"requested": "[4.13.0.5924, )",
"resolved": "4.13.0.5924",
"contentHash": "J072mACLTy3R1Y5kqit4IM3LqMoz1g0szIr/MT+qJVOA3RTvwnfyCTTZ6tQnvZLfbvk58PoxZmaU1J6MraeKoQ==",
"dependencies": {
"Emgu.CV": "4.13.0",
"Emgu.runtime.windows.msvc.rt.arm64": "19.44.35224",
"Emgu.runtime.windows.msvc.rt.x64": "19.44.35224",
"Emgu.runtime.windows.msvc.rt.x86": "19.44.35224"
}
},
"Microsoft.Extensions.Hosting": {
"type": "Direct",
"requested": "[11.0.0-preview.4.26230.115, )",
@@ -44,6 +32,15 @@
"Microsoft.Extensions.Logging.EventSource": "11.0.0-preview.4.26230.115"
}
},
"Microsoft.ML.OnnxRuntime": {
"type": "Direct",
"requested": "[1.26.0, )",
"resolved": "1.26.0",
"contentHash": "wiylawSnyspmJdZxilJUuUq3Tp/nT9BsngHHKvrCGWsADo15Z7y0G6kYAU0Pqb5af+f/EzwIi2aHaNUlzp/eww==",
"dependencies": {
"Microsoft.ML.OnnxRuntime.Managed": "1.26.0"
}
},
"MSTest": {
"type": "Direct",
"requested": "[4.2.3, )",
@@ -76,26 +73,16 @@
"System.Management": "6.0.1"
}
},
"Emgu.runtime.windows.msvc.rt.arm64": {
"type": "Transitive",
"resolved": "19.44.35224",
"contentHash": "+805ha7RSJDZ437VekFsju55p4onRbT7as9nT6KHQdR72AQQ8rj3uFzMYu36zDB8hyq2xBWEXCTk4KJuO+rBug=="
},
"Emgu.runtime.windows.msvc.rt.x64": {
"type": "Transitive",
"resolved": "19.44.35224",
"contentHash": "IMJsBnqobR4UM21vLNayY+8GlVRpgQHlRC1q6/iI1wbyejrEfWeWUyNVILj/tgmo8r0CgzOAJgR0jZcZGsPuNw=="
},
"Emgu.runtime.windows.msvc.rt.x86": {
"type": "Transitive",
"resolved": "19.44.35224",
"contentHash": "h8WzBTKDC3k34LOO4wkeHhq3ltpE3sbpk/2lOoKvTLKROJ/EcNqsYuGSwum8aYCeoMabucMqlbC/mV49uPng5Q=="
},
"EmptyFiles": {
"type": "Transitive",
"resolved": "4.4.0",
"contentHash": "gwJEfIGS7FhykvtZoscwXj/XwW+mJY6UbAZk+qtLKFUGWC95kfKXnj8VkxsZQnWBxJemM/q664rGLN5nf+OHZw=="
},
"FlashCap.Core": {
"type": "Transitive",
"resolved": "1.11.0",
"contentHash": "vEEUwQmpITV2iBgRU+YYl+Dr+Tm/1T/nXfnSLyLQSbBIWMlF/NO22OqU4ysfSNEb9TN6w+QK0bqGFMmnN13+Ag=="
},
"Microsoft.ApplicationInsights": {
"type": "Transitive",
"resolved": "2.23.0",
@@ -369,6 +356,11 @@
"resolved": "11.0.0-preview.4.26230.115",
"contentHash": "/o76q92uK1eaosCQrIjp/V4OBHs9zIXxH+8ZEMFZg1GVH7fI24GUPx1BLawLCmdq/U1AdGeoto716k4BJEhi2g=="
},
"System.IO.Hashing": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "ne1843evDugl0md7Fjzy6QjJrzsjh46ZKbhf8GwBXb5f/gw97J4bxMs0NQKifDuThh/f0bZ0e62NPl1jzTuRqA=="
},
"System.Management": {
"type": "Transitive",
"resolved": "6.0.1",
@@ -377,18 +369,28 @@
"System.CodeDom": "6.0.0"
}
},
"System.Numerics.Tensors": {
"type": "Transitive",
"resolved": "9.0.0",
"contentHash": "hyJB4UlpAi19Xr9AXzu2NuagKC4lPfHObNMEAA0HmqFz2rX7wKgzeYzO/jM/eBHDhnUGFFEjk5cOoJaxqg5J4A=="
},
"MMirror.Integrations.FaceCamera": {
"type": "Project",
"dependencies": {
"Emgu.CV": "[4.13.0.5924, )",
"Microsoft.Extensions.Options.ConfigurationExtensions": "[11.0.0-preview.4.26230.115, )"
"FlashCap": "[1.11.0, )",
"Microsoft.Extensions.Options.ConfigurationExtensions": "[11.0.0-preview.4.26230.115, )",
"Microsoft.ML.OnnxRuntime.Managed": "[1.26.0, )",
"SixLabors.ImageSharp": "[4.0.0, )"
}
},
"Emgu.CV": {
"FlashCap": {
"type": "CentralTransitive",
"requested": "[4.13.0.5924, )",
"resolved": "4.13.0.5924",
"contentHash": "st6Jux7EAlK2/LvG/aPaRLElFf54o0UrtCXU5ZEhGLRGeF8W/NW0j1x6MuRXur0DWJni++LsWInUDC6e4MtG5Q=="
"requested": "[1.11.0, )",
"resolved": "1.11.0",
"contentHash": "XwH9DHLKGUTciHat2D7GgsUegAOErJAyZHX+3H5gHX70Ipds7Zv2/q3T9/f0KkIh2A5P6WCg+lFwVxMgLERCKA==",
"dependencies": {
"FlashCap.Core": "1.11.0"
}
},
"Microsoft.Extensions.DependencyInjection": {
"type": "CentralTransitive",
@@ -404,36 +406,36 @@
"dependencies": {
"Microsoft.Extensions.Configuration.Binder": "11.0.0-preview.4.26230.115"
}
},
"Microsoft.ML.OnnxRuntime.Managed": {
"type": "CentralTransitive",
"requested": "[1.26.0, )",
"resolved": "1.26.0",
"contentHash": "hEmwYh5WL8n1xjNvmfdSUOqGGXAKCLtxfgUfGZRRAen9IWuSk7ieoBFH08+wlrYp1Vma80HtAirL3QLDbTeEzQ==",
"dependencies": {
"System.Numerics.Tensors": "9.0.0"
}
},
"SixLabors.ImageSharp": {
"type": "CentralTransitive",
"requested": "[4.0.0, )",
"resolved": "4.0.0",
"contentHash": "6Ft5sclM1t5bY+P0SsLLGwXIAgmDASFFD9hD0tlEcfFCU8Yj9nR7ZzaqCL/p+SIfqoe8jLKFHD7LFPRJPGXZ5w==",
"dependencies": {
"System.IO.Hashing": "8.0.0"
}
}
},
"net11.0/linux-arm64": {
"Emgu.CV.runtime.windows": {
"Microsoft.ML.OnnxRuntime": {
"type": "Direct",
"requested": "[4.13.0.5924, )",
"resolved": "4.13.0.5924",
"contentHash": "J072mACLTy3R1Y5kqit4IM3LqMoz1g0szIr/MT+qJVOA3RTvwnfyCTTZ6tQnvZLfbvk58PoxZmaU1J6MraeKoQ==",
"requested": "[1.26.0, )",
"resolved": "1.26.0",
"contentHash": "wiylawSnyspmJdZxilJUuUq3Tp/nT9BsngHHKvrCGWsADo15Z7y0G6kYAU0Pqb5af+f/EzwIi2aHaNUlzp/eww==",
"dependencies": {
"Emgu.CV": "4.13.0",
"Emgu.runtime.windows.msvc.rt.arm64": "19.44.35224",
"Emgu.runtime.windows.msvc.rt.x64": "19.44.35224",
"Emgu.runtime.windows.msvc.rt.x86": "19.44.35224"
"Microsoft.ML.OnnxRuntime.Managed": "1.26.0"
}
},
"Emgu.runtime.windows.msvc.rt.arm64": {
"type": "Transitive",
"resolved": "19.44.35224",
"contentHash": "+805ha7RSJDZ437VekFsju55p4onRbT7as9nT6KHQdR72AQQ8rj3uFzMYu36zDB8hyq2xBWEXCTk4KJuO+rBug=="
},
"Emgu.runtime.windows.msvc.rt.x64": {
"type": "Transitive",
"resolved": "19.44.35224",
"contentHash": "IMJsBnqobR4UM21vLNayY+8GlVRpgQHlRC1q6/iI1wbyejrEfWeWUyNVILj/tgmo8r0CgzOAJgR0jZcZGsPuNw=="
},
"Emgu.runtime.windows.msvc.rt.x86": {
"type": "Transitive",
"resolved": "19.44.35224",
"contentHash": "h8WzBTKDC3k34LOO4wkeHhq3ltpE3sbpk/2lOoKvTLKROJ/EcNqsYuGSwum8aYCeoMabucMqlbC/mV49uPng5Q=="
},
"Microsoft.Testing.Extensions.CodeCoverage": {
"type": "Transitive",
"resolved": "18.5.2",
@@ -459,33 +461,15 @@
}
},
"net11.0/linux-x64": {
"Emgu.CV.runtime.windows": {
"Microsoft.ML.OnnxRuntime": {
"type": "Direct",
"requested": "[4.13.0.5924, )",
"resolved": "4.13.0.5924",
"contentHash": "J072mACLTy3R1Y5kqit4IM3LqMoz1g0szIr/MT+qJVOA3RTvwnfyCTTZ6tQnvZLfbvk58PoxZmaU1J6MraeKoQ==",
"requested": "[1.26.0, )",
"resolved": "1.26.0",
"contentHash": "wiylawSnyspmJdZxilJUuUq3Tp/nT9BsngHHKvrCGWsADo15Z7y0G6kYAU0Pqb5af+f/EzwIi2aHaNUlzp/eww==",
"dependencies": {
"Emgu.CV": "4.13.0",
"Emgu.runtime.windows.msvc.rt.arm64": "19.44.35224",
"Emgu.runtime.windows.msvc.rt.x64": "19.44.35224",
"Emgu.runtime.windows.msvc.rt.x86": "19.44.35224"
"Microsoft.ML.OnnxRuntime.Managed": "1.26.0"
}
},
"Emgu.runtime.windows.msvc.rt.arm64": {
"type": "Transitive",
"resolved": "19.44.35224",
"contentHash": "+805ha7RSJDZ437VekFsju55p4onRbT7as9nT6KHQdR72AQQ8rj3uFzMYu36zDB8hyq2xBWEXCTk4KJuO+rBug=="
},
"Emgu.runtime.windows.msvc.rt.x64": {
"type": "Transitive",
"resolved": "19.44.35224",
"contentHash": "IMJsBnqobR4UM21vLNayY+8GlVRpgQHlRC1q6/iI1wbyejrEfWeWUyNVILj/tgmo8r0CgzOAJgR0jZcZGsPuNw=="
},
"Emgu.runtime.windows.msvc.rt.x86": {
"type": "Transitive",
"resolved": "19.44.35224",
"contentHash": "h8WzBTKDC3k34LOO4wkeHhq3ltpE3sbpk/2lOoKvTLKROJ/EcNqsYuGSwum8aYCeoMabucMqlbC/mV49uPng5Q=="
},
"Microsoft.Testing.Extensions.CodeCoverage": {
"type": "Transitive",
"resolved": "18.5.2",
@@ -511,33 +495,15 @@
}
},
"net11.0/osx-arm64": {
"Emgu.CV.runtime.windows": {
"Microsoft.ML.OnnxRuntime": {
"type": "Direct",
"requested": "[4.13.0.5924, )",
"resolved": "4.13.0.5924",
"contentHash": "J072mACLTy3R1Y5kqit4IM3LqMoz1g0szIr/MT+qJVOA3RTvwnfyCTTZ6tQnvZLfbvk58PoxZmaU1J6MraeKoQ==",
"requested": "[1.26.0, )",
"resolved": "1.26.0",
"contentHash": "wiylawSnyspmJdZxilJUuUq3Tp/nT9BsngHHKvrCGWsADo15Z7y0G6kYAU0Pqb5af+f/EzwIi2aHaNUlzp/eww==",
"dependencies": {
"Emgu.CV": "4.13.0",
"Emgu.runtime.windows.msvc.rt.arm64": "19.44.35224",
"Emgu.runtime.windows.msvc.rt.x64": "19.44.35224",
"Emgu.runtime.windows.msvc.rt.x86": "19.44.35224"
"Microsoft.ML.OnnxRuntime.Managed": "1.26.0"
}
},
"Emgu.runtime.windows.msvc.rt.arm64": {
"type": "Transitive",
"resolved": "19.44.35224",
"contentHash": "+805ha7RSJDZ437VekFsju55p4onRbT7as9nT6KHQdR72AQQ8rj3uFzMYu36zDB8hyq2xBWEXCTk4KJuO+rBug=="
},
"Emgu.runtime.windows.msvc.rt.x64": {
"type": "Transitive",
"resolved": "19.44.35224",
"contentHash": "IMJsBnqobR4UM21vLNayY+8GlVRpgQHlRC1q6/iI1wbyejrEfWeWUyNVILj/tgmo8r0CgzOAJgR0jZcZGsPuNw=="
},
"Emgu.runtime.windows.msvc.rt.x86": {
"type": "Transitive",
"resolved": "19.44.35224",
"contentHash": "h8WzBTKDC3k34LOO4wkeHhq3ltpE3sbpk/2lOoKvTLKROJ/EcNqsYuGSwum8aYCeoMabucMqlbC/mV49uPng5Q=="
},
"Microsoft.Testing.Extensions.CodeCoverage": {
"type": "Transitive",
"resolved": "18.5.2",
@@ -563,33 +529,15 @@
}
},
"net11.0/osx-x64": {
"Emgu.CV.runtime.windows": {
"Microsoft.ML.OnnxRuntime": {
"type": "Direct",
"requested": "[4.13.0.5924, )",
"resolved": "4.13.0.5924",
"contentHash": "J072mACLTy3R1Y5kqit4IM3LqMoz1g0szIr/MT+qJVOA3RTvwnfyCTTZ6tQnvZLfbvk58PoxZmaU1J6MraeKoQ==",
"requested": "[1.26.0, )",
"resolved": "1.26.0",
"contentHash": "wiylawSnyspmJdZxilJUuUq3Tp/nT9BsngHHKvrCGWsADo15Z7y0G6kYAU0Pqb5af+f/EzwIi2aHaNUlzp/eww==",
"dependencies": {
"Emgu.CV": "4.13.0",
"Emgu.runtime.windows.msvc.rt.arm64": "19.44.35224",
"Emgu.runtime.windows.msvc.rt.x64": "19.44.35224",
"Emgu.runtime.windows.msvc.rt.x86": "19.44.35224"
"Microsoft.ML.OnnxRuntime.Managed": "1.26.0"
}
},
"Emgu.runtime.windows.msvc.rt.arm64": {
"type": "Transitive",
"resolved": "19.44.35224",
"contentHash": "+805ha7RSJDZ437VekFsju55p4onRbT7as9nT6KHQdR72AQQ8rj3uFzMYu36zDB8hyq2xBWEXCTk4KJuO+rBug=="
},
"Emgu.runtime.windows.msvc.rt.x64": {
"type": "Transitive",
"resolved": "19.44.35224",
"contentHash": "IMJsBnqobR4UM21vLNayY+8GlVRpgQHlRC1q6/iI1wbyejrEfWeWUyNVILj/tgmo8r0CgzOAJgR0jZcZGsPuNw=="
},
"Emgu.runtime.windows.msvc.rt.x86": {
"type": "Transitive",
"resolved": "19.44.35224",
"contentHash": "h8WzBTKDC3k34LOO4wkeHhq3ltpE3sbpk/2lOoKvTLKROJ/EcNqsYuGSwum8aYCeoMabucMqlbC/mV49uPng5Q=="
},
"Microsoft.Testing.Extensions.CodeCoverage": {
"type": "Transitive",
"resolved": "18.5.2",
@@ -615,33 +563,15 @@
}
},
"net11.0/win-arm64": {
"Emgu.CV.runtime.windows": {
"Microsoft.ML.OnnxRuntime": {
"type": "Direct",
"requested": "[4.13.0.5924, )",
"resolved": "4.13.0.5924",
"contentHash": "J072mACLTy3R1Y5kqit4IM3LqMoz1g0szIr/MT+qJVOA3RTvwnfyCTTZ6tQnvZLfbvk58PoxZmaU1J6MraeKoQ==",
"requested": "[1.26.0, )",
"resolved": "1.26.0",
"contentHash": "wiylawSnyspmJdZxilJUuUq3Tp/nT9BsngHHKvrCGWsADo15Z7y0G6kYAU0Pqb5af+f/EzwIi2aHaNUlzp/eww==",
"dependencies": {
"Emgu.CV": "4.13.0",
"Emgu.runtime.windows.msvc.rt.arm64": "19.44.35224",
"Emgu.runtime.windows.msvc.rt.x64": "19.44.35224",
"Emgu.runtime.windows.msvc.rt.x86": "19.44.35224"
"Microsoft.ML.OnnxRuntime.Managed": "1.26.0"
}
},
"Emgu.runtime.windows.msvc.rt.arm64": {
"type": "Transitive",
"resolved": "19.44.35224",
"contentHash": "+805ha7RSJDZ437VekFsju55p4onRbT7as9nT6KHQdR72AQQ8rj3uFzMYu36zDB8hyq2xBWEXCTk4KJuO+rBug=="
},
"Emgu.runtime.windows.msvc.rt.x64": {
"type": "Transitive",
"resolved": "19.44.35224",
"contentHash": "IMJsBnqobR4UM21vLNayY+8GlVRpgQHlRC1q6/iI1wbyejrEfWeWUyNVILj/tgmo8r0CgzOAJgR0jZcZGsPuNw=="
},
"Emgu.runtime.windows.msvc.rt.x86": {
"type": "Transitive",
"resolved": "19.44.35224",
"contentHash": "h8WzBTKDC3k34LOO4wkeHhq3ltpE3sbpk/2lOoKvTLKROJ/EcNqsYuGSwum8aYCeoMabucMqlbC/mV49uPng5Q=="
},
"Microsoft.Testing.Extensions.CodeCoverage": {
"type": "Transitive",
"resolved": "18.5.2",
@@ -667,33 +597,15 @@
}
},
"net11.0/win-x64": {
"Emgu.CV.runtime.windows": {
"Microsoft.ML.OnnxRuntime": {
"type": "Direct",
"requested": "[4.13.0.5924, )",
"resolved": "4.13.0.5924",
"contentHash": "J072mACLTy3R1Y5kqit4IM3LqMoz1g0szIr/MT+qJVOA3RTvwnfyCTTZ6tQnvZLfbvk58PoxZmaU1J6MraeKoQ==",
"requested": "[1.26.0, )",
"resolved": "1.26.0",
"contentHash": "wiylawSnyspmJdZxilJUuUq3Tp/nT9BsngHHKvrCGWsADo15Z7y0G6kYAU0Pqb5af+f/EzwIi2aHaNUlzp/eww==",
"dependencies": {
"Emgu.CV": "4.13.0",
"Emgu.runtime.windows.msvc.rt.arm64": "19.44.35224",
"Emgu.runtime.windows.msvc.rt.x64": "19.44.35224",
"Emgu.runtime.windows.msvc.rt.x86": "19.44.35224"
"Microsoft.ML.OnnxRuntime.Managed": "1.26.0"
}
},
"Emgu.runtime.windows.msvc.rt.arm64": {
"type": "Transitive",
"resolved": "19.44.35224",
"contentHash": "+805ha7RSJDZ437VekFsju55p4onRbT7as9nT6KHQdR72AQQ8rj3uFzMYu36zDB8hyq2xBWEXCTk4KJuO+rBug=="
},
"Emgu.runtime.windows.msvc.rt.x64": {
"type": "Transitive",
"resolved": "19.44.35224",
"contentHash": "IMJsBnqobR4UM21vLNayY+8GlVRpgQHlRC1q6/iI1wbyejrEfWeWUyNVILj/tgmo8r0CgzOAJgR0jZcZGsPuNw=="
},
"Emgu.runtime.windows.msvc.rt.x86": {
"type": "Transitive",
"resolved": "19.44.35224",
"contentHash": "h8WzBTKDC3k34LOO4wkeHhq3ltpE3sbpk/2lOoKvTLKROJ/EcNqsYuGSwum8aYCeoMabucMqlbC/mV49uPng5Q=="
},
"Microsoft.Testing.Extensions.CodeCoverage": {
"type": "Transitive",
"resolved": "18.5.2",