Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
A VSR (Super Resolução de Vídeo) é uma tecnologia de amostragem de vídeo baseada em IA que aprimora de forma inteligente fluxos de vídeo de baixa resolução de pessoas, restaurando nitidez e detalhes que, de outra forma, seriam perdidos devido a limitações de largura de banda, condições de rede ruins, compactação ou conteúdo de origem de baixa qualidade.
Adicionar recursos do VSR ao seu aplicativo habilita cenários, incluindo o seguinte:
- Melhorando a qualidade do vídeo em conexões de rede precárias
- Otimização de largura de banda para reduzir os custos da CDN
- Cenários de alta largura de banda, como chamadas de vídeo em grupo com vários participantes
- Melhorando a qualidade do vídeo nas redes sociais na edição, upload ou exibição
O recurso VSR atualmente requer um pc Copilot+ com uma NPU. Para obter mais informações, consulte Desenvolver aplicativos de IA para PCs Copilot+.
Essas APIs VSR usam modelos de ML (Machine Learning) e foram projetadas especificamente para cenários como chamadas de vídeo, aplicativos de conferência, vídeos sociais e vídeos curtos que apresentam rostos humanos falando.
Atualmente, o VSR dá suporte aos seguintes intervalos de resolução, formato e FPS:
| Attribute | Conteúdo com suporte |
|---|---|
| Resolução de entrada | 240p – 1440p |
| Resolução de saída | 480p – 1440p |
| Intervalo FPS (quadros por segundo) | 15 fps – 60 fps |
| Formato de pixel de entrada | BGR (API imagebuffer), NV12 (API Direct3D) |
| Formato de píxel de saída | BGR (API ImageBuffer), BGRA (API Direct3D) |
Criar uma sessão do VideoScaler
O exemplo a seguir mostra como criar uma sessão VSR. Primeiro, obtenha uma instância de ExecutionProviderCatalog e chame EnsureAndRegisterCertifiedAsync para carregar os modelos disponíveis. Chame GetReadyState na classe VideoScalar para determinar se o dimensionador de vídeo está pronto para processar quadros. Caso contrário, chame EnsureReadyAsync para inicializar o dimensionador de vídeo.
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();
}
Escalonar um VideoFrame
O exemplo de código a seguir usa o método VideoScaler.ScaleFrame para dimensionar os dados de imagem contidos em um objeto VideoFrame . Você pode obter o VideoFrame de uma câmera usando a classe MediaFrameReader . Para mais informações, consulte Processamento de quadros de mídia com MediaFrameReader. Você também pode usar o controle CameraPreview do Kit de Ferramentas da Comunidade WinUI para obter objetos VideoFrame da câmera.
Em seguida, um Direct3DSurface é obtido do frame de vídeo de entrada e outro Direct3DSurface é criado para a saída do upscaling. VideoScaler.ScaleFrame é chamado para ampliar o quadro. Neste exemplo, um controle Imagem na interface do usuário do app é atualizado com o frame ampliado.
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;
}
});
}
Dimensionar um SoftwareBitmap usando o ImageBuffer
O exemplo de código a seguir demonstra o uso da classe VideoScalar para dimensionar um SoftwareBitmap. Este exemplo não representa um uso típico das APIs vsr. Ele é menos performante do que usar o Direct3D. Mas você pode usar este exemplo para experimentar as APIs do VSR sem configurar uma câmera ou pipeline de streaming de vídeo. Como o dimensionador de vídeo requer um BGR8 ao usar um ImageBuffer, alguns métodos auxiliares são necessários para converter o formato de pixel do SoftwareBitmap fornecido.
O código de exemplo neste artigo baseia-se no componente VSR dos exemplos da API de IA do Windows
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étodos de extensão de bitmap de software
Os métodos auxiliares a seguir convertem um SoftwareBitmap entre os formatos BGRA8 e BGR8 para corresponder aos requisitos de entrada e saída do escalar de vídeo.
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;
}
IA responsável
Usamos uma combinação das etapas a seguir para garantir que essas APIs de imagem sejam confiáveis, seguras e criadas com responsabilidade. Recomendamos revisar as práticas recomendadas descritas no Desenvolvimento Responsável de IA Generativa no Windows ao implementar recursos de IA em seu aplicativo.
Essas APIs VSR usam modelos de ML (Machine Learning), foram projetadas especificamente para cenários como aplicativos de chamada e conferência de vídeo e vídeos sociais e de formato curto que apresentam rostos humanos falando. Portanto, não recomendamos o uso dessas APIs para imagens nos seguintes cenários:
- Onde as imagens contêm conteúdo potencialmente confidencial e descrições imprecisas podem ser controversas, como sinalizadores, mapas, globos, símbolos culturais ou símbolos religiosos.
- Quando descrições precisas são críticas, como para orientação médica ou diagnóstico, conteúdo legal ou documentos financeiros.