diff --git a/OnnxStack.Core/Config/OnnxModelType.cs b/OnnxStack.Core/Config/OnnxModelType.cs index f8adfc74..ffd3420f 100644 --- a/OnnxStack.Core/Config/OnnxModelType.cs +++ b/OnnxStack.Core/Config/OnnxModelType.cs @@ -8,6 +8,7 @@ public enum OnnxModelType TextEncoder = 20, TextEncoder2 = 21, VaeEncoder = 30, - VaeDecoder = 40 + VaeDecoder = 40, + Upscaler = 1000 } } diff --git a/OnnxStack.ImageUpscaler/Config/UpscaleModelSet.cs b/OnnxStack.ImageUpscaler/Config/UpscaleModelSet.cs index 5a7ba714..febe79e9 100644 --- a/OnnxStack.ImageUpscaler/Config/UpscaleModelSet.cs +++ b/OnnxStack.ImageUpscaler/Config/UpscaleModelSet.cs @@ -4,7 +4,7 @@ namespace OnnxStack.StableDiffusion.Config { - public class UpscaleModelSet : IOnnxModelSetConfig + public record UpscaleModelSet : IOnnxModelSetConfig { public string Name { get; set; } public int Channels { get; set; } diff --git a/OnnxStack.ImageUpscaler/Services/IUpscaleService.cs b/OnnxStack.ImageUpscaler/Services/IUpscaleService.cs index 1b4fba95..4600e59c 100644 --- a/OnnxStack.ImageUpscaler/Services/IUpscaleService.cs +++ b/OnnxStack.ImageUpscaler/Services/IUpscaleService.cs @@ -46,7 +46,6 @@ public interface IUpscaleService /// Task LoadModelAsync(UpscaleModelSet model); - /// /// Unloads the model. /// @@ -54,6 +53,14 @@ public interface IUpscaleService /// Task UnloadModelAsync(UpscaleModelSet model); + /// + /// Determines whether [is model loaded] [the specified model options]. + /// + /// The model options. + /// + /// true if [is model loaded] [the specified model options]; otherwise, false. + /// + bool IsModelLoaded(UpscaleModelSet modelOptions); /// /// Generates the upscaled image. diff --git a/OnnxStack.ImageUpscaler/Services/UpscaleService.cs b/OnnxStack.ImageUpscaler/Services/UpscaleService.cs index eb2e6254..fd2d08c5 100644 --- a/OnnxStack.ImageUpscaler/Services/UpscaleService.cs +++ b/OnnxStack.ImageUpscaler/Services/UpscaleService.cs @@ -124,6 +124,20 @@ public async Task UnloadModelAsync(UpscaleModelSet model) } + /// + /// Determines whether [is model loaded] [the specified model options]. + /// + /// The model options. + /// + /// true if [is model loaded] [the specified model options]; otherwise, false. + /// + /// + public bool IsModelLoaded(UpscaleModelSet modelOptions) + { + return _modelService.IsModelLoaded(modelOptions); + } + + /// /// Generates the upscaled image. /// @@ -191,7 +205,7 @@ private async Task> GenerateInternalAsync(UpscaleModelSet modelSet using (var image = inputImage.ToImage()) { var upscaleInput = CreateInputParams(image, modelSet.SampleSize, modelSet.ScaleFactor); - var metadata = _modelService.GetModelMetadata(modelSet, OnnxModelType.Unet); + var metadata = _modelService.GetModelMetadata(modelSet, OnnxModelType.Upscaler); var outputResult = new Image(upscaleInput.OutputWidth, upscaleInput.OutputHeight); foreach (var tile in upscaleInput.ImageTiles) @@ -205,7 +219,7 @@ private async Task> GenerateInternalAsync(UpscaleModelSet modelSet inferenceParameters.AddInputTensor(inputTensor); inferenceParameters.AddOutputBuffer(outputDimension); - var results = await _modelService.RunInferenceAsync(modelSet, OnnxModelType.Unet, inferenceParameters); + var results = await _modelService.RunInferenceAsync(modelSet, OnnxModelType.Upscaler, inferenceParameters); using (var result = results.First()) { outputResult.Mutate(x => x.DrawImage(result.ToImage(), tile.Destination.Location, 1f)); @@ -231,5 +245,6 @@ private UpscaleInput CreateInputParams(Image imageSource, int maxTileSiz var height = imageSource.Height * scaleFactor; return new UpscaleInput(tiles, width, height); } + } } \ No newline at end of file diff --git a/OnnxStack.StableDiffusion/Config/StableDiffusionModelSet.cs b/OnnxStack.StableDiffusion/Config/StableDiffusionModelSet.cs index 6ccf1460..5fb61c5f 100644 --- a/OnnxStack.StableDiffusion/Config/StableDiffusionModelSet.cs +++ b/OnnxStack.StableDiffusion/Config/StableDiffusionModelSet.cs @@ -8,7 +8,7 @@ namespace OnnxStack.StableDiffusion.Config { - public class StableDiffusionModelSet : IOnnxModelSetConfig + public record StableDiffusionModelSet : IOnnxModelSetConfig { public string Name { get; set; } public bool IsEnabled { get; set; } diff --git a/OnnxStack.StableDiffusion/Enums/DiffuserType.cs b/OnnxStack.StableDiffusion/Enums/DiffuserType.cs index f759bdc8..96a127f1 100644 --- a/OnnxStack.StableDiffusion/Enums/DiffuserType.cs +++ b/OnnxStack.StableDiffusion/Enums/DiffuserType.cs @@ -1,11 +1,22 @@ -namespace OnnxStack.StableDiffusion.Enums +using System.ComponentModel; + +namespace OnnxStack.StableDiffusion.Enums { public enum DiffuserType { + [Description("Text To Image")] TextToImage = 0, + + [Description("Image To Image")] ImageToImage = 1, + + [Description("Image Inpaint")] ImageInpaint = 2, + + [Description("Image Inpaint Legacy")] ImageInpaintLegacy = 3, + + [Description("Image To Animation")] ImageToAnimation = 4 } } diff --git a/OnnxStack.UI/App.xaml b/OnnxStack.UI/App.xaml index 038a9c28..5c4b7c5b 100644 --- a/OnnxStack.UI/App.xaml +++ b/OnnxStack.UI/App.xaml @@ -2,8 +2,9 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=mscorlib" + xmlns:componentModel="clr-namespace:System.ComponentModel;assembly=System.ComponentModel.TypeConverter" xmlns:theme="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero2" - xmlns:local="clr-namespace:OnnxStack.UI" + xmlns:local="clr-namespace:OnnxStack.UI" xmlns:SD_Enums="clr-namespace:OnnxStack.StableDiffusion.Enums;assembly=OnnxStack.StableDiffusion" xmlns:userControls="clr-namespace:OnnxStack.UI.UserControls" xmlns:behaviors="clr-namespace:OnnxStack.UI.Behaviors" @@ -25,7 +26,8 @@ pack://application:,,,/Fonts/fa-regular-400.ttf#Font Awesome 5 Pro Regular pack://application:,,,/Fonts/fa-solid-900.ttf#Font Awesome 5 Pro Solid - + True + False @@ -35,6 +37,14 @@ + + + + + + + + @@ -42,6 +52,18 @@ + + + + + + + + + + + + @@ -106,7 +128,7 @@ - + @@ -233,8 +255,8 @@ - - + @@ -260,7 +285,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -722,14 +795,15 @@ - - - - - - - - + diff --git a/OnnxStack.UI/App.xaml.cs b/OnnxStack.UI/App.xaml.cs index 62de9235..6310ef46 100644 --- a/OnnxStack.UI/App.xaml.cs +++ b/OnnxStack.UI/App.xaml.cs @@ -2,6 +2,7 @@ using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using OnnxStack.Core; +using OnnxStack.ImageUpscaler; using OnnxStack.UI.Dialogs; using OnnxStack.UI.Models; using OnnxStack.UI.Services; @@ -26,6 +27,7 @@ public App() // Add OnnxStackStableDiffusion builder.Services.AddOnnxStackStableDiffusion(); + builder.Services.AddOnnxStackImageUpscaler(); builder.Services.AddOnnxStackConfig(); // Add Windows @@ -34,6 +36,14 @@ public App() builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); + builder.Services.AddTransient(); + builder.Services.AddTransient(); + builder.Services.AddTransient(); + builder.Services.AddTransient(); + builder.Services.AddTransient(); + builder.Services.AddTransient(); + builder.Services.AddTransient (); + builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); diff --git a/OnnxStack.UI/Converters/ComboBoxAllItemConverter.cs b/OnnxStack.UI/Converters/ComboBoxAllItemConverter.cs new file mode 100644 index 00000000..8ffda443 --- /dev/null +++ b/OnnxStack.UI/Converters/ComboBoxAllItemConverter.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Windows.Data; + +namespace OnnxStack.UI.Converters +{ + public class ComboBoxAllItemConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + IEnumerable container = value as IEnumerable; + if (container != null) + { + IEnumerable genericContainer = container.OfType(); + IEnumerable emptyItem = new object[] { "All" }; + return emptyItem.Concat(genericContainer); + } + + return value; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + return value is string str && str == "All" ? null : value; + } + } +} diff --git a/OnnxStack.UI/Converters/EnumDescriptionConverter.cs b/OnnxStack.UI/Converters/EnumDescriptionConverter.cs new file mode 100644 index 00000000..6bb5d7b3 --- /dev/null +++ b/OnnxStack.UI/Converters/EnumDescriptionConverter.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Globalization; +using System.Reflection; +using System.Text; +using System.Windows.Data; + +namespace OnnxStack.UI.Converters +{ + public class EnumDescriptionConverter : IValueConverter + { + private string GetEnumDescription(Enum enumObj) + { + FieldInfo fieldInfo = enumObj.GetType().GetField(enumObj.ToString()); + object[] attribArray = fieldInfo.GetCustomAttributes(false); + + if (attribArray.Length == 0) + return enumObj.ToString(); + else + { + DescriptionAttribute attrib = null; + + foreach (var att in attribArray) + { + if (att is DescriptionAttribute) + attrib = att as DescriptionAttribute; + } + + if (attrib != null) + return attrib.Description; + + return enumObj.ToString(); + } + } + + object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value is not Enum myEnum) + return value; + + string description = GetEnumDescription(myEnum); + return description; + } + + object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + return string.Empty; + } + } +} diff --git a/OnnxStack.UI/Dialogs/AddModelDialog.xaml b/OnnxStack.UI/Dialogs/AddModelDialog.xaml index f233ae8e..dc7dc77c 100644 --- a/OnnxStack.UI/Dialogs/AddModelDialog.xaml +++ b/OnnxStack.UI/Dialogs/AddModelDialog.xaml @@ -3,38 +3,88 @@ 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:OnnxStack.UI.Dialogs" + xmlns:models="clr-namespace:OnnxStack.UI.Models" + xmlns:userControls="clr-namespace:OnnxStack.UI.UserControls" mc:Ignorable="d" Name="UI" Icon="/Images/Icon.png" - MinWidth="400" + MinWidth="500" SizeToContent="WidthAndHeight" WindowStartupLocation="CenterOwner" SnapsToDevicePixels="True" UseLayoutRounding="True" Style="{StaticResource BaseWindow}" - ContentRendered="OnContentRendered"> + ContentRendered="OnContentRendered" + Title="Add StableDiffusion Model"> - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + diff --git a/OnnxStack.UI/UserControls/ModelPickerControl.xaml b/OnnxStack.UI/UserControls/ModelPickerControl.xaml index 18b5a6b7..0d0ebd60 100644 --- a/OnnxStack.UI/UserControls/ModelPickerControl.xaml +++ b/OnnxStack.UI/UserControls/ModelPickerControl.xaml @@ -49,30 +49,18 @@ - - - - - - + + + + + + + diff --git a/OnnxStack.UI/UserControls/ModelPickerControl.xaml.cs b/OnnxStack.UI/UserControls/ModelPickerControl.xaml.cs index 5a0d2060..f6a2d284 100644 --- a/OnnxStack.UI/UserControls/ModelPickerControl.xaml.cs +++ b/OnnxStack.UI/UserControls/ModelPickerControl.xaml.cs @@ -1,5 +1,4 @@ using Microsoft.Extensions.Logging; -using Models; using OnnxStack.Core; using OnnxStack.StableDiffusion.Common; using OnnxStack.StableDiffusion.Enums; @@ -7,13 +6,13 @@ using OnnxStack.UI.Models; using System; using System.Collections.Generic; -using System.Collections.ObjectModel; using System.ComponentModel; using System.Linq; using System.Runtime.CompilerServices; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; +using System.Windows.Data; namespace OnnxStack.UI.UserControls { @@ -24,6 +23,7 @@ public partial class ModelPickerControl : UserControl, INotifyPropertyChanged { private readonly ILogger _logger; private readonly IStableDiffusionService _stableDiffusionService; + private ICollectionView _modelCollectionView; /// Initializes a new instance of the class. public ModelPickerControl() @@ -42,28 +42,17 @@ public ModelPickerControl() public AsyncRelayCommand LoadCommand { get; set; } public AsyncRelayCommand UnloadCommand { get; set; } - - /// - /// Gets or sets the models. - /// - public ObservableCollection Models - { - get { return (ObservableCollection)GetValue(ModelsProperty); } - set { SetValue(ModelsProperty, value); } - } - public static readonly DependencyProperty ModelsProperty = - DependencyProperty.Register("Models", typeof(ObservableCollection), typeof(ModelPickerControl), new PropertyMetadata(propertyChangedCallback: OnModelsChanged)); - - public OnnxStackUIConfig UISettings { get { return (OnnxStackUIConfig)GetValue(UISettingsProperty); } set { SetValue(UISettingsProperty, value); } } public static readonly DependencyProperty UISettingsProperty = - DependencyProperty.Register("UISettings", typeof(OnnxStackUIConfig), typeof(ModelPickerControl)); - - + DependencyProperty.Register("UISettings", typeof(OnnxStackUIConfig), typeof(ModelPickerControl), new PropertyMetadata((d, e) => + { + if (d is ModelPickerControl control && e.NewValue is OnnxStackUIConfig settings) + control.InitializeModels(); + })); /// /// Gets or sets the supported diffusers. @@ -74,28 +63,50 @@ public List SupportedDiffusers set { SetValue(SupportedDiffusersProperty, value); } } public static readonly DependencyProperty SupportedDiffusersProperty = - DependencyProperty.Register("SupportedDiffusers", typeof(List), typeof(ModelPickerControl)); - + DependencyProperty.Register("SupportedDiffusers", typeof(List), typeof(ModelPickerControl), new PropertyMetadata((d, e) => + { + if (d is ModelPickerControl control && e.NewValue is List diffusers) + control.ModelCollectionView?.Refresh(); + })); /// /// Gets or sets the selected model. /// - public ModelOptionsModel SelectedModel + public StableDiffusionModelSetViewModel SelectedModel { - get { return (ModelOptionsModel)GetValue(SelectedModelProperty); } + get { return (StableDiffusionModelSetViewModel)GetValue(SelectedModelProperty); } set { SetValue(SelectedModelProperty, value); } } public static readonly DependencyProperty SelectedModelProperty = - DependencyProperty.Register("SelectedModel", typeof(ModelOptionsModel), typeof(ModelPickerControl)); + DependencyProperty.Register("SelectedModel", typeof(StableDiffusionModelSetViewModel), typeof(ModelPickerControl)); + public ICollectionView ModelCollectionView + { + get { return _modelCollectionView; } + set { _modelCollectionView = value; NotifyPropertyChanged(); } + } + + + private void InitializeModels() + { + ModelCollectionView = new ListCollectionView(UISettings.StableDiffusionModelSets); + ModelCollectionView.Filter = (obj) => + { + if (obj is not StableDiffusionModelSetViewModel viewModel) + return false; + + return viewModel.ModelSet.Diffusers.Intersect(SupportedDiffusers).Any(); + }; + } + /// /// Loads the model. /// private async Task LoadModel() { - if (_stableDiffusionService.IsModelLoaded(SelectedModel.ModelOptions)) + if (_stableDiffusionService.IsModelLoaded(SelectedModel.ModelSet)) return; var elapsed = _logger.LogBegin($"'{SelectedModel.Name}' Loading..."); @@ -106,15 +117,18 @@ private async Task LoadModel() { if (UISettings.ModelCacheMode == ModelCacheMode.Single) { - foreach (var model in Models.Where(x => x.IsLoaded)) + foreach (var model in UISettings.StableDiffusionModelSets.Where(x => x.IsLoaded)) { _logger.LogInformation($"'{model.Name}' Unloading..."); - await _stableDiffusionService.UnloadModelAsync(model.ModelOptions); + await _stableDiffusionService.UnloadModelAsync(model.ModelSet); model.IsLoaded = false; } } - SelectedModel.IsLoaded = await _stableDiffusionService.LoadModelAsync(SelectedModel.ModelOptions); + SelectedModel.ModelSet.InitBlankTokenArray(); + SelectedModel.ModelSet.ApplyConfigurationOverrides(); + await _stableDiffusionService.AddModelAsync(SelectedModel.ModelSet); + SelectedModel.IsLoaded = await _stableDiffusionService.LoadModelAsync(SelectedModel.ModelSet); } catch (Exception ex) { @@ -131,33 +145,17 @@ private async Task LoadModel() /// private async Task UnloadModel() { - if (!_stableDiffusionService.IsModelLoaded(SelectedModel.ModelOptions)) + if (!_stableDiffusionService.IsModelLoaded(SelectedModel.ModelSet)) return; _logger.LogInformation($"'{SelectedModel.Name}' Unloading..."); SelectedModel.IsLoading = true; - await _stableDiffusionService.UnloadModelAsync(SelectedModel.ModelOptions); + await _stableDiffusionService.UnloadModelAsync(SelectedModel.ModelSet); SelectedModel.IsLoading = false; SelectedModel.IsLoaded = false; _logger.LogInformation($"'{SelectedModel.Name}' Unloaded."); } - - /// - /// Called when the Models source collection has changes, via Settings most likely. - /// - /// The owner. - /// The instance containing the event data. - private static void OnModelsChanged(DependencyObject owner, DependencyPropertyChangedEventArgs e) - { - if (owner is ModelPickerControl control) - { - control.SelectedModel = control.Models - .Where(x => control.SupportedDiffusers.Any(x.ModelOptions.Diffusers.Contains)) - .FirstOrDefault(x => x.ModelOptions.IsEnabled); - } - } - #region INotifyPropertyChanged public event PropertyChangedEventHandler PropertyChanged; public void NotifyPropertyChanged([CallerMemberName] string property = "") diff --git a/OnnxStack.UI/UserControls/PromptControl.xaml.cs b/OnnxStack.UI/UserControls/PromptControl.xaml.cs index 8650b292..76eb5ecd 100644 --- a/OnnxStack.UI/UserControls/PromptControl.xaml.cs +++ b/OnnxStack.UI/UserControls/PromptControl.xaml.cs @@ -47,14 +47,14 @@ public PromptOptionsModel PromptOptions DependencyProperty.Register("PromptOptions", typeof(PromptOptionsModel), typeof(PromptControl)); - public ModelOptionsModel SelectedModel + public StableDiffusionModelSetViewModel SelectedModel { - get { return (ModelOptionsModel)GetValue(SelectedModelProperty); } + get { return (StableDiffusionModelSetViewModel)GetValue(SelectedModelProperty); } set { SetValue(SelectedModelProperty, value); } } public static readonly DependencyProperty SelectedModelProperty = - DependencyProperty.Register("SelectedModel", typeof(ModelOptionsModel), typeof(PromptControl)); + DependencyProperty.Register("SelectedModel", typeof(StableDiffusionModelSetViewModel), typeof(PromptControl)); /// diff --git a/OnnxStack.UI/UserControls/SchedulerControl.xaml.cs b/OnnxStack.UI/UserControls/SchedulerControl.xaml.cs index e045991a..426473c8 100644 --- a/OnnxStack.UI/UserControls/SchedulerControl.xaml.cs +++ b/OnnxStack.UI/UserControls/SchedulerControl.xaml.cs @@ -20,7 +20,6 @@ namespace OnnxStack.UI.UserControls /// public partial class SchedulerControl : UserControl, INotifyPropertyChanged { - private SchedulerOptionsConfig _optionsConfig = new(); private ObservableCollection _schedulerTypes = new(); /// Initializes a new instance of the class. @@ -47,16 +46,16 @@ public ObservableCollection SchedulerTypes /// /// Gets or sets the selected model. /// - public ModelOptionsModel SelectedModel + public StableDiffusionModelSetViewModel SelectedModel { - get { return (ModelOptionsModel)GetValue(SelectedModelProperty); } + get { return (StableDiffusionModelSetViewModel)GetValue(SelectedModelProperty); } set { SetValue(SelectedModelProperty, value); } } public static readonly DependencyProperty SelectedModelProperty = - DependencyProperty.Register("SelectedModel", typeof(ModelOptionsModel), typeof(SchedulerControl), new PropertyMetadata((d, e) => + DependencyProperty.Register("SelectedModel", typeof(StableDiffusionModelSetViewModel), typeof(SchedulerControl), new PropertyMetadata((d, e) => { if (d is SchedulerControl schedulerControl) - schedulerControl.OnModelChanged(e.NewValue as ModelOptionsModel); + schedulerControl.OnModelChanged(e.NewValue as StableDiffusionModelSetViewModel); })); @@ -112,47 +111,36 @@ public bool IsGenerating - - /// - /// Gets or sets the options configuration. - /// - public SchedulerOptionsConfig OptionsConfig - { - get { return _optionsConfig; } - set { _optionsConfig = value; NotifyPropertyChanged(); } - } - - /// /// Called when the selected model has changed. /// /// The model options model. - private void OnModelChanged(ModelOptionsModel model) + private void OnModelChanged(StableDiffusionModelSetViewModel model) { if (model is null) return; SchedulerTypes.Clear(); - foreach (SchedulerType type in model.ModelOptions.PipelineType.GetSchedulerTypes()) + foreach (SchedulerType type in model.ModelSet.PipelineType.GetSchedulerTypes()) SchedulerTypes.Add(type); SchedulerOptions.Width = 512; SchedulerOptions.Height = 512; - if (model.ModelOptions.PipelineType == DiffuserPipelineType.StableDiffusion) + if (model.ModelSet.PipelineType == DiffuserPipelineType.StableDiffusion) { SchedulerOptions.OriginalInferenceSteps = 100; SchedulerOptions.InferenceSteps = 30; SchedulerOptions.GuidanceScale = 7.5f; SchedulerOptions.SchedulerType = SchedulerType.DDIM; } - else if (model.ModelOptions.PipelineType == DiffuserPipelineType.LatentConsistency) + else if (model.ModelSet.PipelineType == DiffuserPipelineType.LatentConsistency) { SchedulerOptions.OriginalInferenceSteps = 50; SchedulerOptions.InferenceSteps = 6; SchedulerOptions.GuidanceScale = 1f; SchedulerOptions.SchedulerType = SchedulerType.LCM; } - else if (model.ModelOptions.PipelineType == DiffuserPipelineType.LatentConsistencyXL) + else if (model.ModelSet.PipelineType == DiffuserPipelineType.LatentConsistencyXL) { SchedulerOptions.OriginalInferenceSteps = 50; SchedulerOptions.InferenceSteps = 6; @@ -161,13 +149,13 @@ private void OnModelChanged(ModelOptionsModel model) SchedulerOptions.Height = 1024; SchedulerOptions.SchedulerType = SchedulerType.LCM; } - else if (model.ModelOptions.PipelineType == DiffuserPipelineType.InstaFlow) + else if (model.ModelSet.PipelineType == DiffuserPipelineType.InstaFlow) { SchedulerOptions.InferenceSteps = 1; SchedulerOptions.GuidanceScale = 0f; SchedulerOptions.SchedulerType = SchedulerType.InstaFlow; } - else if (model.ModelOptions.PipelineType == DiffuserPipelineType.StableDiffusionXL) + else if (model.ModelSet.PipelineType == DiffuserPipelineType.StableDiffusionXL) { SchedulerOptions.OriginalInferenceSteps = 100; SchedulerOptions.InferenceSteps = 30; @@ -186,7 +174,7 @@ private void ResetParameters() { SchedulerOptions = new SchedulerOptionsModel { - SchedulerType = SelectedModel.ModelOptions.PipelineType.GetSchedulerTypes().First() + SchedulerType = SelectedModel.ModelSet.PipelineType.GetSchedulerTypes().First() }; } diff --git a/OnnxStack.UI/UserControls/UpscalePickerControl.xaml b/OnnxStack.UI/UserControls/UpscalePickerControl.xaml new file mode 100644 index 00000000..e0186973 --- /dev/null +++ b/OnnxStack.UI/UserControls/UpscalePickerControl.xaml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/OnnxStack.UI/UserControls/UpscalePickerControl.xaml.cs b/OnnxStack.UI/UserControls/UpscalePickerControl.xaml.cs new file mode 100644 index 00000000..5aef6142 --- /dev/null +++ b/OnnxStack.UI/UserControls/UpscalePickerControl.xaml.cs @@ -0,0 +1,125 @@ +using Microsoft.Extensions.Logging; +using OnnxStack.Core; +using OnnxStack.ImageUpscaler.Services; +using OnnxStack.UI.Commands; +using OnnxStack.UI.Models; +using System; +using System.ComponentModel; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; + +namespace OnnxStack.UI.UserControls +{ + /// + /// Interaction logic for UpscalePickerControl.xaml + /// + public partial class UpscalePickerControl : UserControl, INotifyPropertyChanged + { + private readonly ILogger _logger; + private readonly IUpscaleService _upscaleService; + + /// Initializes a new instance of the class. + public UpscalePickerControl() + { + if (!DesignerProperties.GetIsInDesignMode(this)) + { + _logger = App.GetService>(); + _upscaleService = App.GetService(); + } + + LoadCommand = new AsyncRelayCommand(LoadModel); + UnloadCommand = new AsyncRelayCommand(UnloadModel); + InitializeComponent(); + } + + public AsyncRelayCommand LoadCommand { get; set; } + public AsyncRelayCommand UnloadCommand { get; set; } + + public OnnxStackUIConfig UISettings + { + get { return (OnnxStackUIConfig)GetValue(UISettingsProperty); } + set { SetValue(UISettingsProperty, value); } + } + public static readonly DependencyProperty UISettingsProperty = + DependencyProperty.Register("UISettings", typeof(OnnxStackUIConfig), typeof(UpscalePickerControl)); + + + /// + /// Gets or sets the selected model. + /// + public UpscaleModelSetViewModel SelectedModel + { + get { return (UpscaleModelSetViewModel)GetValue(SelectedModelProperty); } + set { SetValue(SelectedModelProperty, value); } + } + public static readonly DependencyProperty SelectedModelProperty = + DependencyProperty.Register("SelectedModel", typeof(UpscaleModelSetViewModel), typeof(UpscalePickerControl)); + + + + /// + /// Loads the model. + /// + private async Task LoadModel() + { + if (_upscaleService.IsModelLoaded(SelectedModel.ModelSet)) + return; + + var elapsed = _logger.LogBegin($"'{SelectedModel.Name}' Loading..."); + SelectedModel.IsLoaded = false; + SelectedModel.IsLoading = true; + + try + { + if (UISettings.ModelCacheMode == ModelCacheMode.Single) + { + foreach (var model in UISettings.UpscaleModelSets.Where(x => x.IsLoaded)) + { + _logger.LogInformation($"'{model.Name}' Unloading..."); + await _upscaleService.UnloadModelAsync(model.ModelSet); + model.IsLoaded = false; + } + } + + SelectedModel.ModelSet.ApplyConfigurationOverrides(); + await _upscaleService.AddModelAsync(SelectedModel.ModelSet); + SelectedModel.IsLoaded = await _upscaleService.LoadModelAsync(SelectedModel.ModelSet); + } + catch (Exception ex) + { + _logger.LogError($"An error occured while loading model '{SelectedModel.Name}' \n {ex}"); + } + + SelectedModel.IsLoading = false; + _logger.LogEnd($"'{SelectedModel.Name}' Loaded.", elapsed); + } + + + /// + /// Unloads the model. + /// + private async Task UnloadModel() + { + if (!_upscaleService.IsModelLoaded(SelectedModel.ModelSet)) + return; + + _logger.LogInformation($"'{SelectedModel.Name}' Unloading..."); + SelectedModel.IsLoading = true; + await _upscaleService.UnloadModelAsync(SelectedModel.ModelSet); + SelectedModel.IsLoading = false; + SelectedModel.IsLoaded = false; + _logger.LogInformation($"'{SelectedModel.Name}' Unloaded."); + } + + #region INotifyPropertyChanged + public event PropertyChangedEventHandler PropertyChanged; + public void NotifyPropertyChanged([CallerMemberName] string property = "") + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property)); + } + #endregion + } +} diff --git a/OnnxStack.UI/Utils.cs b/OnnxStack.UI/Utils.cs index 1d99f9e7..b1079c72 100644 --- a/OnnxStack.UI/Utils.cs +++ b/OnnxStack.UI/Utils.cs @@ -3,9 +3,11 @@ using OnnxStack.StableDiffusion.Enums; using OnnxStack.UI.Models; using System; +using System.Collections.ObjectModel; using System.Diagnostics; using System.IO; using System.Reflection; +using System.Runtime; using System.Text.Json; using System.Text.Json.Serialization; using System.Threading; @@ -49,13 +51,12 @@ public static byte[] GetImageBytes(this BitmapSource image) } } - - public static async Task SaveImageFileAsync(this ImageResult imageResult, string filename) + public static async Task SaveImageFileAsync(this BitmapSource image, string filename) { await Task.Run(() => { var encoder = new PngBitmapEncoder(); - encoder.Frames.Add(BitmapFrame.Create(imageResult.Image)); + encoder.Frames.Add(BitmapFrame.Create(image)); using (var fileStream = new FileStream(filename, FileMode.Create)) { encoder.Save(fileStream); @@ -88,7 +89,7 @@ public static async Task AutoSaveAsync(this ImageResult imageResult, strin var random = RandomString(); var imageFile = Path.Combine(autosaveDirectory, $"image-{imageResult.SchedulerOptions.Seed}-{random}.png"); var blueprintFile = Path.Combine(autosaveDirectory, $"image-{imageResult.SchedulerOptions.Seed}-{random}.json"); - if (!await imageResult.SaveImageFileAsync(imageFile)) + if (!await imageResult.Image.SaveImageFileAsync(imageFile)) return false; if (includeBlueprint) @@ -209,5 +210,17 @@ public static void LogToWindow(string message) (System.Windows.Application.Current.MainWindow as MainWindow).UpdateOutputLog(message); })); } + + + /// + /// Forces the notify collection changed event. + /// + /// + /// The collection. + public static void ForceNotifyCollectionChanged(this ObservableCollection collection) + { + // Hack: Moving an item will invoke a collection changed event + collection?.Move(0, 0); + } } } diff --git a/OnnxStack.UI/Views/ImageInpaintView.xaml b/OnnxStack.UI/Views/ImageInpaintView.xaml index 1dce3887..bffbfe56 100644 --- a/OnnxStack.UI/Views/ImageInpaintView.xaml +++ b/OnnxStack.UI/Views/ImageInpaintView.xaml @@ -24,7 +24,7 @@ UISettings="{Binding UISettings}" SupportedDiffusers="{Binding SupportedDiffusers}" IsEnabled="{Binding IsGenerating, Converter={StaticResource InverseBoolConverter}}" - SelectedModel="{Binding SelectedModel, Mode=TwoWay}" Models="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}}, Path=Models}"/> + SelectedModel="{Binding SelectedModel, Mode=TwoWay}"/> ImageResults { get; } - public ModelOptionsModel SelectedModel + public StableDiffusionModelSetViewModel SelectedModel { get { return _selectedModel; } set { _selectedModel = value; NotifyPropertyChanged(); } @@ -193,8 +193,8 @@ public async Task NavigateAsync(ImageResult imageResult) InputImageMask = null; HasInputResult = true; HasInputMaskResult = false; - if (imageResult.Model.ModelOptions.Diffusers.Contains(DiffuserType.ImageInpaint) - || imageResult.Model.ModelOptions.Diffusers.Contains(DiffuserType.ImageInpaintLegacy)) + if (imageResult.Model.ModelSet.Diffusers.Contains(DiffuserType.ImageInpaint) + || imageResult.Model.ModelSet.Diffusers.Contains(DiffuserType.ImageInpaintLegacy)) { SelectedModel = imageResult.Model; } @@ -229,7 +229,7 @@ private async Task Generate() try { - await foreach (var resultImage in ExecuteStableDiffusion(_selectedModel.ModelOptions, promptOptions, schedulerOptions, batchOptions)) + await foreach (var resultImage in ExecuteStableDiffusion(_selectedModel.ModelSet, promptOptions, schedulerOptions, batchOptions)) { if (resultImage != null) { @@ -392,7 +392,7 @@ private PromptOptions GetPromptOptions(PromptOptionsModel promptOptionsModel, Im { Prompt = promptOptionsModel.Prompt, NegativePrompt = promptOptionsModel.NegativePrompt, - DiffuserType = SelectedModel.ModelOptions.Diffusers.Contains(DiffuserType.ImageInpaint) + DiffuserType = SelectedModel.ModelSet.Diffusers.Contains(DiffuserType.ImageInpaint) ? DiffuserType.ImageInpaint : DiffuserType.ImageInpaintLegacy, InputImage = new InputImage @@ -425,7 +425,7 @@ private async Task GenerateResultAsync(byte[] imageBytes, PromptOpt Model = _selectedModel, Prompt = promptOptions.Prompt, NegativePrompt = promptOptions.NegativePrompt, - PipelineType = _selectedModel.ModelOptions.PipelineType, + PipelineType = _selectedModel.ModelSet.PipelineType, DiffuserType = promptOptions.DiffuserType, SchedulerType = schedulerOptions.SchedulerType, SchedulerOptions = schedulerOptions, diff --git a/OnnxStack.UI/Views/ImageToImageView.xaml b/OnnxStack.UI/Views/ImageToImageView.xaml index ca912d57..e7addc88 100644 --- a/OnnxStack.UI/Views/ImageToImageView.xaml +++ b/OnnxStack.UI/Views/ImageToImageView.xaml @@ -24,7 +24,7 @@ UISettings="{Binding UISettings}" SupportedDiffusers="{Binding SupportedDiffusers}" IsEnabled="{Binding IsGenerating, Converter={StaticResource InverseBoolConverter}}" - SelectedModel="{Binding SelectedModel, Mode=TwoWay}" Models="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}}, Path=Models}"/> + SelectedModel="{Binding SelectedModel, Mode=TwoWay}"/> ImageResults { get; } - public ModelOptionsModel SelectedModel + public StableDiffusionModelSetViewModel SelectedModel { get { return _selectedModel; } set { _selectedModel = value; NotifyPropertyChanged(); } @@ -177,7 +177,7 @@ public async Task NavigateAsync(ImageResult imageResult) HasResult = false; ResultImage = null; HasInputResult = true; - if (imageResult.Model.ModelOptions.Diffusers.Contains(DiffuserType.ImageToImage)) + if (imageResult.Model.ModelSet.Diffusers.Contains(DiffuserType.ImageToImage)) { SelectedModel = imageResult.Model; } @@ -211,7 +211,7 @@ private async Task Generate() try { - await foreach (var resultImage in ExecuteStableDiffusion(_selectedModel.ModelOptions, promptOptions, schedulerOptions, batchOptions)) + await foreach (var resultImage in ExecuteStableDiffusion(_selectedModel.ModelSet, promptOptions, schedulerOptions, batchOptions)) { if (resultImage != null) { @@ -402,7 +402,7 @@ private async Task GenerateResultAsync(byte[] imageBytes, PromptOpt Model = _selectedModel, Prompt = promptOptions.Prompt, NegativePrompt = promptOptions.NegativePrompt, - PipelineType = _selectedModel.ModelOptions.PipelineType, + PipelineType = _selectedModel.ModelSet.PipelineType, DiffuserType = promptOptions.DiffuserType, SchedulerType = schedulerOptions.SchedulerType, SchedulerOptions = schedulerOptions, diff --git a/OnnxStack.UI/Views/ModelSettingsView.xaml b/OnnxStack.UI/Views/ModelSettingsView.xaml new file mode 100644 index 00000000..d05388bf --- /dev/null +++ b/OnnxStack.UI/Views/ModelSettingsView.xaml @@ -0,0 +1,596 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/OnnxStack.UI/Views/ModelSettingsView.xaml.cs b/OnnxStack.UI/Views/ModelSettingsView.xaml.cs new file mode 100644 index 00000000..93949660 --- /dev/null +++ b/OnnxStack.UI/Views/ModelSettingsView.xaml.cs @@ -0,0 +1,919 @@ +using Microsoft.Extensions.Logging; +using OnnxStack.Core; +using OnnxStack.Core.Config; +using OnnxStack.StableDiffusion.Config; +using OnnxStack.UI.Commands; +using OnnxStack.UI.Dialogs; +using OnnxStack.UI.Models; +using OnnxStack.UI.Services; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Text.Json.Serialization; +using System.Threading; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; + + +namespace OnnxStack.UI.Views +{ + /// + /// Interaction logic for ModelSettingsView.xaml + /// + public partial class ModelSettingsView : UserControl, INavigatable, INotifyPropertyChanged + { + private readonly IModelFactory _modelFactory; + private readonly IDialogService _dialogService; + private readonly ILogger _logger; + private readonly IModelDownloadService _modelDownloadService; + + private ModelTemplateViewModel _selectedModelTemplate; + private ICollectionView _modelTemplateCollectionView; + + private string _modelTemplateFilterText; + private string _modelTemplateFilterAuthor; + private string _modelTemplateFilterTemplateType; + private List _modelTemplateFilterAuthors; + private ModelTemplateStatusFilter _modelTemplateFilterStatus; + + private LayoutViewType _modelTemplateLayoutView = LayoutViewType.TileSmall; + private string _modelTemplateSortProperty; + private ListSortDirection _modelTemplateSortDirection; + + + /// + /// Initializes a new instance of the class. + /// + public ModelSettingsView() + { + if (!DesignerProperties.GetIsInDesignMode(this)) + { + _logger = App.GetService>(); + _modelFactory = App.GetService(); + _dialogService = App.GetService(); + _modelDownloadService = App.GetService(); + } + + + UpdateModelCommand = new AsyncRelayCommand(UpdateModel); + UpdateModelAdvancedCommand = new AsyncRelayCommand(UpdateModelAdvanced); + + RemoveModelCommand = new AsyncRelayCommand(RemoveModel); + InstallModelCommand = new AsyncRelayCommand(InstallModel); + UninstallModelCommand = new AsyncRelayCommand(UninstallModel); + DownloadModelCommand = new AsyncRelayCommand(DownloadModel); + DownloadModelCancelCommand = new AsyncRelayCommand(DownloadModelCancel); + ModelTemplateFilterResetCommand = new AsyncRelayCommand(ModelTemplateFilterReset); + UpdateModelMetadataCommand = new AsyncRelayCommand(UpdateModelMetadata); + ViewModelMetadataCommand = new AsyncRelayCommand(ViewModelMetadata); + + HyperLinkNavigateCommand = new AsyncRelayCommand(HyperLinkNavigate); + ModelTemplateLayoutCommand = new AsyncRelayCommand(ModelTemplateLayout); + + AddUpscaleModelCommand = new AsyncRelayCommand(AddUpscaleModel); + AddStableDiffusionModelCommand = new AsyncRelayCommand(AddStableDiffusionModel); + InitializeComponent(); + } + + + + private Task HyperLinkNavigate(string link) + { + Process.Start(new ProcessStartInfo(link) { UseShellExecute = true }); + return Task.CompletedTask; + } + + + public AsyncRelayCommand UpdateModelCommand { get; } + public AsyncRelayCommand UpdateModelAdvancedCommand { get; } + public AsyncRelayCommand RemoveModelCommand { get; } + public AsyncRelayCommand InstallModelCommand { get; } + public AsyncRelayCommand UninstallModelCommand { get; } + public AsyncRelayCommand DownloadModelCommand { get; } + public AsyncRelayCommand DownloadModelCancelCommand { get; } + public AsyncRelayCommand ModelTemplateFilterResetCommand { get; } + public AsyncRelayCommand HyperLinkNavigateCommand { get; } + public AsyncRelayCommand AddUpscaleModelCommand { get; } + public AsyncRelayCommand AddStableDiffusionModelCommand { get; } + public AsyncRelayCommand ModelTemplateLayoutCommand { get; } + public AsyncRelayCommand UpdateModelMetadataCommand { get; } + public AsyncRelayCommand ViewModelMetadataCommand { get; } + + public ModelTemplateViewModel SelectedModelTemplate + { + get { return _selectedModelTemplate; } + set { _selectedModelTemplate = value; NotifyPropertyChanged(); } + } + + public ICollectionView ModelTemplateCollectionView + { + get { return _modelTemplateCollectionView; } + set { _modelTemplateCollectionView = value; NotifyPropertyChanged(); } + } + + public string ModelTemplateFilterText + { + get { return _modelTemplateFilterText; } + set { _modelTemplateFilterText = value; NotifyPropertyChanged(); ModelTemplateRefresh(); } + } + + public string ModelTemplateFilterTemplateType + { + get { return _modelTemplateFilterTemplateType; } + set { _modelTemplateFilterTemplateType = value; NotifyPropertyChanged(); ModelTemplateRefresh(); } + } + + public string ModelTemplateFilterAuthor + { + get { return _modelTemplateFilterAuthor; } + set { _modelTemplateFilterAuthor = value; NotifyPropertyChanged(); ModelTemplateRefresh(); } + } + + public List ModelTemplateFilterAuthors + { + get { return _modelTemplateFilterAuthors; } + set { _modelTemplateFilterAuthors = value; NotifyPropertyChanged(); } + } + + + + public ModelTemplateStatusFilter ModelTemplateFilterStatus + { + get { return _modelTemplateFilterStatus; } + set { _modelTemplateFilterStatus = value; NotifyPropertyChanged(); ModelTemplateRefresh(); } + } + + + + + public LayoutViewType ModelTemplateLayoutView + { + get { return _modelTemplateLayoutView; } + set { _modelTemplateLayoutView = value; NotifyPropertyChanged(); } + } + + public string ModelTemplateSortProperty + { + get { return _modelTemplateSortProperty; } + set { _modelTemplateSortProperty = value; NotifyPropertyChanged(); ModelTemplateSort(); } + } + + public ListSortDirection ModelTemplateSortDirection + { + get { return _modelTemplateSortDirection; } + set { _modelTemplateSortDirection = value; NotifyPropertyChanged(); ModelTemplateSort(); } + } + + public OnnxStackUIConfig UISettings + { + get { return (OnnxStackUIConfig)GetValue(UISettingsProperty); } + set { SetValue(UISettingsProperty, value); } + } + public static readonly DependencyProperty UISettingsProperty = + DependencyProperty.Register("UISettings", typeof(OnnxStackUIConfig), typeof(ModelSettingsView), new PropertyMetadata((d, e) => + { + if (d is ModelSettingsView control && e.NewValue is OnnxStackUIConfig) + control.InitializeTemplates(); + })); + + + public Task NavigateAsync(ImageResult imageResult) + { + throw new NotImplementedException(); + } + + + private async Task RemoveModel() + { + var modelTemplate = UISettings.Templates.FirstOrDefault(x => x.Name == _selectedModelTemplate.Name); + if (modelTemplate == null) + return; + + if (modelTemplate.Category == ModelTemplateCategory.Upscaler) + await RemoveUpscaleModel(modelTemplate); + else if (modelTemplate.Category == ModelTemplateCategory.StableDiffusion) + await RemoveStableDiffusionModel(modelTemplate); + } + + + private async Task InstallModel() + { + var modelTemplate = UISettings.Templates.FirstOrDefault(x => x.Name == _selectedModelTemplate.Name); + if (modelTemplate == null) + return; + + if (modelTemplate.Category == ModelTemplateCategory.Upscaler) + await InstallUpscaleModel(modelTemplate); + else if (modelTemplate.Category == ModelTemplateCategory.StableDiffusion) + await InstallStableDiffusionModel(modelTemplate); + } + + + private async Task UninstallModel() + { + var modelTemplate = UISettings.Templates.FirstOrDefault(x => x.Name == _selectedModelTemplate.Name); + if (modelTemplate == null) + return; + + if (modelTemplate.Category == ModelTemplateCategory.Upscaler) + await UninstallUpscaleModel(modelTemplate); + else if (modelTemplate.Category == ModelTemplateCategory.StableDiffusion) + await UninstallStableDiffusionModel(modelTemplate); + } + + + private async Task UpdateModel() + { + var modelTemplate = UISettings.Templates.FirstOrDefault(x => x.IsUserTemplate && x.Name == _selectedModelTemplate.Name); + if (modelTemplate == null) + return; + + if (modelTemplate.Category == ModelTemplateCategory.Upscaler) + await UpdateUpscaleModel(modelTemplate); + else if (modelTemplate.Category == ModelTemplateCategory.StableDiffusion) + await UpdateStableDiffusionModel(modelTemplate); + } + + private async Task UpdateModelAdvanced() + { + var modelTemplate = UISettings.Templates.FirstOrDefault(x => x.IsUserTemplate && x.Name == _selectedModelTemplate.Name); + if (modelTemplate == null) + return; + + if (modelTemplate.Category == ModelTemplateCategory.Upscaler) + await UpdateUpscaleModelAdvanced(modelTemplate); + else if (modelTemplate.Category == ModelTemplateCategory.StableDiffusion) + await UpdateStableDiffusionModelAdvanced(modelTemplate); + } + + + + private Task DownloadModel(bool isRepostitoryClone) + { + var modelTemplate = UISettings.Templates.FirstOrDefault(x => x.Name == _selectedModelTemplate.Name); + if (modelTemplate == null) + return Task.CompletedTask; + + var folderDialog = new System.Windows.Forms.FolderBrowserDialog(); + if (folderDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) + { + var repositoryUrl = modelTemplate.Repository; + var outputDirectory = Path.Combine(folderDialog.SelectedPath, repositoryUrl.Split('/').LastOrDefault()); + modelTemplate.IsDownloading = true; + modelTemplate.CancellationTokenSource = new CancellationTokenSource(); + + // Download File, do not await + _ = Task.Factory.StartNew(async () => + { + modelTemplate.ErrorMessage = null; + modelTemplate.ProgressValue = 1; + modelTemplate.ProgressText = $"Starting Download..."; + Action progress = (f, fp, tp) => + { + modelTemplate.ProgressText = $"{f}"; + modelTemplate.ProgressValue = tp; + }; + try + { + var isDownloadComplete = !isRepostitoryClone + ? await _modelDownloadService.DownloadHttpAsync(modelTemplate.RepositoryFiles, outputDirectory, progress, modelTemplate.CancellationTokenSource.Token) + : await _modelDownloadService.DownloadRepositoryAsync(modelTemplate.RepositoryClone, outputDirectory, progress, modelTemplate.CancellationTokenSource.Token); + App.UIInvoke(async () => + { + if (isDownloadComplete) + { + if (modelTemplate.Category == ModelTemplateCategory.Upscaler) + await DownloadUpscaleModelComplete(modelTemplate, outputDirectory); + if (modelTemplate.Category == ModelTemplateCategory.StableDiffusion) + await DownloadStableDiffusionModelComplete(modelTemplate, outputDirectory); + } + + modelTemplate.IsDownloading = false; + }); + } + catch (Exception ex) + { + modelTemplate.IsDownloading = false; + modelTemplate.ProgressText = null; + modelTemplate.ProgressValue = 0; + modelTemplate.ErrorMessage = ex.Message; + } + }); + } + return Task.CompletedTask; + } + + private Task DownloadModelCancel() + { + _selectedModelTemplate?.CancellationTokenSource?.Cancel(); + return Task.CompletedTask; + } + + private Task ModelTemplateLayout(LayoutViewType layoutViewType) + { + ModelTemplateLayoutView = layoutViewType; + return Task.CompletedTask; + } + + private async Task UpdateModelMetadata() + { + var updateMetadataDialog = _dialogService.GetDialog(); + if (updateMetadataDialog.ShowDialog(_selectedModelTemplate)) + { + await SaveConfigurationFile(); + } + } + + private Task ViewModelMetadata() + { + var viewMetadataDialog = _dialogService.GetDialog(); + viewMetadataDialog.ShowDialog(_selectedModelTemplate); + return Task.CompletedTask; + } + + private Task SaveConfigurationFile() + { + try + { + ConfigManager.SaveConfiguration(UISettings); + ModelTemplateRefresh(); + return Task.FromResult(true); + } + catch (Exception ex) + { + _logger.LogError($"Error saving configuration file, {ex.Message}"); + return Task.FromResult(false); + } + } + + + #region ModelTemplate + + private void InitializeTemplates() + { + if (ModelTemplateCollectionView != null) + ModelTemplateCollectionView.CollectionChanged -= ModelTemplateCollectionView_CollectionChanged; + + foreach (var template in UISettings.Templates.Where(x => x.IsUserTemplate)) + { + template.IsInstalled = UISettings.UpscaleModelSets.Any(x => x.Name == template.Name) + || UISettings.StableDiffusionModelSets.Any(x => x.Name == template.Name); + } + + ModelTemplateFilterAuthors = UISettings.Templates + .Where(x => !string.IsNullOrEmpty(x.Author)) + .Select(x => x.Author) + .Distinct() + .OrderBy(x => x) + .ToList(); + ModelTemplateFilterAuthors.Insert(0, "All"); + ModelTemplateFilterAuthor = "All"; + ModelTemplateCollectionView = new ListCollectionView(UISettings.Templates); + ModelTemplateSort(); + ModelTemplateCollectionView.Filter = ModelTemplateFilter; + ModelTemplateCollectionView.MoveCurrentToFirst(); + SelectedModelTemplate = (ModelTemplateViewModel)ModelTemplateCollectionView.CurrentItem; + ModelTemplateCollectionView.CollectionChanged += ModelTemplateCollectionView_CollectionChanged; + } + + private void ModelTemplateCollectionView_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) + { + if (!ModelTemplateCollectionView.Contains(SelectedModelTemplate)) + { + // If the selected item no longer exists(filtered) select first + ModelTemplateCollectionView.MoveCurrentToFirst(); + SelectedModelTemplate = (ModelTemplateViewModel)ModelTemplateCollectionView.CurrentItem; + } + } + + private void ModelTemplateRefresh() + { + if (ModelTemplateCollectionView is null) + return; + ModelTemplateCollectionView.Refresh(); + } + + private bool ModelTemplateFilter(object obj) + { + if (obj is not ModelTemplateViewModel template) + return false; + + return (string.IsNullOrEmpty(_modelTemplateFilterText) || template.Name.Contains(_modelTemplateFilterText, StringComparison.OrdinalIgnoreCase)) + && (_modelTemplateFilterAuthor == "All" || _modelTemplateFilterAuthor.Equals(template.Author, StringComparison.OrdinalIgnoreCase)) + && (_modelTemplateFilterTemplateType is null || _modelTemplateFilterTemplateType == template.Template) + && (_modelTemplateFilterStatus == ModelTemplateStatusFilter.All + || (_modelTemplateFilterStatus == ModelTemplateStatusFilter.Installed && template.IsInstalled && template.IsUserTemplate) + || (_modelTemplateFilterStatus == ModelTemplateStatusFilter.Uninstalled && !template.IsInstalled && template.IsUserTemplate) + || (_modelTemplateFilterStatus == ModelTemplateStatusFilter.Template && !template.IsUserTemplate)); + } + + private Task ModelTemplateFilterReset() + { + ModelTemplateFilterAuthor = "All"; + ModelTemplateFilterStatus = default; + ModelTemplateFilterTemplateType = null; + ModelTemplateFilterText = null; + return Task.CompletedTask; + } + + + private void ModelTemplateSort() + { + if (ModelTemplateCollectionView is null) + return; + + ModelTemplateCollectionView.SortDescriptions.Clear(); + if (ModelTemplateSortProperty == "Status") + { + var inverseDirction = ModelTemplateSortDirection == ListSortDirection.Ascending ? ListSortDirection.Descending : ListSortDirection.Ascending; + ModelTemplateCollectionView.SortDescriptions.Add(new SortDescription("IsInstalled", inverseDirction)); + ModelTemplateCollectionView.SortDescriptions.Add(new SortDescription("IsUserTemplate", ListSortDirection.Ascending)); + ModelTemplateCollectionView.SortDescriptions.Add(new SortDescription("Rank", ListSortDirection.Descending)); + ModelTemplateCollectionView.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending)); + return; + } + ModelTemplateCollectionView.SortDescriptions.Add(new SortDescription(ModelTemplateSortProperty, ModelTemplateSortDirection)); + } + + #endregion + + #region StableDiffusion Model + + private async Task AddStableDiffusionModel() + { + var addModelDialog = _dialogService.GetDialog(); + if (addModelDialog.ShowDialog()) + { + await InstallStableDiffusionModel(addModelDialog.ModelTemplate, addModelDialog.ModelSetResult); + } + } + + private async Task RemoveStableDiffusionModel(ModelTemplateViewModel modelTemplate) + { + if (!modelTemplate.IsUserTemplate) + return; // Cant remove Templates + + var modelSet = UISettings.StableDiffusionModelSets.FirstOrDefault(x => x.Name == modelTemplate.Name); + if (modelSet.IsLoaded) + { + MessageBox.Show("Please unload model before uninstalling", "Model In Use", MessageBoxButton.OK, MessageBoxImage.Warning); + return; + } + + UISettings.StableDiffusionModelSets.Remove(modelSet); + UISettings.Templates.Remove(modelTemplate); + await SaveConfigurationFile(); + } + + + private async Task InstallStableDiffusionModel(ModelTemplateViewModel modelTemplate) + { + var addModelDialog = _dialogService.GetDialog(); + if (!addModelDialog.ShowDialog(modelTemplate)) + return; // User Canceled + + await InstallStableDiffusionModel(modelTemplate, addModelDialog.ModelSetResult); + } + + + private async Task InstallStableDiffusionModel(ModelTemplateViewModel modelTemplate, StableDiffusionModelSet modelSetResult) + { + if (modelTemplate.IsUserTemplate) + { + modelTemplate.IsInstalled = true; + } + else + { + var newModelTemplate = new ModelTemplateViewModel + { + Name = modelSetResult.Name, + Category = ModelTemplateCategory.StableDiffusion, + IsInstalled = true, + IsUserTemplate = true, + ImageIcon = string.Empty,// modelTemplate.ImageIcon, + Author = "Unknown", //modelTemplate.Author, + Template = modelTemplate.Template, + StableDiffusionTemplate = modelTemplate.StableDiffusionTemplate with { }, + }; + UISettings.Templates.Add(newModelTemplate); + SelectedModelTemplate = newModelTemplate; + } + + UISettings.StableDiffusionModelSets.Add(new StableDiffusionModelSetViewModel + { + Name = modelSetResult.Name, + ModelSet = modelSetResult + }); + await SaveConfigurationFile(); + } + + private async Task UninstallStableDiffusionModel(ModelTemplateViewModel modelTemplate) + { + var modelSet = UISettings.StableDiffusionModelSets.FirstOrDefault(x => x.Name == modelTemplate.Name); + if (modelSet.IsLoaded) + { + MessageBox.Show("Please unload model before uninstalling", "Model In Use", MessageBoxButton.OK, MessageBoxImage.Warning); + return; + } + + UISettings.StableDiffusionModelSets.Remove(modelSet); + modelTemplate.IsInstalled = false; + await SaveConfigurationFile(); + } + + private async Task UpdateStableDiffusionModel(ModelTemplateViewModel modelTemplate) + { + var stableDiffusionModel = UISettings.StableDiffusionModelSets.FirstOrDefault(x => x.Name == modelTemplate.Name); + if (stableDiffusionModel.IsLoaded) + { + MessageBox.Show("Please unload model before updating", "Model In Use", MessageBoxButton.OK, MessageBoxImage.Warning); + return; + } + + + var updateModelDialog = _dialogService.GetDialog(); + if (updateModelDialog.ShowDialog(stableDiffusionModel.ModelSet)) + { + var modelSet = updateModelDialog.ModelSetResult; + stableDiffusionModel.ModelSet = modelSet; + stableDiffusionModel.Name = modelSet.Name; + SelectedModelTemplate.Name = modelSet.Name; + UISettings.StableDiffusionModelSets.ForceNotifyCollectionChanged(); + await SaveConfigurationFile(); + } + } + + + private async Task UpdateStableDiffusionModelAdvanced(ModelTemplateViewModel modelTemplate) + { + var stableDiffusionModel = UISettings.StableDiffusionModelSets.FirstOrDefault(x => x.Name == modelTemplate.Name); + if (stableDiffusionModel.IsLoaded) + { + MessageBox.Show("Please unload model before updating", "Model In Use", MessageBoxButton.OK, MessageBoxImage.Warning); + return; + } + + var updateModelDialog = _dialogService.GetDialog(); + if (updateModelDialog.ShowDialog(stableDiffusionModel.ModelSet)) + { + var modelSet = updateModelDialog.ModelSetResult; + stableDiffusionModel.ModelSet = modelSet; + stableDiffusionModel.Name = modelSet.Name; + SelectedModelTemplate.Name = modelSet.Name; + UISettings.StableDiffusionModelSets.ForceNotifyCollectionChanged(); + await SaveConfigurationFile(); + } + } + + private async Task DownloadStableDiffusionModelComplete(ModelTemplateViewModel modelTemplate, string outputDirectory) + { + var modelSet = _modelFactory.CreateStableDiffusionModelSet(modelTemplate.Name, outputDirectory, modelTemplate.StableDiffusionTemplate); + var isModelSetValid = modelSet.ModelConfigurations.All(x => File.Exists(x.OnnxModelPath)); + if (!isModelSetValid) + { + // Error, Invalid modelset after download + modelTemplate.IsDownloading = false; + modelTemplate.ErrorMessage = "Error: Download completed but ModelSet is invalid"; + return; + } + + UISettings.StableDiffusionModelSets.Add(new StableDiffusionModelSetViewModel + { + Name = modelSet.Name, + ModelSet = modelSet + }); + + // Update/Save + modelTemplate.IsInstalled = true; + await SaveConfigurationFile(); + } + + #endregion + + #region Upscale Model + + private async Task AddUpscaleModel() + { + var addModelDialog = _dialogService.GetDialog(); + if (addModelDialog.ShowDialog()) + { + await InstallUpscaleModel(addModelDialog.ModelTemplate, addModelDialog.ModelSetResult); + } + } + + private async Task UpdateUpscaleModel(ModelTemplateViewModel modelTemplate) + { + var upscaleModel = UISettings.UpscaleModelSets.FirstOrDefault(x => x.Name == modelTemplate.Name); + if (upscaleModel.IsLoaded) + { + MessageBox.Show("Please unload model before updating", "Model In Use", MessageBoxButton.OK, MessageBoxImage.Warning); + return; + } + + + var updateModelDialog = _dialogService.GetDialog(); + if (updateModelDialog.ShowDialog(upscaleModel.ModelSet)) + { + var modelSet = updateModelDialog.ModelSetResult; + upscaleModel.ModelSet = modelSet; + upscaleModel.Name = modelSet.Name; + SelectedModelTemplate.Name = modelSet.Name; + UISettings.UpscaleModelSets.ForceNotifyCollectionChanged(); + await SaveConfigurationFile(); + } + } + + private async Task UpdateUpscaleModelAdvanced(ModelTemplateViewModel modelTemplate) + { + var upscaleModel = UISettings.UpscaleModelSets.FirstOrDefault(x => x.Name == modelTemplate.Name); + if (upscaleModel.IsLoaded) + { + MessageBox.Show("Please unload model before updating", "Model In Use", MessageBoxButton.OK, MessageBoxImage.Warning); + return; + } + + var updateModelDialog = _dialogService.GetDialog(); + if (updateModelDialog.ShowDialog(upscaleModel.ModelSet)) + { + var modelSet = updateModelDialog.ModelSetResult; + upscaleModel.ModelSet = modelSet; + upscaleModel.Name = modelSet.Name; + SelectedModelTemplate.Name = modelSet.Name; + UISettings.UpscaleModelSets.ForceNotifyCollectionChanged(); + await SaveConfigurationFile(); + } + } + + private async Task RemoveUpscaleModel(ModelTemplateViewModel modelTemplate) + { + if (!modelTemplate.IsUserTemplate) + return; // Cant remove Templates + + var modelSet = UISettings.UpscaleModelSets.FirstOrDefault(x => x.Name == modelTemplate.Name); + if (modelSet.IsLoaded) + { + MessageBox.Show("Please unload model before uninstalling", "Model In Use", MessageBoxButton.OK, MessageBoxImage.Warning); + return; + } + + UISettings.UpscaleModelSets.Remove(modelSet); + UISettings.Templates.Remove(modelTemplate); + await SaveConfigurationFile(); + } + + + private async Task InstallUpscaleModel(ModelTemplateViewModel modelTemplate) + { + var addModelDialog = _dialogService.GetDialog(); + if (!addModelDialog.ShowDialog(modelTemplate)) + return; // User Canceled + + await InstallUpscaleModel(modelTemplate, addModelDialog.ModelSetResult); + } + + private async Task InstallUpscaleModel(ModelTemplateViewModel modelTemplate, UpscaleModelSet modelSetResult) + { + if (modelTemplate.IsUserTemplate) + { + modelTemplate.IsInstalled = true; + } + else + { + var newModelTemplate = new ModelTemplateViewModel + { + Name = modelSetResult.Name, + Category = ModelTemplateCategory.Upscaler, + IsInstalled = true, + IsUserTemplate = true, + ImageIcon = string.Empty,// modelTemplate.ImageIcon, + Author = "Unknown", //modelTemplate.Author, + Template = modelTemplate.Template, + UpscaleTemplate = modelTemplate.UpscaleTemplate with { }, + }; + UISettings.Templates.Add(newModelTemplate); + SelectedModelTemplate = newModelTemplate; + } + + UISettings.UpscaleModelSets.Add(new UpscaleModelSetViewModel + { + Name = modelSetResult.Name, + ModelSet = modelSetResult + }); + await SaveConfigurationFile(); + } + + + private async Task UninstallUpscaleModel(ModelTemplateViewModel modelTemplate) + { + var modelSet = UISettings.UpscaleModelSets.FirstOrDefault(x => x.Name == modelTemplate.Name); + if (modelSet.IsLoaded) + { + MessageBox.Show("Please unload model before uninstalling", "Model In Use", MessageBoxButton.OK, MessageBoxImage.Warning); + return; + } + + UISettings.UpscaleModelSets.Remove(modelSet); + modelTemplate.IsInstalled = false; + await SaveConfigurationFile(); + } + + private async Task DownloadUpscaleModelComplete(ModelTemplateViewModel modelTemplate, string outputDirectory) + { + var modelSet = _modelFactory.CreateUpscaleModelSet(modelTemplate.Name, outputDirectory, modelTemplate.UpscaleTemplate); + var isModelSetValid = modelSet.ModelConfigurations.All(x => File.Exists(x.OnnxModelPath)); + if (!isModelSetValid) + { + // Error, Invalid modelset after download + modelTemplate.IsDownloading = false; + modelTemplate.ErrorMessage = "Error: Download completed but ModelSet is invalid"; + return; + } + + UISettings.UpscaleModelSets.Add(new UpscaleModelSetViewModel + { + Name = modelSet.Name, + ModelSet = modelSet + }); + + // Update/Save + modelTemplate.IsInstalled = true; + await SaveConfigurationFile(); + } + + #endregion + + #region INotifyPropertyChanged + public event PropertyChangedEventHandler PropertyChanged; + + public void NotifyPropertyChanged([CallerMemberName] string property = "") + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property)); + } + #endregion + } + + public enum LayoutViewType + { + TileLarge = 0, + TileSmall = 1, + List = 2 + } + + + public enum ModelTemplateCategory + { + StableDiffusion = 0, + Upscaler = 1 + } + + public enum ModelTemplateStatusFilter + { + All = 0, + Installed = 1, + Template = 2, + Uninstalled = 3 + } + + + public class ModelTemplateViewModel : INotifyPropertyChanged + { + private string _name; + private string _imageIcon; + private string _author; + + private bool _isInstalled; + private bool _isDownloading; + private double _progressValue; + private string _progressText; + private string _errorMessage; + + public string Name + { + get { return _name; } + set { _name = value; NotifyPropertyChanged(); } + } + + public string ImageIcon + { + get { return _imageIcon; } + set { _imageIcon = value; NotifyPropertyChanged(); } + } + + public string Author + { + get { return _author; } + set { _author = value; NotifyPropertyChanged(); } + } + + private string _description; + + public string Description + { + get { return _description; } + set { _description = value; NotifyPropertyChanged(); } + } + + public int Rank { get; set; } + public bool IsUserTemplate { get; set; } + + public string Template { get; set; } + + public ModelTemplateCategory Category { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public UpscaleModelTemplate UpscaleTemplate { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public StableDiffusionModelTemplate StableDiffusionTemplate { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string Website { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string Repository { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string RepositoryBranch { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public List RepositoryFiles { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public List PreviewImages { get; set; } + + [JsonIgnore] + public string RepositoryClone + { + get + { + return string.IsNullOrEmpty(RepositoryBranch) + ? Repository + : $"{Repository} -b {RepositoryBranch}"; + } + } + + [JsonIgnore] + public bool IsInstalled + { + get { return _isInstalled; } + set { _isInstalled = value; NotifyPropertyChanged(); } + } + + [JsonIgnore] + public bool IsDownloading + { + get { return _isDownloading; } + set { _isDownloading = value; NotifyPropertyChanged(); } + } + + [JsonIgnore] + public double ProgressValue + { + get { return _progressValue; } + set { _progressValue = value; NotifyPropertyChanged(); } + } + + [JsonIgnore] + public string ProgressText + { + get { return _progressText; } + set { _progressText = value; NotifyPropertyChanged(); } + } + + [JsonIgnore] + public string ErrorMessage + { + get { return _errorMessage; } + set { _errorMessage = value; NotifyPropertyChanged(); } + } + + [JsonIgnore] + public bool IsRepositoryCloneEnabled => !string.IsNullOrEmpty(Repository); + + [JsonIgnore] + public bool IsRepositoryDownloadEnabled => !RepositoryFiles.IsNullOrEmpty(); + + [JsonIgnore] + public CancellationTokenSource CancellationTokenSource { get; set; } + + + + #region INotifyPropertyChanged + public event PropertyChangedEventHandler PropertyChanged; + + public void NotifyPropertyChanged([CallerMemberName] string property = "") + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property)); + } + #endregion + } + + + +} diff --git a/OnnxStack.UI/Views/ModelView.xaml b/OnnxStack.UI/Views/ModelView.xaml deleted file mode 100644 index fe73d5c7..00000000 --- a/OnnxStack.UI/Views/ModelView.xaml +++ /dev/null @@ -1,468 +0,0 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/OnnxStack.UI/Views/UpscaleView.xaml.cs b/OnnxStack.UI/Views/UpscaleView.xaml.cs new file mode 100644 index 00000000..46bc8fa7 --- /dev/null +++ b/OnnxStack.UI/Views/UpscaleView.xaml.cs @@ -0,0 +1,370 @@ +using Microsoft.Extensions.Logging; +using Models; +using OnnxStack.Core.Image; +using OnnxStack.ImageUpscaler.Services; +using OnnxStack.UI.Commands; +using OnnxStack.UI.Models; +using System; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.Threading; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media.Imaging; + +namespace OnnxStack.UI.Views +{ + /// + /// Interaction logic for UpscaleView.xaml + /// + public partial class UpscaleView : UserControl, INavigatable, INotifyPropertyChanged + { + private readonly ILogger _logger; + private readonly IUpscaleService _upscaleService; + + private bool _hasResult; + private int _progressMax; + private int _progressValue; + private bool _isGenerating; + private int _selectedTabIndex; + private bool _isControlsEnabled; + private UpscaleResult _resultImage; + private UpscaleModelSetViewModel _selectedModel; + private CancellationTokenSource _cancelationTokenSource; + private BitmapSource _inputImage; + private string _imageFile; + private UpscaleInfoModel _upscaleInfo; + + /// + /// Initializes a new instance of the class. + /// + public UpscaleView() + { + if (!DesignerProperties.GetIsInDesignMode(this)) + { + _logger = App.GetService>(); + _upscaleService = App.GetService(); + } + + CancelCommand = new AsyncRelayCommand(Cancel, CanExecuteCancel); + GenerateCommand = new AsyncRelayCommand(Generate, CanExecuteGenerate); + ClearHistoryCommand = new AsyncRelayCommand(ClearHistory, CanExecuteClearHistory); + ImageResults = new ObservableCollection(); + UpscaleInfo = new UpscaleInfoModel(); + IsControlsEnabled = true; + InitializeComponent(); + } + + public OnnxStackUIConfig UISettings + { + get { return (OnnxStackUIConfig)GetValue(UISettingsProperty); } + set { SetValue(UISettingsProperty, value); } + } + public static readonly DependencyProperty UISettingsProperty = + DependencyProperty.Register("UISettings", typeof(OnnxStackUIConfig), typeof(UpscaleView)); + + public AsyncRelayCommand CancelCommand { get; } + public AsyncRelayCommand GenerateCommand { get; } + public AsyncRelayCommand ClearHistoryCommand { get; set; } + public ObservableCollection ImageResults { get; } + + public UpscaleModelSetViewModel SelectedModel + { + get { return _selectedModel; } + set { _selectedModel = value; NotifyPropertyChanged(); UpdateInfo(); } + } + + public UpscaleResult ResultImage + { + get { return _resultImage; } + set { _resultImage = value; NotifyPropertyChanged(); } + } + + public BitmapSource InputImage + { + get { return _inputImage; } + set { _inputImage = value; NotifyPropertyChanged(); } + } + + public string ImageFile + { + get { return _imageFile; } + set { _imageFile = value; NotifyPropertyChanged(); LoadImage(); } + } + + + + public UpscaleInfoModel UpscaleInfo + { + get { return _upscaleInfo; } + set { _upscaleInfo = value; NotifyPropertyChanged(); } + } + + + + public int ProgressValue + { + get { return _progressValue; } + set { _progressValue = value; NotifyPropertyChanged(); } + } + + public int ProgressMax + { + get { return _progressMax; } + set { _progressMax = value; NotifyPropertyChanged(); } + } + + public bool IsGenerating + { + get { return _isGenerating; } + set { _isGenerating = value; NotifyPropertyChanged(); } + } + + public bool HasResult + { + get { return _hasResult; } + set { _hasResult = value; NotifyPropertyChanged(); } + } + + public int SelectedTabIndex + { + get { return _selectedTabIndex; } + set { _selectedTabIndex = value; NotifyPropertyChanged(); } + } + + public bool IsControlsEnabled + { + get { return _isControlsEnabled; } + set { _isControlsEnabled = value; NotifyPropertyChanged(); } + } + + private ScrollBarVisibility _scrollBarVisibility; + + public ScrollBarVisibility ScrollBarVisibility + { + get { return _scrollBarVisibility; } + set { _scrollBarVisibility = value; NotifyPropertyChanged(); } + } + + private bool _showFullImage; + + public bool ShowFullImage + { + get { return _showFullImage; } + set { _showFullImage = value; NotifyPropertyChanged(); UpdateScrollBar(); } + } + + private void UpdateScrollBar() + { + ScrollBarVisibility = _showFullImage + ? ScrollBarVisibility.Auto + : ScrollBarVisibility.Disabled; + } + + + + + /// + /// Called on Navigate + /// + /// The image result. + /// + public async Task NavigateAsync(ImageResult imageResult) + { + if (IsGenerating) + await Cancel(); + + Reset(); + HasResult = false; + ResultImage = null; + InputImage = imageResult.Image; + UpdateInfo(); + SelectedTabIndex = 0; + } + + + /// + /// Generates this image result. + /// + private async Task Generate() + { + HasResult = false; + IsGenerating = true; + IsControlsEnabled = false; + ResultImage = null; + + + try + { + var timestamp = Stopwatch.GetTimestamp(); + var resultBytes = await _upscaleService.GenerateAsByteAsync(SelectedModel.ModelSet, new InputImage(InputImage.GetImageBytes())); + if (resultBytes != null) + { + var elapsed = Stopwatch.GetElapsedTime(timestamp).TotalSeconds; + var imageResult = new UpscaleResult(Utils.CreateBitmap(resultBytes), UpscaleInfo with { }, elapsed); + ResultImage = imageResult; + HasResult = true; + + + ImageResults.Add(imageResult); + } + + } + catch (OperationCanceledException) + { + _logger.LogInformation($"Generate was canceled."); + } + catch (Exception ex) + { + _logger.LogError($"Error during Generate\n{ex}"); + } + + Reset(); + } + + + /// + /// Determines whether this instance can execute Generate. + /// + /// + /// true if this instance can execute Generate; otherwise, false. + /// + private bool CanExecuteGenerate() + { + return !IsGenerating && InputImage is not null; + } + + + /// + /// Cancels this generation. + /// + /// + private Task Cancel() + { + _cancelationTokenSource?.Cancel(); + return Task.CompletedTask; + } + + + /// + /// Determines whether this instance can execute Cancel. + /// + /// + /// true if this instance can execute Cancel; otherwise, false. + /// + private bool CanExecuteCancel() + { + return IsGenerating; + } + + + /// + /// Clears the history. + /// + /// + private Task ClearHistory() + { + ImageResults.Clear(); + return Task.CompletedTask; + } + + + /// + /// Determines whether this instance can execute ClearHistory. + /// + /// + /// true if this instance can execute ClearHistory; otherwise, false. + /// + private bool CanExecuteClearHistory() + { + return ImageResults.Count > 0; + } + + + /// + /// Resets this instance. + /// + private void Reset() + { + IsGenerating = false; + IsControlsEnabled = true; + ProgressValue = 0; + } + + private void LoadImage() + { + InputImage = string.IsNullOrEmpty(_imageFile) + ? null + : new BitmapImage(new Uri(_imageFile)); + UpdateInfo(); + } + + private void UpdateInfo() + { + if (SelectedModel != null) + { + UpscaleInfo.SampleSize = SelectedModel.ModelSet.SampleSize; + UpscaleInfo.ScaleFactor = SelectedModel.ModelSet.ScaleFactor; + UpscaleInfo.InputWidth = InputImage?.PixelWidth ?? SelectedModel.ModelSet.SampleSize; + UpscaleInfo.InputHeight = InputImage?.PixelHeight ?? SelectedModel.ModelSet.SampleSize; + return; + } + UpscaleInfo = new UpscaleInfoModel(); + } + + //private async Task GenerateResultAsync(byte[] imageBytes, long timestamp) + //{ + // var image = Utils.CreateBitmap(imageBytes); + + // //var imageResult = new ImageResult + // //{ + // // Image = image, + // // Model = _selectedModel, + + // // Elapsed = Stopwatch.GetElapsedTime(timestamp).TotalSeconds + // //}; + + // if (UISettings.ImageAutoSave) + // await imageResult.AutoSaveAsync(Path.Combine(UISettings.ImageAutoSaveDirectory, "TextToImage"), UISettings.ImageAutoSaveBlueprint); + // return imageResult; + //} + + + /// + /// StableDiffusion progress callback. + /// + /// + private Action ProgressCallback() + { + return (value, maximum) => + { + App.UIInvoke(() => + { + if (_cancelationTokenSource.IsCancellationRequested) + return; + + if (ProgressMax != maximum) + ProgressMax = maximum; + + ProgressValue = value; + }); + }; + } + + + + + #region INotifyPropertyChanged + public event PropertyChangedEventHandler PropertyChanged; + public void NotifyPropertyChanged([CallerMemberName] string property = "") + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property)); + } + + #endregion + } + +} \ No newline at end of file diff --git a/OnnxStack.UI/appsettings.json b/OnnxStack.UI/appsettings.json index 30e86ef3..1b0fa96f 100644 --- a/OnnxStack.UI/appsettings.json +++ b/OnnxStack.UI/appsettings.json @@ -10,6 +10,28 @@ "ModelSets": [ ] }, + "ImageUpscalerConfig": { + "ModelSets": [ + { + "Name": "RealSR BSRGAN x4", + "IsEnabled": true, + "Channels": 3, + "SampleSize": 512, + "ScaleFactor": 4, + "DeviceId": 0, + "InterOpNumThreads": 0, + "IntraOpNumThreads": 0, + "ExecutionMode": "ORT_SEQUENTIAL", + "ExecutionProvider": "DirectML", + "ModelConfigurations": [ + { + "Type": "Unet", + "OnnxModelPath": "D:\\Repositories\\upscaler\\SwinIR\\003_realSR_BSRGAN_DFO_s64w8_SwinIR-M_x4_GAN.onnx" + } + ] + } + ] + }, "OnnxStackUIConfig": { "ModelCacheMode": "Single", "ImageAutoSave": false, @@ -22,522 +44,183 @@ "DefaultIntraOpNumThreads": 0, "DefaultExecutionMode": "ORT_SEQUENTIAL", "DefaultExecutionProvider": "DirectML", - "ModelTemplates": [ - { - "Name": "StableDiffusion 1.5", - "Description": "This is a model that can be used to generate and modify images based on text prompts. It is a Latent Diffusion Model that uses a fixed, pretrained text encoder (CLIP ViT-L/14) as suggested in the Imagen paper.", - "Author": "runwayml", - "Repository": "https://huggingface.co/runwayml/stable-diffusion-v1-5/tree/onnx", - "ImageIcon": "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/stable-diffusion-v1-5/Icon.png", - "Status": "Active", - "PadTokenId": 49407, - "BlankTokenId": 49407, - "TokenizerLimit": 77, - "TokenizerLength": 768, - "TokenizerType": "One", - "ScaleFactor": 0.18215, - "SampleSize": 512, - "PipelineType": "StableDiffusion", - "Diffusers": [ - "TextToImage", - "ImageToImage", - "ImageInpaintLegacy" - ], - "ModelFiles": [ - "https://huggingface.co/runwayml/stable-diffusion-v1-5/resolve/onnx/unet/model.onnx", - "https://huggingface.co/runwayml/stable-diffusion-v1-5/resolve/onnx/unet/weights.pb", - "https://huggingface.co/runwayml/stable-diffusion-v1-5/resolve/onnx/text_encoder/model.onnx", - "https://huggingface.co/runwayml/stable-diffusion-v1-5/resolve/onnx/vae_decoder/model.onnx", - "https://huggingface.co/runwayml/stable-diffusion-v1-5/resolve/onnx/vae_encoder/model.onnx" - ], - "Images": [ - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/stable-diffusion-v1-5/Preview1.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/stable-diffusion-v1-5/Preview2.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/stable-diffusion-v1-5/Preview3.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/stable-diffusion-v1-5/Preview4.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/stable-diffusion-v1-5/Preview5.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/stable-diffusion-v1-5/Preview6.png" - ] - }, + + "Templates": [ { - "Name": "Cyberpunk Anime", - "Description": "The tokens for Cyberpunk Anime Diffusion are: dgs illustration style", - "Author": "TheyCallMeHex", - "Repository": "https://huggingface.co/TheyCallMeHex/Cyberpunk-Anime-Diffusion-ONNX", - "ImageIcon": "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Cyberpunk-Anime-Diffusion/Icon.png", - "Status": "Active", - "PadTokenId": 49407, - "BlankTokenId": 49407, - "TokenizerLimit": 77, - "TokenizerLength": 768, - "TokenizerType": "One", - "ScaleFactor": 0.18215, - "SampleSize": 512, - "PipelineType": "StableDiffusion", - "Diffusers": [ - "TextToImage", - "ImageToImage", - "ImageInpaintLegacy" - ], - "ModelFiles": [ - "https://huggingface.co/TheyCallMeHex/Cyberpunk-Anime-Diffusion-ONNX/resolve/main/tokenizer/model.onnx", - "https://huggingface.co/TheyCallMeHex/Cyberpunk-Anime-Diffusion-ONNX/resolve/main/unet/model.onnx", - "https://huggingface.co/TheyCallMeHex/Cyberpunk-Anime-Diffusion-ONNX/resolve/main/unet/model.onnx_data", - "https://huggingface.co/TheyCallMeHex/Cyberpunk-Anime-Diffusion-ONNX/resolve/main/text_encoder/model.onnx", - "https://huggingface.co/TheyCallMeHex/Cyberpunk-Anime-Diffusion-ONNX/resolve/main/vae_decoder/model.onnx", - "https://huggingface.co/TheyCallMeHex/Cyberpunk-Anime-Diffusion-ONNX/resolve/main/vae_encoder/model.onnx" - ], - "Images": [ - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Cyberpunk-Anime-Diffusion/Preview1.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Cyberpunk-Anime-Diffusion/Preview2.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Cyberpunk-Anime-Diffusion/Preview3.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Cyberpunk-Anime-Diffusion/Preview4.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Cyberpunk-Anime-Diffusion/Preview5.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Cyberpunk-Anime-Diffusion/Preview6.png" - ] - }, - { - "Name": "Comic-Diffusion", - "Description": "The tokens for Comic Diffusion are: charliebo artstyle, holliemengert artstyle, marioalberti artstyle, pepelarraz artstyle, andreasrocha artstyle, jamesdaly artstyle, comicmay artstyle", - "Author": "TheyCallMeHex", - "Repository": "https://huggingface.co/TheyCallMeHex/Comic-Diffusion-ONNX", - "ImageIcon": "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Comic-Diffusion/Icon.png", - "Status": "Active", - "PadTokenId": 49407, - "BlankTokenId": 49407, - "TokenizerLimit": 77, - "TokenizerLength": 768, - "TokenizerType": "One", - "ScaleFactor": 0.18215, - "SampleSize": 512, - "PipelineType": "StableDiffusion", - "Diffusers": [ - "TextToImage", - "ImageToImage", - "ImageInpaintLegacy" - ], - "ModelFiles": [ - "https://huggingface.co/TheyCallMeHex/Comic-Diffusion-ONNX/resolve/main/tokenizer/model.onnx", - "https://huggingface.co/TheyCallMeHex/Comic-Diffusion-ONNX/resolve/main/unet/model.onnx", - "https://huggingface.co/TheyCallMeHex/Comic-Diffusion-ONNX/resolve/main/unet/model.onnx_data", - "https://huggingface.co/TheyCallMeHex/Comic-Diffusion-ONNX/resolve/main/text_encoder/model.onnx", - "https://huggingface.co/TheyCallMeHex/Comic-Diffusion-ONNX/resolve/main/vae_decoder/model.onnx", - "https://huggingface.co/TheyCallMeHex/Comic-Diffusion-ONNX/resolve/main/vae_encoder/model.onnx" - ], - "Images": [ - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Comic-Diffusion/Preview1.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Comic-Diffusion/Preview2.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Comic-Diffusion/Preview3.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Comic-Diffusion/Preview4.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Comic-Diffusion/Preview5.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Comic-Diffusion/Preview6.png" - ] - }, - { - "Name": "DreamLike PhotoReal 2.0", - "Description": "", - "Author": "TheyCallMeHex", - "Repository": "https://huggingface.co/TheyCallMeHex/DreamLike-PhotoReal-2.0-ONNX", - "ImageIcon": "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/DreamLike-PhotoReal-2.0/Icon.png", - "Status": "Active", - "PadTokenId": 49407, - "BlankTokenId": 49407, - "TokenizerLimit": 77, - "TokenizerLength": 768, - "TokenizerType": "One", - "ScaleFactor": 0.18215, - "SampleSize": 512, - "PipelineType": "StableDiffusion", - "Diffusers": [ - "TextToImage", - "ImageToImage", - "ImageInpaintLegacy" - ], - "ModelFiles": [ - "https://huggingface.co/TheyCallMeHex/DreamLike-PhotoReal-2.0-ONNX/resolve/main/tokenizer/model.onnx", - "https://huggingface.co/TheyCallMeHex/DreamLike-PhotoReal-2.0-ONNX/resolve/main/unet/model.onnx", - "https://huggingface.co/TheyCallMeHex/DreamLike-PhotoReal-2.0-ONNX/resolve/main/unet/model.onnx_data", - "https://huggingface.co/TheyCallMeHex/DreamLike-PhotoReal-2.0-ONNX/resolve/main/text_encoder/model.onnx", - "https://huggingface.co/TheyCallMeHex/DreamLike-PhotoReal-2.0-ONNX/resolve/main/vae_decoder/model.onnx", - "https://huggingface.co/TheyCallMeHex/DreamLike-PhotoReal-2.0-ONNX/resolve/main/vae_encoder/model.onnx" - ], - "Images": [ - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/DreamLike-PhotoReal-2.0/Preview1.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/DreamLike-PhotoReal-2.0/Preview2.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/DreamLike-PhotoReal-2.0/Preview3.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/DreamLike-PhotoReal-2.0/Preview4.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/DreamLike-PhotoReal-2.0/Preview5.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/DreamLike-PhotoReal-2.0/Preview6.png" - ] - }, - { - "Name": "epiCRealism", - "Description": "", - "Author": "TheyCallMeHex", - "Repository": "https://huggingface.co/TheyCallMeHex/epiCRealism-ONNX", - "ImageIcon": "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/epiCRealism/Icon.png", - "Status": "Active", - "PadTokenId": 49407, - "BlankTokenId": 49407, - "TokenizerLimit": 77, - "TokenizerLength": 768, - "TokenizerType": "One", - "ScaleFactor": 0.18215, - "SampleSize": 512, - "PipelineType": "StableDiffusion", - "Diffusers": [ - "TextToImage", - "ImageToImage", - "ImageInpaintLegacy" - ], - "ModelFiles": [ - "https://huggingface.co/TheyCallMeHex/epiCRealism-ONNX/resolve/main/tokenizer/model.onnx", - "https://huggingface.co/TheyCallMeHex/epiCRealism-ONNX/resolve/main/unet/model.onnx", - "https://huggingface.co/TheyCallMeHex/epiCRealism-ONNX/resolve/main/unet/model.onnx_data", - "https://huggingface.co/TheyCallMeHex/epiCRealism-ONNX/resolve/main/text_encoder/model.onnx", - "https://huggingface.co/TheyCallMeHex/epiCRealism-ONNX/resolve/main/vae_decoder/model.onnx", - "https://huggingface.co/TheyCallMeHex/epiCRealism-ONNX/resolve/main/vae_encoder/model.onnx" - ], - "Images": [ - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/epiCRealism/Preview1.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/epiCRealism/Preview2.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/epiCRealism/Preview3.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/epiCRealism/Preview4.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/epiCRealism/Preview5.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/epiCRealism/Preview6.png" - ] + "Name": "StableDiffusion", + "ImageIcon": "", + "Rank": 100, + "Author": "OnnxStack", + "Category": "StableDiffusion", + "Template": "StableDiffusion", + "StableDiffusionTemplate": { + "ModelType": "Base", + "SampleSize": 512, + "PipelineType": "StableDiffusion", + "DiffuserTypes": [ + "TextToImage", + "ImageToImage", + "ImageInpaintLegacy" + ] + } }, { - "Name": "Ghibli Diffusion", - "Description": "The tokens for Ghibli Diffusion are: ghibli style", - "Author": "TheyCallMeHex", - "Repository": "https://huggingface.co/TheyCallMeHex/Ghibli-Diffusion-ONNX", - "ImageIcon": "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Ghibli-Diffusion/Icon.png", - "Status": "Active", - "PadTokenId": 49407, - "BlankTokenId": 49407, - "TokenizerLimit": 77, - "TokenizerLength": 768, - "TokenizerType": "One", - "ScaleFactor": 0.18215, - "SampleSize": 512, - "PipelineType": "StableDiffusion", - "Diffusers": [ - "TextToImage", - "ImageToImage", - "ImageInpaintLegacy" - ], - "ModelFiles": [ - "https://huggingface.co/TheyCallMeHex/Ghibli-Diffusion-ONNX/resolve/main/tokenizer/model.onnx", - "https://huggingface.co/TheyCallMeHex/Ghibli-Diffusion-ONNX/resolve/main/unet/model.onnx", - "https://huggingface.co/TheyCallMeHex/Ghibli-Diffusion-ONNX/resolve/main/unet/model.onnx_data", - "https://huggingface.co/TheyCallMeHex/Ghibli-Diffusion-ONNX/resolve/main/text_encoder/model.onnx", - "https://huggingface.co/TheyCallMeHex/Ghibli-Diffusion-ONNX/resolve/main/vae_decoder/model.onnx", - "https://huggingface.co/TheyCallMeHex/Ghibli-Diffusion-ONNX/resolve/main/vae_encoder/model.onnx" - ], - "Images": [ - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Ghibli-Diffusion/Preview1.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Ghibli-Diffusion/Preview2.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Ghibli-Diffusion/Preview3.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Ghibli-Diffusion/Preview4.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Ghibli-Diffusion/Preview5.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Ghibli-Diffusion/Preview6.png" - ] + "Name": "StableDiffusion Inpaint", + "ImageIcon": "", + "Rank": 0, + "Author": "OnnxStack", + "Category": "StableDiffusion", + "Template": "StableDiffusionInpaint", + "StableDiffusionTemplate": { + "ModelType": "Base", + "PipelineType": "StableDiffusion", + "DiffuserTypes": [ + "ImageInpaint" + ] + } }, { - "Name": "Inkpunk Diffusion", - "Description": "The tokens for Inkpunk Diffusion are: nvinkpunk", - "Author": "TheyCallMeHex", - "Repository": "https://huggingface.co/TheyCallMeHex/Inkpunk-Diffusion-ONNX", - "ImageIcon": "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Inkpunk-Diffusion/Icon.png", - "Status": "Active", - "PadTokenId": 49407, - "BlankTokenId": 49407, - "TokenizerLimit": 77, - "TokenizerLength": 768, - "TokenizerType": "One", - "ScaleFactor": 0.18215, - "SampleSize": 512, - "PipelineType": "StableDiffusion", - "Diffusers": [ - "TextToImage", - "ImageToImage", - "ImageInpaintLegacy" - ], - "ModelFiles": [ - "https://huggingface.co/TheyCallMeHex/Inkpunk-Diffusion-ONNX/resolve/main/tokenizer/model.onnx", - "https://huggingface.co/TheyCallMeHex/Inkpunk-Diffusion-ONNX/resolve/main/unet/model.onnx", - "https://huggingface.co/TheyCallMeHex/Inkpunk-Diffusion-ONNX/resolve/main/unet/model.onnx_data", - "https://huggingface.co/TheyCallMeHex/Inkpunk-Diffusion-ONNX/resolve/main/text_encoder/model.onnx", - "https://huggingface.co/TheyCallMeHex/Inkpunk-Diffusion-ONNX/resolve/main/vae_decoder/model.onnx", - "https://huggingface.co/TheyCallMeHex/Inkpunk-Diffusion-ONNX/resolve/main/vae_encoder/model.onnx" - ], - "Images": [ - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Inkpunk-Diffusion/Preview1.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Inkpunk-Diffusion/Preview2.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Inkpunk-Diffusion/Preview3.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Inkpunk-Diffusion/Preview4.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Inkpunk-Diffusion/Preview5.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Inkpunk-Diffusion/Preview6.png" - ] + "Name": "StableDiffusion XL", + "ImageIcon": "", + "Rank": 99, + "Author": "OnnxStack", + "Category": "StableDiffusion", + "Template": "StableDiffusionXL", + "StableDiffusionTemplate": { + "ModelType": "Base", + "PipelineType": "StableDiffusionXL", + "DiffuserTypes": [ + "TextToImage", + "ImageToImage", + "ImageInpaintLegacy" + ] + } }, { - "Name": "Dreamshaper v7(LCM)", - "Description": "DreamShaper started as a model to have an alternative to MidJourney in the open source world.", - "Author": "TheyCallMeHex", - "Repository": "https://huggingface.co/TheyCallMeHex/LCM-Dreamshaper-V7-ONNX", - "ImageIcon": "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/LCM-Dreamshaper-V7/Icon.png", - "Status": "Active", - "PadTokenId": 49407, - "BlankTokenId": 49407, - "TokenizerLimit": 77, - "TokenizerLength": 768, - "TokenizerType": "One", - "ScaleFactor": 0.18215, - "SampleSize": 512, - "PipelineType": "LatentConsistency", - "Diffusers": [ - "TextToImage", - "ImageToImage", - "ImageInpaintLegacy" - ], - "ModelFiles": [ - "https://huggingface.co/TheyCallMeHex/LCM-Dreamshaper-V7-ONNX/resolve/main/tokenizer/model.onnx", - "https://huggingface.co/TheyCallMeHex/LCM-Dreamshaper-V7-ONNX/resolve/main/unet/model.onnx", - "https://huggingface.co/TheyCallMeHex/LCM-Dreamshaper-V7-ONNX/resolve/main/unet/model.onnx_data", - "https://huggingface.co/TheyCallMeHex/LCM-Dreamshaper-V7-ONNX/resolve/main/text_encoder/model.onnx", - "https://huggingface.co/TheyCallMeHex/LCM-Dreamshaper-V7-ONNX/resolve/main/vae_decoder/model.onnx", - "https://huggingface.co/TheyCallMeHex/LCM-Dreamshaper-V7-ONNX/resolve/main/vae_encoder/model.onnx" - ], - "Images": [ - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/LCM-Dreamshaper-V7/Preview1.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/LCM-Dreamshaper-V7/Preview2.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/LCM-Dreamshaper-V7/Preview3.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/LCM-Dreamshaper-V7/Preview4.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/LCM-Dreamshaper-V7/Preview5.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/LCM-Dreamshaper-V7/Preview6.png" - ] + "Name": "StableDiffusion XL Inpaint", + "ImageIcon": "", + "Rank": 0, + "Author": "OnnxStack", + "Category": "StableDiffusion", + "Template": "StableDiffusionXLInpaint", + "StableDiffusionTemplate": { + "ModelType": "Base", + "PipelineType": "StableDiffusionXL", + "DiffuserTypes": [ + "ImageInpaint" + ] + } }, { - "Name": "Mo-Di Diffusion", - "Description": "The tokens for Mo-Di Diffusion are: modern disney style", - "Author": "TheyCallMeHex", - "Repository": "https://huggingface.co/TheyCallMeHex/Mo-Di-Diffusion-ONNX", - "ImageIcon": "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Mo-Di-Diffusion/Icon.png", - "Status": "Active", - "PadTokenId": 49407, - "BlankTokenId": 49407, - "TokenizerLimit": 77, - "TokenizerLength": 768, - "TokenizerType": "One", - "ScaleFactor": 0.18215, - "SampleSize": 512, - "PipelineType": "StableDiffusion", - "Diffusers": [ - "TextToImage", - "ImageToImage", - "ImageInpaintLegacy" - ], - "ModelFiles": [ - "https://huggingface.co/TheyCallMeHex/Mo-Di-Diffusion-ONNX/resolve/main/tokenizer/model.onnx", - "https://huggingface.co/TheyCallMeHex/Mo-Di-Diffusion-ONNX/resolve/main/unet/model.onnx", - "https://huggingface.co/TheyCallMeHex/Mo-Di-Diffusion-ONNX/resolve/main/unet/model.onnx_data", - "https://huggingface.co/TheyCallMeHex/Mo-Di-Diffusion-ONNX/resolve/main/text_encoder/model.onnx", - "https://huggingface.co/TheyCallMeHex/Mo-Di-Diffusion-ONNX/resolve/main/vae_decoder/model.onnx", - "https://huggingface.co/TheyCallMeHex/Mo-Di-Diffusion-ONNX/resolve/main/vae_encoder/model.onnx" - ], - "Images": [ - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Mo-Di-Diffusion/Preview1.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Mo-Di-Diffusion/Preview2.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Mo-Di-Diffusion/Preview3.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Mo-Di-Diffusion/Preview4.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Mo-Di-Diffusion/Preview5.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Mo-Di-Diffusion/Preview6.png" - ] + "Name": "StableDiffusion XL Refiner", + "ImageIcon": "", + "Rank": 0, + "Author": "OnnxStack", + "Category": "StableDiffusion", + "Template": "StableDiffusionXLRefiner", + "StableDiffusionTemplate": { + "ModelType": "Base", + "PipelineType": "StableDiffusionXL", + "DiffuserTypes": [ + "TextToImage", + "ImageToImage", + "ImageInpaintLegacy" + ] + } }, { - "Name": "OpenJourney V4", - "Description": "", - "Author": "TheyCallMeHex", - "Repository": "https://huggingface.co/TheyCallMeHex/OpenJourney-V4-ONNX", - "ImageIcon": "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/OpenJourney-V4/Icon.png", - "Status": "Active", - "PadTokenId": 49407, - "BlankTokenId": 49407, - "TokenizerLimit": 77, - "TokenizerLength": 768, - "TokenizerType": "One", - "ScaleFactor": 0.18215, - "SampleSize": 512, - "PipelineType": "StableDiffusion", - "Diffusers": [ - "TextToImage", - "ImageToImage", - "ImageInpaintLegacy" - ], - "ModelFiles": [ - "https://huggingface.co/TheyCallMeHex/OpenJourney-V4-ONNX/resolve/main/tokenizer/model.onnx", - "https://huggingface.co/TheyCallMeHex/OpenJourney-V4-ONNX/resolve/main/unet/model.onnx", - "https://huggingface.co/TheyCallMeHex/OpenJourney-V4-ONNX/resolve/main/unet/model.onnx_data", - "https://huggingface.co/TheyCallMeHex/OpenJourney-V4-ONNX/resolve/main/text_encoder/model.onnx", - "https://huggingface.co/TheyCallMeHex/OpenJourney-V4-ONNX/resolve/main/vae_decoder/model.onnx", - "https://huggingface.co/TheyCallMeHex/OpenJourney-V4-ONNX/resolve/main/vae_encoder/model.onnx" - ], - "Images": [ - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/OpenJourney-V4/Preview1.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/OpenJourney-V4/Preview2.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/OpenJourney-V4/Preview3.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/OpenJourney-V4/Preview4.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/OpenJourney-V4/Preview5.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/OpenJourney-V4/Preview6.png" - ] + "Name": "Latent Consistency", + "ImageIcon": "", + "Rank": 90, + "Author": "OnnxStack", + "Category": "StableDiffusion", + "Template": "LatentConsistency", + "StableDiffusionTemplate": { + "ModelType": "Base", + "PipelineType": "LatentConsistency", + "DiffuserTypes": [ + "TextToImage", + "ImageToImage", + "ImageInpaintLegacy" + ] + } }, { - "Name": "Redshift-Diffusion", - "Description": "The tokens for Redshift Diffusion are: redshift style", - "Author": "TheyCallMeHex", - "Repository": "https://huggingface.co/TheyCallMeHex/Redshift-Diffusion-ONNX", - "ImageIcon": "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Redshift-Diffusion/Icon.png", - "Status": "Active", - "PadTokenId": 49407, - "BlankTokenId": 49407, - "TokenizerLimit": 77, - "TokenizerLength": 768, - "TokenizerType": "One", - "ScaleFactor": 0.18215, - "SampleSize": 512, - "PipelineType": "StableDiffusion", - "Diffusers": [ - "TextToImage", - "ImageToImage", - "ImageInpaintLegacy" - ], - "ModelFiles": [ - "https://huggingface.co/TheyCallMeHex/Redshift-Diffusion-ONNX/resolve/main/tokenizer/model.onnx", - "https://huggingface.co/TheyCallMeHex/Redshift-Diffusion-ONNX/resolve/main/unet/model.onnx", - "https://huggingface.co/TheyCallMeHex/Redshift-Diffusion-ONNX/resolve/main/unet/model.onnx_data", - "https://huggingface.co/TheyCallMeHex/Redshift-Diffusion-ONNX/resolve/main/text_encoder/model.onnx", - "https://huggingface.co/TheyCallMeHex/Redshift-Diffusion-ONNX/resolve/main/vae_decoder/model.onnx", - "https://huggingface.co/TheyCallMeHex/Redshift-Diffusion-ONNX/resolve/main/vae_encoder/model.onnx" - ], - "Images": [ - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Redshift-Diffusion/Preview1.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Redshift-Diffusion/Preview2.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Redshift-Diffusion/Preview3.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Redshift-Diffusion/Preview4.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Redshift-Diffusion/Preview5.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Redshift-Diffusion/Preview6.png" - ] + "Name": "Latent Consistency XL", + "ImageIcon": "", + "Rank": 90, + "Author": "OnnxStack", + "Category": "StableDiffusion", + "Template": "LatentConsistencyXL", + "StableDiffusionTemplate": { + "ModelType": "Base", + "PipelineType": "LatentConsistencyXL", + "DiffuserTypes": [ + "TextToImage", + "ImageToImage", + "ImageInpaintLegacy" + ] + } }, { - "Name": "Deliberate V3", - "Description": "", - "Author": "TheyCallMeHex", - "Repository": "https://huggingface.co/TheyCallMeHex/Deliberate-V3-ONNX", - "ImageIcon": "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Deliberate-V3/Icon.png", - "Status": "Active", - "PadTokenId": 49407, - "BlankTokenId": 49407, - "TokenizerLimit": 77, - "TokenizerLength": 768, - "TokenizerType": "One", - "ScaleFactor": 0.18215, - "SampleSize": 512, - "PipelineType": "StableDiffusion", - "Diffusers": [ - "TextToImage", - "ImageToImage", - "ImageInpaintLegacy" - ], - "ModelFiles": [ - "https://huggingface.co/TheyCallMeHex/Deliberate-V3-ONNX/resolve/main/tokenizer/model.onnx", - "https://huggingface.co/TheyCallMeHex/Deliberate-V3-ONNX/resolve/main/unet/model.onnx", - "https://huggingface.co/TheyCallMeHex/Deliberate-V3-ONNX/resolve/main/unet/model.onnx_data", - "https://huggingface.co/TheyCallMeHex/Deliberate-V3-ONNX/resolve/main/text_encoder/model.onnx", - "https://huggingface.co/TheyCallMeHex/Deliberate-V3-ONNX/resolve/main/vae_decoder/model.onnx", - "https://huggingface.co/TheyCallMeHex/Deliberate-V3-ONNX/resolve/main/vae_encoder/model.onnx" - ], - "Images": [ - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Deliberate-V3/Preview1.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Deliberate-V3/Preview2.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Deliberate-V3/Preview3.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Deliberate-V3/Preview4.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Deliberate-V3/Preview5.png", - "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/Deliberate-V3/Preview6.png" - ] + "Name": "InstaFlow", + "ImageIcon": "", + "Rank": 0, + "Author": "OnnxStack", + "Category": "StableDiffusion", + "Template": "InstaFlow", + "StableDiffusionTemplate": { + "ModelType": "Base", + "PipelineType": "InstaFlow", + "DiffuserTypes": [ + "TextToImage" + ] + } }, { - "Name": "InstaFlow 0.9B", - "Description": "", - "Author": "TheyCallMeHex", - "Repository": "https://huggingface.co/TheyCallMeHex/InstaFlow-0.9B-ONNX", + "Name": "Upscaler x4", "ImageIcon": "", - "Status": "Active", - "PadTokenId": 49407, - "BlankTokenId": 49407, - "TokenizerLimit": 77, - "TokenizerLength": 768, - "TokenizerType": "One", - "ScaleFactor": 0.18215, - "SampleSize": 512, - "PipelineType": "InstaFlow", - "Diffusers": [ - "TextToImage" - ], - "ModelFiles": [ - "https://huggingface.co/TheyCallMeHex/InstaFlow-0.9B-ONNX/resolve/main/tokenizer/model.onnx", - "https://huggingface.co/TheyCallMeHex/InstaFlow-0.9B-ONNX/resolve/main/unet/model.onnx", - "https://huggingface.co/TheyCallMeHex/InstaFlow-0.9B-ONNX/resolve/main/unet/model.onnx_data", - "https://huggingface.co/TheyCallMeHex/InstaFlow-0.9B-ONNX/resolve/main/text_encoder/model.onnx", - "https://huggingface.co/TheyCallMeHex/InstaFlow-0.9B-ONNX/resolve/main/vae_decoder/model.onnx", - "https://huggingface.co/TheyCallMeHex/InstaFlow-0.9B-ONNX/resolve/main/vae_encoder/model.onnx" - ], - "Images": [ - "", - "", - "", - "", - "", - "" - ] + "Author": "OnnxStack", + "Category": "Upscaler", + "Template": "Upscaler", + "UpscaleTemplate": { + "Channels": 3, + "ScaleFactor": 4, + "SampleSize": 512 + } }, { - "Name": "Stable Diffusion XL Base 1.0", - "Description": "", - "Author": "stabilityai", - "Repository": "https://huggingface.co/stabilityai/stable-diffusion-xl-base-1.0", - "ImageIcon": "", - "Status": "Active", - "PadTokenId": 1, - "BlankTokenId": 49407, - "TokenizerLimit": 77, - "TokenizerLength": 768, - "Tokenizer2Length": 1280, - "TokenizerType": "Both", - "ScaleFactor": 0.13025, - "SampleSize": 1024, - "PipelineType": "StableDiffusionXL", - "Diffusers": [ - "TextToImage", - "ImageToImage", - "ImageInpaint" - ], - "ModelFiles": [ - "https://huggingface.co/stabilityai/stable-diffusion-xl-base-1.0/resolve/main/text_encoder/model.onnx", - "https://huggingface.co/stabilityai/stable-diffusion-xl-base-1.0/resolve/main/text_encoder_2/model.onnx", - "https://huggingface.co/stabilityai/stable-diffusion-xl-base-1.0/resolve/main/text_encoder_2/model.onnx_data", - "https://huggingface.co/stabilityai/stable-diffusion-xl-base-1.0/resolve/main/unet/model.onnx", - "https://huggingface.co/stabilityai/stable-diffusion-xl-base-1.0/resolve/main/unet/model.onnx_data", - "https://huggingface.co/stabilityai/stable-diffusion-xl-base-1.0/resolve/main/vae_decoder/model.onnx", - "https://huggingface.co/stabilityai/stable-diffusion-xl-base-1.0/resolve/main/vae_encoder/model.onnx" + "Name": "Stable Diffusion 1.5", + "ImageIcon": "https://www.runwayml.com/images/logo-square.png", + "Author": "RunwayML", + "Description": "Stable Diffusion is a text-to-image latent diffusion model created by the researchers and engineers from CompVis, Stability AI and LAION. It is trained on 512x512 images from a subset of the LAION-5B database. LAION-5B is the largest, freely accessible multi-modal dataset that currently exists.", + "IsUserTemplate": true, + "Template": "StableDiffusion", + "Category": "StableDiffusion", + "StableDiffusionTemplate": { + "PipelineType": "StableDiffusion", + "ModelType": "Base", + "SampleSize": 512, + "DiffuserTypes": [ + "TextToImage", + "ImageToImage", + "ImageInpaintLegacy" + ] + }, + "Repository": "https://huggingface.co/runwayml/stable-diffusion-v1-5", + "RepositoryBranch": "onnx", + "RepositoryFiles": [ + "https://huggingface.co/runwayml/stable-diffusion-v1-5/resolve/onnx/unet/model.onnx", + "https://huggingface.co/runwayml/stable-diffusion-v1-5/resolve/onnx/unet/weights.pb", + "https://huggingface.co/runwayml/stable-diffusion-v1-5/resolve/onnx/text_encoder/model.onnx", + "https://huggingface.co/runwayml/stable-diffusion-v1-5/resolve/onnx/vae_decoder/model.onnx", + "https://huggingface.co/runwayml/stable-diffusion-v1-5/resolve/onnx/vae_encoder/model.onnx" ], - "Images": [ - "", - "", - "", - "", - "", - "" + "PreviewImages": [ + "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/stable-diffusion-v1-5/Preview1.png", + "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/stable-diffusion-v1-5/Preview2.png", + "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/stable-diffusion-v1-5/Preview3.png", + "https://raw.githubusercontent.com/saddam213/OnnxStack/master/Assets/Templates/stable-diffusion-v1-5/Preview4.png" ] } ]