mirror of
https://github.com/unclshura/splitter.git
synced 2026-06-22 00:22:01 +00:00
Added slider for identity confidence. Progress is back.
This commit is contained in:
parent
f2493c1709
commit
e5a9a04265
@ -122,6 +122,19 @@ public partial class JobViewModel : ObservableObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public float IdentityThreshold
|
||||||
|
{
|
||||||
|
get => Job.IdentityThreshold;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (Math.Abs(Job.IdentityThreshold - value) < 0.001)
|
||||||
|
return;
|
||||||
|
Job.IdentityThreshold = value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
Task.Run(CreatePreview);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public string? Mask
|
public string? Mask
|
||||||
{
|
{
|
||||||
get => Job.Mask;
|
get => Job.Mask;
|
||||||
|
|||||||
@ -54,7 +54,7 @@ public partial class MainViewModel : ViewModelBase
|
|||||||
_cancellationTokenSource?.Cancel();
|
_cancellationTokenSource?.Cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Start()
|
public Task Start() => Task.Run(async () =>
|
||||||
{
|
{
|
||||||
_cancellationTokenSource = new CancellationTokenSource();
|
_cancellationTokenSource = new CancellationTokenSource();
|
||||||
try
|
try
|
||||||
@ -89,6 +89,6 @@ public partial class MainViewModel : ViewModelBase
|
|||||||
|
|
||||||
_cancellationTokenSource?.Dispose();
|
_cancellationTokenSource?.Dispose();
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
|
using Avalonia.Threading;
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
using CommunityToolkit.Mvvm.Input;
|
using CommunityToolkit.Mvvm.Input;
|
||||||
|
|
||||||
@ -26,7 +27,7 @@ public partial class ProgressViewModel : ObservableObject
|
|||||||
_mainModel = mainModel;
|
_mainModel = mainModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClearProgress(string name, int progressLine)
|
public void ClearProgress(string name, int progressLine) => Dispatch(() =>
|
||||||
{
|
{
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
@ -36,8 +37,9 @@ public partial class ProgressViewModel : ObservableObject
|
|||||||
NumberOfProcesses -= 1;
|
NumberOfProcesses -= 1;
|
||||||
Processes[progressLine] = new ProgressInfo("", progressLine, 0, TimeSpan.Zero, 0);
|
Processes[progressLine] = new ProgressInfo("", progressLine, 0, TimeSpan.Zero, 0);
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
public void DrawProgress(string name, int progressLine, double progress, TimeSpan eta, double speed)
|
|
||||||
|
public void DrawProgress(string name, int progressLine, double progress, TimeSpan eta, double speed) => Dispatch(() =>
|
||||||
{
|
{
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
@ -53,6 +55,18 @@ public partial class ProgressViewModel : ObservableObject
|
|||||||
NumberOfProcesses += 1;
|
NumberOfProcesses += 1;
|
||||||
Processes[progressLine] = new ProgressInfo(name, progressLine, progress, eta, speed);
|
Processes[progressLine] = new ProgressInfo(name, progressLine, progress, eta, speed);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
private void Dispatch(Action action)
|
||||||
|
{
|
||||||
|
if (Dispatcher.UIThread.CheckAccess())
|
||||||
|
{
|
||||||
|
action();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Dispatcher.UIThread.Post(() => action());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -12,7 +12,7 @@ x:DataType="vm:InspectorPaneViewModel">
|
|||||||
<StackPanel Orientation="Horizontal"
|
<StackPanel Orientation="Horizontal"
|
||||||
HorizontalAlignment="Right"
|
HorizontalAlignment="Right"
|
||||||
Spacing="8"
|
Spacing="8"
|
||||||
Margin="0,10,0,0">
|
Margin="0,0,10,0">
|
||||||
|
|
||||||
<Button Content="Apply to Selected"
|
<Button Content="Apply to Selected"
|
||||||
Command="{Binding ApplyOverridesCommand}"/>
|
Command="{Binding ApplyOverridesCommand}"/>
|
||||||
@ -103,7 +103,7 @@ x:DataType="vm:InspectorPaneViewModel">
|
|||||||
|
|
||||||
<!-- ScoreThreshold -->
|
<!-- ScoreThreshold -->
|
||||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||||
<TextBlock Text="Score Threshold" Width="120"/>
|
<TextBlock Text="Score threshold" Width="120"/>
|
||||||
|
|
||||||
<StackPanel Orientation="Vertical" Spacing="4" Width="260">
|
<StackPanel Orientation="Vertical" Spacing="4" Width="260">
|
||||||
<Slider Minimum="0"
|
<Slider Minimum="0"
|
||||||
@ -120,6 +120,25 @@ x:DataType="vm:InspectorPaneViewModel">
|
|||||||
</StackPanel>
|
</StackPanel>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
|
<!-- ScoreThreshold -->
|
||||||
|
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||||
|
<TextBlock Text="Identity matching threshold" Width="120"/>
|
||||||
|
|
||||||
|
<StackPanel Orientation="Vertical" Spacing="4" Width="260">
|
||||||
|
<Slider Minimum="0"
|
||||||
|
Maximum="1"
|
||||||
|
SmallChange="0.01"
|
||||||
|
LargeChange="0.1"
|
||||||
|
TickFrequency="0.05"
|
||||||
|
IsSnapToTickEnabled="False"
|
||||||
|
Value="{Binding Selected.IdentityThreshold, Mode=TwoWay}"/>
|
||||||
|
|
||||||
|
<TextBlock Text="{Binding Selected.IdentityThreshold, StringFormat='0.00'}"
|
||||||
|
FontSize="10"
|
||||||
|
HorizontalAlignment="Right"/>
|
||||||
|
</StackPanel>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
<!-- DetectAbove -->
|
<!-- DetectAbove -->
|
||||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||||
<TextBlock Text="Detect Above" Width="120"/>
|
<TextBlock Text="Detect Above" Width="120"/>
|
||||||
|
|||||||
@ -47,6 +47,10 @@
|
|||||||
|
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
|
<Grid ColumnDefinitions="*"
|
||||||
|
IsVisible="{Binding TransformMode}">
|
||||||
|
<views:ProgressView DataContext="{Binding Progress}"/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
</DockPanel>
|
</DockPanel>
|
||||||
</Window>
|
</Window>
|
||||||
|
|||||||
@ -49,6 +49,10 @@ public class SingleJob
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public float ScoreThreshold { get; set; } = 0.25f;
|
public float ScoreThreshold { get; set; } = 0.25f;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// Identity matching confidence threshold. This is a value between 0.0 and 1.0 that sets the minimum confidence
|
||||||
|
/// </summary>
|
||||||
|
public float IdentityThreshold { get; set; } = 0.25f;
|
||||||
|
/// <summary>
|
||||||
/// Face or human detectors should only report detections if their upper bound starts below this threshold.
|
/// Face or human detectors should only report detections if their upper bound starts below this threshold.
|
||||||
/// This is a value between 0.0 and 1.0 mapped to 0..Height.
|
/// This is a value between 0.0 and 1.0 mapped to 0..Height.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -144,6 +148,7 @@ public class SingleJob
|
|||||||
target.Debug = Debug;
|
target.Debug = Debug;
|
||||||
target.Detect = Detect;
|
target.Detect = Detect;
|
||||||
target.ScoreThreshold = ScoreThreshold;
|
target.ScoreThreshold = ScoreThreshold;
|
||||||
|
target.IdentityThreshold = IdentityThreshold;
|
||||||
target.DetectAbove = DetectAbove;
|
target.DetectAbove = DetectAbove;
|
||||||
target.DetectId = DetectId;
|
target.DetectId = DetectId;
|
||||||
target.OverrideTargetDuration = OverrideTargetDuration;
|
target.OverrideTargetDuration = OverrideTargetDuration;
|
||||||
|
|||||||
@ -9,17 +9,16 @@ public sealed class IdentityCache
|
|||||||
private sealed class Identity
|
private sealed class Identity
|
||||||
{
|
{
|
||||||
public ulong Id;
|
public ulong Id;
|
||||||
public float[] Embedding; // EMA
|
public float[] Embedding = null!; // EMA
|
||||||
public int Samples;
|
public int Samples;
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly List<Identity> _ids = new();
|
private readonly List<Identity> _ids = new();
|
||||||
private ulong _nextId = 1;
|
private ulong _nextId = 1;
|
||||||
|
|
||||||
private const float Threshold = 0.35f; // good for OSNet
|
private const float _emaAlpha = 0.2f;
|
||||||
private const float EmaAlpha = 0.2f;
|
|
||||||
|
|
||||||
public ulong ResolveId(float[] embedding)
|
public ulong ResolveId(float[] embedding, float threshold)
|
||||||
{
|
{
|
||||||
if (_ids.Count == 0)
|
if (_ids.Count == 0)
|
||||||
return CreateNew(embedding);
|
return CreateNew(embedding);
|
||||||
@ -37,7 +36,7 @@ public sealed class IdentityCache
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bestDist <= Threshold)
|
if (bestDist <= threshold)
|
||||||
{
|
{
|
||||||
UpdateEma(_ids[bestIndex].Embedding, embedding);
|
UpdateEma(_ids[bestIndex].Embedding, embedding);
|
||||||
_ids[bestIndex].Samples++;
|
_ids[bestIndex].Samples++;
|
||||||
@ -73,6 +72,6 @@ public sealed class IdentityCache
|
|||||||
private static void UpdateEma(float[] ema, float[] v)
|
private static void UpdateEma(float[] ema, float[] v)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < ema.Length; i++)
|
for (int i = 0; i < ema.Length; i++)
|
||||||
ema[i] = ema[i] * (1 - EmaAlpha) + v[i] * EmaAlpha;
|
ema[i] = ema[i] * (1 - _emaAlpha) + v[i] * _emaAlpha;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,7 +26,7 @@ public class ObjectTracker(IObjectDetector _detector, IEmbeddingExtractor _embed
|
|||||||
rect.Height = Math.Clamp(rect.Height, 1, frameMat.Height - rect.Y);
|
rect.Height = Math.Clamp(rect.Height, 1, frameMat.Height - rect.Y);
|
||||||
|
|
||||||
var embedding = _embeddingExtractor.Extract(frameMat, rect).ToArray(); // make a copy of the embedding array
|
var embedding = _embeddingExtractor.Extract(frameMat, rect).ToArray(); // make a copy of the embedding array
|
||||||
p.Id = _identityCache.ResolveId(embedding);
|
p.Id = _identityCache.ResolveId(embedding, job.Job.IdentityThreshold);
|
||||||
|
|
||||||
objects[i] = p;
|
objects[i] = p;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user