Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Video Super Resolution (VSR) est une technologie d'amélioration vidéo basée sur l'IA qui met intelligemment à l’échelle des flux vidéo à faible résolution contenant des images de personnes, restaurant la netteté et les détails qui seraient autrement perdus en raison des limitations de bande passante, des conditions réseau médiocres, de la compression ou d'un contenu source de qualité inférieure.
L’ajout de fonctionnalités VSR à votre application permet des scénarios, notamment les suivants :
- Amélioration de la qualité de la vidéo sur les connexions réseau médiocres
- Optimisation de la bande passante pour réduire les coûts CDN
- Scénarios à bande passante élevée comme les appels vidéo de groupe avec plusieurs participants
- Amélioration de la qualité vidéo des médias sociaux en édition, chargement ou affichage
La fonctionnalité VSR nécessite actuellement un PC Copilot+ avec un NPU. Pour plus d’informations, consultez Développer des applications IA pour pc Copilot+.
Ces API VSR utilisent des modèles Machine Learning (ML), ont été conçues spécifiquement pour des scénarios tels que les applications d’appel vidéo et de conférence, ainsi que les vidéos de forme courte et sociale qui présentent des visages humains parlant
VSR prend actuellement en charge les plages de résolution, de format et FPS suivantes :
| Caractéristique | Contenu pris en charge |
|---|---|
| Résolution d’entrée | 240p – 1440p |
| Résolution de sortie | 480p – 1440p |
| Plage images par seconde (FPS) | 15 fps – 60 fps |
| Format de pixel d’entrée | BGR (API ImageBuffer), NV12 (API Direct3D) |
| Format de pixel de sortie | BGR (API ImageBuffer), BGRA (API Direct3D) |
Créer une session VideoScaler
L’exemple suivant montre comment créer une session VSR. Tout d’abord, obtenez une instance d’ExecutionProviderCatalog et appelez EnsureAndRegisterCertifiedAsync pour charger les modèles disponibles. Appelez GetReadyState sur la classe VideoScalar pour déterminer si le scaler vidéo est prêt à traiter des images. Si ce n’est pas le cas, appelez EnsureReadyAsync pour initialiser le scaler vidéo.
private VideoScaler? _videoScaler;
protected override async Task LoadModelAsync(SampleNavigationParameters sampleParams)
{
try
{
var catalog = ExecutionProviderCatalog.GetDefault();
await catalog.EnsureAndRegisterCertifiedAsync();
var readyState = VideoScaler.GetReadyState();
if (readyState == AIFeatureReadyState.NotReady)
{
var operation = await VideoScaler.EnsureReadyAsync();
if (operation.Status != AIFeatureReadyResultState.Success)
{
ShowException(null, "Video Scaler is not available.");
}
}
_videoScaler = await VideoScaler.CreateAsync();
}
catch (Exception ex)
{
ShowException(ex, "Failed to load model.");
}
sampleParams.NotifyCompletion();
}
Mettre à l’échelle un VideoFrame
L’exemple de code suivant utilise la méthode VideoScaler.ScaleFrame pour mettre à l’échelle les données d’image contenues dans un objet VideoFrame . Vous pouvez obtenir VideoFrame à partir d’une caméra à l’aide de la classe MediaFrameReader . Pour plus d’informations, consultez Traiter les trames multimédias avec MediaFrameReader. Vous pouvez également utiliser le contrôle CameraPreview WinUI Community Toolkit pour obtenir des objets VideoFrame à partir de la caméra.
Ensuite, un Direct3DSurface est obtenu à partir de l’image vidéo d’entrée et un autre Direct3DSurface est créé pour la sortie de la mise à l’échelle. VideoScaler.ScaleFrame est appelé pour agrandir l'image. Dans cet exemple, un contrôle Image dans l’interface utilisateur de l’application est mis à jour avec la trame agrandie.
private async Task ProcessFrame(VideoFrame videoFrame)
{
// Process the frame with super resolution model
var processedBitmap = await Task.Run(async () =>
{
int width = 0;
int height = 0;
var inputD3dSurface = videoFrame.Direct3DSurface;
if (inputD3dSurface != null)
{
Debug.Assert(inputD3dSurface.Description.Format == Windows.Graphics.DirectX.DirectXPixelFormat.NV12, "input in NV12 format");
width = inputD3dSurface.Description.Width;
height = inputD3dSurface.Description.Height;
}
else
{
var softwareBitmap = videoFrame.SoftwareBitmap;
if (softwareBitmap == null)
{
return null;
}
Debug.Assert(softwareBitmap.BitmapPixelFormat == BitmapPixelFormat.Nv12, "input in NV12 format");
width = softwareBitmap.PixelWidth;
height = softwareBitmap.PixelHeight;
}
try
{
if (inputD3dSurface == null)
{
// Create Direct3D11-backed VideoFrame for input
using var inputVideoFrame = VideoFrame.CreateAsDirect3D11SurfaceBacked(
Windows.Graphics.DirectX.DirectXPixelFormat.NV12,
width,
height);
if (inputVideoFrame.Direct3DSurface == null)
{
return null;
}
// Copy the software bitmap to the Direct3D-backed frame
await videoFrame.CopyToAsync(inputVideoFrame);
inputD3dSurface = inputVideoFrame.Direct3DSurface;
}
// Create or resize output surface (BGRA8 format for display)
if (_outputD3dSurface == null || _outputWidth != width || _outputHeight != height)
{
_outputD3dSurface?.Dispose();
// DXGI_FORMAT_B8G8R8A8_UNORM = 87
_outputD3dSurface = Direct3DExtensions.CreateDirect3DSurface(87, width, height);
_outputWidth = width;
_outputHeight = height;
}
// Scale the frame using VideoScaler
var result = _videoScaler!.ScaleFrame(inputD3dSurface, _outputD3dSurface, new VideoScalerOptions());
if (result.Status == ScaleFrameStatus.Success)
{
var outputBitmap = await SoftwareBitmap.CreateCopyFromSurfaceAsync(
_outputD3dSurface,
BitmapAlphaMode.Premultiplied);
return outputBitmap;
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"ProcessFrame error: {ex.Message}");
}
return null;
});
if (processedBitmap == null)
{
return;
}
DispatcherQueue.TryEnqueue(async () =>
{
using (processedBitmap)
{
var source = new SoftwareBitmapSource();
await source.SetBitmapAsync(processedBitmap);
ProcessedVideoImage.Source = source;
}
});
}
Mettre à l’échelle un SoftwareBitmap à l’aide d’ImageBuffer
L’exemple de code suivant illustre l’utilisation de la classe VideoScalar pour mettre à l’échelle un SoftwareBitmap. Cet exemple ne représente pas une utilisation classique des API VSR. Il est moins performant que l’utilisation de Direct3D. Toutefois, vous pouvez utiliser cet exemple pour tester les API VSR sans configurer de pipeline de diffusion vidéo ou de caméra. Étant donné que la mise à l'échelle vidéo nécessite un BGR8 lors de l’utilisation d’un ImageBuffer, certaines méthodes utilitaires sont requises pour convertir le format de pixel du SoftwareBitmap fourni.
L’exemple de code de cet article est basé sur le composant VSR des exemples d’API Windows AI
public SoftwareBitmap ScaleVideoFrame(SoftwareBitmap inputFrame)
{
ImageBuffer inputImageBuffer = SoftwareBitmapExtensions.ConvertToBgr8ImageBuffer(inputFrame);
var size = (uint)(inputFrame.PixelWidth * inputFrame.PixelHeight * 3);
IBuffer outputBuffer = new global::Windows.Storage.Streams.Buffer(size);
outputBuffer.Length = size;
ImageBuffer outputImageBuffer = ImageBuffer.CreateForBuffer(
outputBuffer,
ImageBufferPixelFormat.Bgr8,
inputFrame.PixelWidth,
inputFrame.PixelHeight,
inputFrame.PixelWidth * 3);
var result = Session.ScaleFrame(inputImageBuffer, outputImageBuffer, new VideoScalerOptions());
if (result.Status != ScaleFrameStatus.Success)
{
throw new Exception($"Failed to scale video frame: {result.Status}");
}
return SoftwareBitmapExtensions.ConvertBgr8ImageBufferToBgra8SoftwareBitmap(outputImageBuffer);
}
Méthodes d’extension bitmap logicielle
Les méthodes d’assistance suivantes convertissent un SoftwareBitmap entre les formats BGRA8 et BGR8 pour correspondre aux exigences d’entrée et de sortie du scalaire vidéo.
public static ImageBuffer ConvertToBgr8ImageBuffer(SoftwareBitmap input)
{
var bgraBitmap = input;
if (input.BitmapPixelFormat != BitmapPixelFormat.Bgra8)
{
bgraBitmap = SoftwareBitmap.Convert(input, BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied);
}
int width = bgraBitmap.PixelWidth;
int height = bgraBitmap.PixelHeight;
byte[] bgraBuffer = new byte[width * height * 4];
bgraBitmap.CopyToBuffer(bgraBuffer.AsBuffer());
byte[] bgrBuffer = new byte[width * height * 3];
for (int i = 0, j = 0; i < bgraBuffer.Length; i += 4, j += 3)
{
bgrBuffer[j] = bgraBuffer[i];
bgrBuffer[j + 1] = bgraBuffer[i + 1];
bgrBuffer[j + 2] = bgraBuffer[i + 2];
}
return ImageBuffer.CreateForBuffer(
bgrBuffer.AsBuffer(),
ImageBufferPixelFormat.Bgr8,
width,
height,
width * 3);
}
public static SoftwareBitmap ConvertBgr8ImageBufferToBgra8SoftwareBitmap(ImageBuffer bgrImageBuffer)
{
if (bgrImageBuffer.PixelFormat != ImageBufferPixelFormat.Bgr8)
{
throw new ArgumentException("Input ImageBuffer must be in Bgr8 format");
}
int width = bgrImageBuffer.PixelWidth;
int height = bgrImageBuffer.PixelHeight;
// Get BGR data from ImageBuffer
byte[] bgrBuffer = new byte[width * height * 3];
bgrImageBuffer.CopyToByteArray(bgrBuffer);
// Create BGRA buffer (4 bytes per pixel)
byte[] bgraBuffer = new byte[width * height * 4];
for (int i = 0, j = 0; i < bgrBuffer.Length; i += 3, j += 4)
{
bgraBuffer[j] = bgrBuffer[i]; // B
bgraBuffer[j + 1] = bgrBuffer[i + 1]; // G
bgraBuffer[j + 2] = bgrBuffer[i + 2]; // R
bgraBuffer[j + 3] = 255; // A (full opacity)
}
// Create SoftwareBitmap and copy data
var softwareBitmap = new SoftwareBitmap(
BitmapPixelFormat.Bgra8,
width,
height,
BitmapAlphaMode.Premultiplied);
softwareBitmap.CopyFromBuffer(bgraBuffer.AsBuffer());
return softwareBitmap;
}
Intelligence artificielle responsable
Nous avons utilisé une combinaison des étapes suivantes pour garantir que ces API d’imagerie sont fiables, sécurisées et générées de manière responsable. Nous vous recommandons de consulter les meilleures pratiques décrites dans développement d’IA responsable sur Windows lors de l’implémentation de fonctionnalités IA dans votre application.
Ces API VSR utilisent des modèles Machine Learning (ML), conçues spécifiquement pour des scénarios tels que des applications d’appel vidéo et de conférence, ainsi que des vidéos de forme courte et sociale qui présentent des visages humains parlant. Par conséquent, nous vous déconseillons d’utiliser ces API pour les images dans les scénarios suivants :
- Lorsque les images contiennent du contenu potentiellement sensible et des descriptions inexactes peuvent être controversées, telles que des drapeaux, des cartes, des globes, des symboles culturels ou des symboles religieux.
- Lorsque des descriptions précises sont essentielles, comme pour les conseils médicaux ou le diagnostic, le contenu juridique ou les documents financiers.