Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
using var inputImage = await LoadYourImageAsSoftwareBitmap();
using ImageForegroundExtractor extractor = await ImageForegroundExtractor.CreateAsync();
using var foregroundMask = extractor.GetMaskFromSoftwareBitmap(inputImage);
// Apply the mask to extract the foreground
var foregroundImage = inputImage.ApplyMask(foregroundMask);
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
if (ImageForegroundExtractor.GetReadyState() == AIFeatureReadyState.NotReady)
{
await ImageForegroundExtractor.EnsureReadyAsync();
}
3 changes: 3 additions & 0 deletions Samples/WindowsAIFoundry/cs-winui/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
<NavigationViewItem Content="Image Object Extractor"
Tag="ImageObjectExtractor"
Icon="Cut"/>
<NavigationViewItem Content="Image Foreground Extractor"
Tag="ImageForegroundExtractor"
Icon="ContactInfo"/>
<NavigationViewItem Content="Image Description"
Tag="ImageDescription"
Icon="Caption"/>
Expand Down
3 changes: 3 additions & 0 deletions Samples/WindowsAIFoundry/cs-winui/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ private void NavView_SelectionChanged(NavigationView sender, NavigationViewSelec
case "ImageObjectExtractor":
rootFrame.Navigate(typeof(ImageObjectExtractorPage));
break;
case "ImageForegroundExtractor":
rootFrame.Navigate(typeof(ImageForegroundExtractorPage));
break;
case "ImageDescription":
rootFrame.Navigate(typeof (ImageDescriptionPage));
break;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using WindowsAISample.Models.Contracts;
using System;
using System.Threading;
using System.Threading.Tasks;
using Windows.Graphics.Imaging;
using Microsoft.Windows.AI;
using Microsoft.Windows.AI.Imaging;

namespace WindowsAISample.Models;

class ImageForegroundExtractorModel : IModelManager
{
public async Task CreateModelSessionWithProgress(IProgress<double> progress, CancellationToken cancellationToken = default)
{
if (ImageForegroundExtractor.GetReadyState() == AIFeatureReadyState.NotReady)
{
var foregroundExtractorDeploymentOperation = ImageForegroundExtractor.EnsureReadyAsync();
foregroundExtractorDeploymentOperation.Progress = (_, modelDeploymentProgress) =>
{
progress.Report(modelDeploymentProgress % 0.75); // all progress is within 75%
};
using var _ = cancellationToken.Register(() => foregroundExtractorDeploymentOperation.Cancel());
await foregroundExtractorDeploymentOperation;
}
else
{
progress.Report(0.75);
}
progress.Report(1.0); // 100% progress
}

public async Task<SoftwareBitmap> ExtractForegroundMaskAsync(SoftwareBitmap inputImage, CancellationToken cancellationToken = default)
{
using var extractor = await ImageForegroundExtractor.CreateAsync();
return extractor.GetMaskFromSoftwareBitmap(inputImage);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<!-- Copyright (c) Microsoft Corporation.
Licensed under the MIT License. -->
<Page
x:Class="WindowsAISample.Pages.ImageForegroundExtractorPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:WindowsAISample"
xmlns:pages="using:WindowsAISample.Pages"
xmlns:models="using:WindowsAISample.ViewModels"
xmlns:controls="using:WindowsAISample.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DataContext="{d:DesignInstance Type=models:ImageForegroundExtractorViewModel}"
mc:Ignorable="d"
DataContext="{Binding ImageForegroundExtractor}"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

<ScrollViewer VerticalScrollBarVisibility="Auto"
HorizontalAlignment="Stretch">
<StackPanel Orientation="Vertical"
HorizontalAlignment="Stretch"
Margin="20">
<TextBlock Text="Image Foreground Extractor"
Style="{StaticResource TitleTextBlockStyle}"
Margin="10"/>
<TextBlock Text="The Image Foreground Extractor API lets you automatically extract the foreground from an image using an AI model, creating a mask that separates the main subject from the background."
Style="{StaticResource BodyTextBlockStyle}"
Margin="10"/>

<controls:ModelInitializationControl SourceFile="Examples/ImageForegroundExtractorInit.md"/>

<TextBlock Text="Extract Foreground"
Style="{StaticResource SubtitleTextBlockStyle}"
Margin="10"/>
<TextBlock Text="Once the model is available, click the button below to automatically extract the foreground from the input image."
Style="{StaticResource BodyTextBlockStyle}"
Margin="10"/>

<Border Margin="10"
CornerRadius="10"
BorderThickness="2"
BorderBrush="{ThemeResource CardBackgroundFillColorSecondaryBrush}"
Background="{ThemeResource CardBackgroundFillColorDefault}">
<StackPanel Orientation="Vertical">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel Orientation="Vertical"
Margin="10">
<TextBlock Margin="10"
Style="{StaticResource BodyStrongTextBlockStyle}">Input image</TextBlock>
<Image x:Name="InputImage"
Source="{Binding InputSource}"
Stretch="Uniform"/>
</StackPanel>
<StackPanel Orientation="Vertical"
Grid.Column="1"
HorizontalAlignment="Center"
Margin="10">
<TextBlock Margin="10"
Style="{StaticResource BodyStrongTextBlockStyle}">Output image</TextBlock>
<Image x:Name="OutputImage"
Source="{Binding ExtractForegroundCommand.Result}"/>
</StackPanel>
</Grid>

<StackPanel Orientation="Horizontal"
HorizontalAlignment="Left"
Margin="10">
<Button Margin="0,0,10,0"
Command="{Binding PickInputImageCommand}">Load Image</Button>
<Button Margin="0,0,10,0"
Command="{Binding ExtractForegroundCommand}"
IsEnabled="{Binding IsAvailable}">Extract Foreground</Button>
<ProgressRing Visibility="{Binding ExtractForegroundCommand.IsExecuting, Converter={StaticResource BoolToVisibilityConverter}}"/>
</StackPanel>

<controls:CodeBlockControl SourceFile="Examples/ImageForegroundExtractor.md"
Margin="10"/>
</StackPanel>
</Border>
</StackPanel>
</ScrollViewer>
</Page>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using Microsoft.UI.Xaml.Controls;

namespace WindowsAISample.Pages;

/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class ImageForegroundExtractorPage : Page
{
public ImageForegroundExtractorPage()
{
InitializeComponent();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ internal CopilotRootViewModel()
ImageObjectExtractor = new(new Models.ImageObjectExtractorModel());
ImageDescriptionGenerator = new(new Models.ImageDescriptionModel());
ImageObjectRemover = new(new Models.ImageObjectRemoverModel());
ImageForegroundExtractor = new(new Models.ImageForegroundExtractorModel());
}

public LanguageModelViewModel LanguageModel { get; }
Expand All @@ -30,4 +31,6 @@ internal CopilotRootViewModel()
public ImageObjectExtractorViewModel ImageObjectExtractor { get; }

public ImageObjectRemoverViewModel ImageObjectRemover { get; }

public ImageForegroundExtractorViewModel ImageForegroundExtractor { get; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using WindowsAISample.Models.Contracts;
using WindowsAISample.Util;
using Microsoft.UI.Xaml.Media.Imaging;
using System;
using System.Windows.Input;
using Windows.Graphics.Imaging;
using WindowsAISample.Models;

namespace WindowsAISample.ViewModels;

internal partial class ImageForegroundExtractorViewModel : InputImageViewModelBase<ImageForegroundExtractorModel>
{
private readonly AsyncCommand<SoftwareBitmap, SoftwareBitmapSource> _extractForegroundCommand;

public ImageForegroundExtractorViewModel(ImageForegroundExtractorModel imageForegroundExtractorSession)
: base(imageForegroundExtractorSession)
{
_extractForegroundCommand = new(
async _ =>
{
if (Input == null)
{
throw new InvalidOperationException();
}

var foregroundMask = await Session.ExtractForegroundMaskAsync(Input);
var outputBitmap = Input.ApplyMask(foregroundMask);

return await DispatcherQueue.EnqueueAsync(async () =>
{
return await outputBitmap.ToSourceAsync();
});
},
(_) => IsAvailable && Input is not null);
}

public ICommand ExtractForegroundCommand => _extractForegroundCommand;

protected override void OnIsAvailableChanged()
{
_extractForegroundCommand.FireCanExecuteChanged();
}
}