Skip to content
This repository was archived by the owner on Nov 27, 2024. It is now read-only.

Commit 5d5bf7c

Browse files
committed
Realtime ImageToImage
1 parent 5a4d599 commit 5d5bf7c

File tree

2 files changed

+105
-36
lines changed

2 files changed

+105
-36
lines changed

OnnxStack.UI/Views/ImageToImage.xaml

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -19,25 +19,24 @@
1919
<Button Content="Cancel" Command="{Binding CancelCommand}" Margin="0,0,1,0"/>
2020
<Button Content="Generate" Command="{Binding GenerateCommand}" IsEnabled="{Binding SelectedModel.IsLoaded, FallbackValue=False, TargetNullValue=False}" IsDefault="True" Margin="1,0,0,0"/>
2121
</UniformGrid>
22-
<DockPanel IsEnabled="{Binding IsGenerating, Converter={StaticResource InverseBoolConverter}}">
23-
<UniformGrid Rows="2">
24-
<DockPanel>
25-
<userControls:ModelPickerControl DockPanel.Dock="Top"
26-
UISettings="{Binding UISettings}"
27-
SupportedDiffusers="{Binding SupportedDiffusers}"
28-
SelectedModel="{Binding SelectedModel, Mode=TwoWay}" Models="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}}, Path=Models}"/>
29-
<userControls:PromptControl
30-
SelectedModel="{Binding SelectedModel}"
31-
PromptOptions="{Binding PromptOptions}"
32-
IsEnabled="{Binding SelectedModel.IsLoaded, FallbackValue=False, TargetNullValue=False}"/>
33-
</DockPanel>
34-
<userControls:SchedulerControl DockPanel.Dock="Bottom"
35-
SelectedModel="{Binding SelectedModel}"
36-
DiffuserType="ImageToImage"
37-
BatchOptions="{Binding BatchOptions}"
38-
SchedulerOptions="{Binding SchedulerOptions, Mode=TwoWay}"
39-
IsEnabled="{Binding SelectedModel.IsLoaded, FallbackValue=False, TargetNullValue=False}"
40-
Margin="0, 10, 0 ,0"/>
22+
<DockPanel>
23+
<userControls:ModelPickerControl DockPanel.Dock="Top"
24+
UISettings="{Binding UISettings}"
25+
SupportedDiffusers="{Binding SupportedDiffusers}"
26+
IsEnabled="{Binding IsGenerating, Converter={StaticResource InverseBoolConverter}}"
27+
SelectedModel="{Binding SelectedModel, Mode=TwoWay}" Models="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}}, Path=Models}"/>
28+
<UniformGrid Rows="2" IsEnabled="{Binding SelectedModel.IsLoaded, FallbackValue=False, TargetNullValue=False}">
29+
<userControls:PromptControl
30+
SelectedModel="{Binding SelectedModel}"
31+
PromptOptions="{Binding PromptOptions}"
32+
IsEnabled="{Binding IsControlsEnabled}"/>
33+
<userControls:SchedulerControl DockPanel.Dock="Bottom" Margin="0, 10, 0 ,0"
34+
SelectedModel="{Binding SelectedModel}"
35+
DiffuserType="ImageToImage"
36+
BatchOptions="{Binding BatchOptions}"
37+
SchedulerOptions="{Binding SchedulerOptions, Mode=TwoWay}"
38+
IsEnabled="{Binding IsControlsEnabled}"
39+
IsAutomationEnabled="{Binding IsGenerating, Converter={StaticResource InverseBoolConverter}}"/>
4140
</UniformGrid>
4241
</DockPanel>
4342
</DockPanel>

OnnxStack.UI/Views/ImageToImage.xaml.cs

Lines changed: 87 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ public partial class ImageToImage : UserControl, INavigatable, INotifyPropertyCh
3535
private bool _isGenerating;
3636
private int _selectedTabIndex;
3737
private bool _hasInputResult;
38+
private bool _isControlsEnabled;
3839
private ImageInput _inputImage;
3940
private ImageResult _resultImage;
4041
private ModelOptionsModel _selectedModel;
@@ -64,6 +65,7 @@ public ImageToImage()
6465
BatchOptions = new BatchOptionsModel();
6566
ImageResults = new ObservableCollection<ImageResult>();
6667
ProgressMax = SchedulerOptions.InferenceSteps;
68+
IsControlsEnabled = true;
6769
InitializeComponent();
6870
}
6971

@@ -153,6 +155,12 @@ public int SelectedTabIndex
153155
set { _selectedTabIndex = value; NotifyPropertyChanged(); }
154156
}
155157

158+
public bool IsControlsEnabled
159+
{
160+
get { return _isControlsEnabled; }
161+
set { _isControlsEnabled = value; NotifyPropertyChanged(); }
162+
}
163+
156164

157165
/// <summary>
158166
/// Called on Navigate
@@ -192,18 +200,9 @@ private async Task Generate()
192200
{
193201
HasResult = false;
194202
IsGenerating = true;
203+
IsControlsEnabled = false;
195204
ResultImage = null;
196-
var promptOptions = new PromptOptions
197-
{
198-
Prompt = PromptOptions.Prompt,
199-
NegativePrompt = PromptOptions.NegativePrompt,
200-
DiffuserType = DiffuserType.ImageToImage,
201-
InputImage = new StableDiffusion.Models.InputImage
202-
{
203-
ImageBytes = InputImage.Image.GetImageBytes()
204-
}
205-
};
206-
205+
var promptOptions = GetPromptOptions(PromptOptions, InputImage);
207206
var batchOptions = BatchOptions.ToBatchOptions();
208207
var schedulerOptions = SchedulerOptions.ToSchedulerOptions();
209208

@@ -214,8 +213,11 @@ private async Task Generate()
214213
if (resultImage != null)
215214
{
216215
ResultImage = resultImage;
217-
ImageResults.Add(resultImage);
218216
HasResult = true;
217+
if (BatchOptions.IsAutomationEnabled && BatchOptions.DisableHistory)
218+
continue;
219+
220+
ImageResults.Add(resultImage);
219221
}
220222
}
221223
}
@@ -241,7 +243,7 @@ private async Task Generate()
241243
private bool CanExecuteGenerate()
242244
{
243245
return !IsGenerating
244-
&& !string.IsNullOrEmpty(PromptOptions.Prompt)
246+
&& !string.IsNullOrEmpty(PromptOptions.Prompt)
245247
&& HasInputResult;
246248
}
247249

@@ -298,6 +300,7 @@ private bool CanExecuteClearHistory()
298300
private void Reset()
299301
{
300302
IsGenerating = false;
303+
IsControlsEnabled = true;
301304
ProgressValue = 0;
302305
}
303306

@@ -312,6 +315,9 @@ private void Reset()
312315
/// <returns></returns>
313316
private async IAsyncEnumerable<ImageResult> ExecuteStableDiffusion(IModelOptions modelOptions, PromptOptions promptOptions, SchedulerOptions schedulerOptions, BatchOptions batchOptions)
314317
{
318+
if (!IsExecuteOptionsValid(PromptOptions))
319+
yield break;
320+
315321
_cancelationTokenSource = new CancellationTokenSource();
316322
if (!BatchOptions.IsAutomationEnabled)
317323
{
@@ -321,15 +327,61 @@ private async IAsyncEnumerable<ImageResult> ExecuteStableDiffusion(IModelOptions
321327
}
322328
else
323329
{
324-
var timestamp = Stopwatch.GetTimestamp();
325-
await foreach (var batchResult in _stableDiffusionService.GenerateBatchAsync(modelOptions, promptOptions, schedulerOptions, batchOptions, ProgressBatchCallback(), _cancelationTokenSource.Token))
330+
if (_batchOptions.BatchType != BatchOptionType.Realtime)
331+
{
332+
var timestamp = Stopwatch.GetTimestamp();
333+
await foreach (var batchResult in _stableDiffusionService.GenerateBatchAsync(modelOptions, promptOptions, schedulerOptions, batchOptions, ProgressBatchCallback(), _cancelationTokenSource.Token))
334+
{
335+
yield return await GenerateResultAsync(batchResult.ImageResult.ToImageBytes(), promptOptions, batchResult.SchedulerOptions, timestamp);
336+
timestamp = Stopwatch.GetTimestamp();
337+
}
338+
yield break;
339+
}
340+
341+
// Realtime Diffusion
342+
IsControlsEnabled = true;
343+
while (!_cancelationTokenSource.IsCancellationRequested)
326344
{
327-
yield return await GenerateResultAsync(batchResult.ImageResult.ToImageBytes(), promptOptions, batchResult.SchedulerOptions, timestamp);
328-
timestamp = Stopwatch.GetTimestamp();
345+
var refreshTimestamp = Stopwatch.GetTimestamp();
346+
if (SchedulerOptions.HasChanged || PromptOptions.HasChanged)
347+
{
348+
PromptOptions.HasChanged = false;
349+
SchedulerOptions.HasChanged = false;
350+
var realtimePromptOptions = GetPromptOptions(PromptOptions, InputImage);
351+
var realtimeSchedulerOptions = SchedulerOptions.ToSchedulerOptions();
352+
353+
var timestamp = Stopwatch.GetTimestamp();
354+
var result = await _stableDiffusionService.GenerateAsBytesAsync(modelOptions, realtimePromptOptions, realtimeSchedulerOptions, RealtimeProgressCallback(), _cancelationTokenSource.Token);
355+
yield return await GenerateResultAsync(result, promptOptions, schedulerOptions, timestamp);
356+
}
357+
await Utils.RefreshDelay(refreshTimestamp, BatchOptions.RealtimeRefreshRate, _cancelationTokenSource.Token);
329358
}
330359
}
331360
}
332361

362+
private bool IsExecuteOptionsValid(PromptOptionsModel prompt)
363+
{
364+
if (string.IsNullOrEmpty(prompt.Prompt))
365+
return false;
366+
367+
return true;
368+
}
369+
370+
371+
private PromptOptions GetPromptOptions(PromptOptionsModel promptOptionsModel, ImageInput imageInput)
372+
{
373+
return new PromptOptions
374+
{
375+
Prompt = promptOptionsModel.Prompt,
376+
NegativePrompt = promptOptionsModel.NegativePrompt,
377+
DiffuserType = DiffuserType.ImageToImage,
378+
InputImage = new StableDiffusion.Models.InputImage
379+
{
380+
ImageBytes = imageInput.Image.GetImageBytes()
381+
}
382+
};
383+
}
384+
333385

334386
/// <summary>
335387
/// Generates the result.
@@ -404,6 +456,24 @@ private Action<int, int, int, int> ProgressBatchCallback()
404456
};
405457
}
406458

459+
private Action<int, int> RealtimeProgressCallback()
460+
{
461+
return (value, maximum) =>
462+
{
463+
App.UIInvoke(() =>
464+
{
465+
if (_cancelationTokenSource.IsCancellationRequested)
466+
return;
467+
468+
if (BatchOptions.StepValue != value)
469+
BatchOptions.StepValue = value;
470+
if (BatchOptions.StepsValue != maximum)
471+
BatchOptions.StepsValue = maximum;
472+
});
473+
};
474+
}
475+
476+
407477
#region INotifyPropertyChanged
408478
public event PropertyChangedEventHandler PropertyChanged;
409479
public void NotifyPropertyChanged([CallerMemberName] string property = "")

0 commit comments

Comments
 (0)