Lenguaje

Introducción a AI Video Super Resolution (VSR)

La Súper Resolución de Video (VSR) es una tecnología de escalado de vídeo basada en IA que escala inteligentemente las secuencias de vídeo de baja resolución, restaurando la nitidez y los detalles que, de lo contrario, se perderían debido a limitaciones de ancho de banda, condiciones de red deficientes, compresión o contenido de origen de menor calidad.

La adición de funcionalidades de VSR a la aplicación permite escenarios que incluyen lo siguiente:

  • Mejora de la calidad del vídeo a través de conexiones de red deficientes
  • Optimización del ancho de banda para reducir los costos de la red CDN
  • Escenarios de alto ancho de banda, como las videollamadas grupales con varios participantes
  • Mejora de la calidad del vídeo de redes sociales en la edición, carga o visualización

La característica VSR está disponible en Copilot+ PCs con una NPU y en dispositivos que cumplen las especificaciones de CPU recommendadas. Para obtener más información, consulte Desarrollo de aplicaciones de IA para equipos Copilot+ PC y la tabla de hardware compatible.

Compatibilidad del hardware

Hardware Situación Detalles
NPU (Copilot+ PC) ✅ Disponible Mejor rendimiento. Consulte Copilot+ PCs guía para desarrolladores.
Unidad Central de Procesamiento (CPU) ✅ Disponible Mejor en los dispositivos que cumplen las especificaciones de CPU recomendadas. VSR seguirá intentando ejecutarse en dispositivos de especificación inferior, pero la calidad en tiempo real y la velocidad de fotogramas pueden sufrir.
Unidad de Procesamiento Gráfico (GPU) ❌ No es compatible VSR no está disponible en GPU.

Note

La selección de hardware es automática. En un PC Copilot+ con una NPU, VSR siempre se ejecuta en la NPU. En dispositivos que no son de Copilot+, VSR se ejecuta automáticamente en la CPU; no hay ningún usuario final o desarrollador que seleccione CPU en un dispositivo Copilot+. Esto coincide con el patrón usado por otras API de IA de Windows; consulte Hardware compatible para ver la vista entre API.

Estas API de VSR usan modelos de Machine Learning (ML) diseñados específicamente para escenarios como aplicaciones de videollamadas y conferencias y vídeos sociales y de formato corto que incluyen caras humanas hablando

VSR admite actualmente los siguientes intervalos de resolución, formato y FPS:

Atributo Contenido compatible
Resolución de entrada 240p – 1440p
Resolución de salida 480p – 1440p (4K para el procesamiento de vídeo sin conexión)
Intervalo de fotogramas por segundo (FPS) 15 fps: 60 fps
Formato de píxel de entrada BGR (ImageBuffer API), NV12 (API de Direct3D)
Formato de píxel de salida BGR (ImageBuffer API), BGRA y NV12 (API de Direct3D)

El modelo de VSR se entrega como parte del SDK de Aplicaciones para Windows, por lo que no hay ningún paso de consentimiento de descarga o primera ejecución independiente en dispositivos de CPU. VSR se ejecutará en cualquier CPU en la que se ejecuten el resto de las API de IA de Windows, pero la calidad del escalado en tiempo real y la frecuencia de fotogramas dependerán de la CPU del equipo host.

Para obtener un buen rendimiento del procesador, elija dispositivos que cumplan todas las siguientes especificaciones recomendadas:

  • 4 o más núcleos físicos
  • Reloj base de 3 GHz o superior
  • 32 MB o más de caché L3

Estas son recomendaciones, no mínimos duros: la API seguirá intentando escalar en dispositivos de especificación inferiores. Las aplicaciones que tienen como destino un amplio rango de CPU deben consultar la CPU en tiempo de ejecución y, si el dispositivo está debajo de la barra recomendada, vuelva a una canalización que no sea VSR o muestre una sugerencia de compensación de calidad al usuario.

Note

GetReadyState y la comprobación de las especificaciones de la CPU responden a preguntas diferentes y deben usarse juntas. GetReadyState indica si VSR es compatible con el dispositivo (si el modelo está cargado, si los controladores están presentes y si la directiva de hardware lo permite). La comprobación de las especificaciones de la CPU indica si VSR funcionará suficientemente bien para tu experiencia de usuario. Utilice GetReadyState para decidir si se debe usar VSR; utilice la comprobación de la CPU para decidir entre VSR y una alternativa ligera (como el reescalado bilineal) en hardware con prestaciones ajustadas.

Comprobación del nivel de compatibilidad de CPU

El ejemplo de C# siguiente usa Windows Management Instrumentation (WMI) para consultar la clase /> cuando el dispositivo cumple las especificaciones recomendadas. El ejemplo usa el paquete NuGet System.Management publicado por Microsoft —la biblioteca contenedora estándar de .NET para WMI— para realizar llamadas a WMI desde C#.

using System;
using System.Management;

private static bool MeetsRecommendedCpuSpecs()
{
    const int RecommendedCores      = 4;
    const int RecommendedClockMhz   = 3000;
    const int RecommendedL3CacheKb  = 32 * 1024; // 32 MB

    int totalCores   = 0;
    int maxClockMhz  = 0;
    int maxL3CacheKb = 0;

    using var searcher = new ManagementObjectSearcher(
        "SELECT NumberOfCores, MaxClockSpeed, L3CacheSize FROM Win32_Processor");

    foreach (ManagementObject processor in searcher.Get())
    {
        totalCores   += Convert.ToInt32(processor["NumberOfCores"]);
        maxClockMhz   = Math.Max(maxClockMhz,   Convert.ToInt32(processor["MaxClockSpeed"]));
        maxL3CacheKb  = Math.Max(maxL3CacheKb,  Convert.ToInt32(processor["L3CacheSize"]));
    }

    return totalCores   >= RecommendedCores
        && maxClockMhz  >= RecommendedClockMhz
        && maxL3CacheKb >= RecommendedL3CacheKb;
}

Utiliza el resultado para condicionar las decisiones de UX —por ejemplo, mostrar un aviso sobre la compensación de calidad, usar por defecto una resolución de salida inferior u omitir VSR por completo en los dispositivos que quedan por debajo de las recomendaciones.

Notas sobre la comprobación de WMI

  • Almacene en caché el resultado. La primera consulta WMI toma aproximadamente 50–200 ms debido a la inicialización COM. Las consultas posteriores son rápidas, pero la forma más limpia es ejecutar MeetsRecommendedCpuSpecs una vez al inicio y almacenar en caché el valor booleano durante toda la vida del proceso. El hardware de CPU no cambia en tiempo de ejecución.
  • MaxClockSpeed es la frecuencia base nominal, no la frecuencia turbo. Una CPU de 2,5 GHz que puede alcanzar 4,5 GHz en modo turbo mostrará 2500 y no superará la comprobación de 3 GHz. Esto es deliberado: el rendimiento sostenido importa más que la frecuencia turbo máxima para cargas de trabajo de IA en streaming como VSR, por lo que la frecuencia base es el indicador adecuado.
  • Alternativa para las comprobaciones inferiores a un milisegundo. Si necesita evitar depender de System.Management o la sobrecarga de WMI es inaceptable (por ejemplo, en una ruta crítica de inicio), los mismos datos están disponibles mediante las API nativas de Windows: GetLogicalProcessorInformationEx devuelve el número de núcleos y los tamaños de caché, y la frecuencia nominal de reloj se expone en HKLM\HARDWARE\DESCRIPTION\System\CentralProcessor\0 (valor ~MHz). Estos devuelven en tiempo de submilisegundos, pero requieren más código.

Creación de una sesión de VideoScaler

En el ejemplo siguiente se muestra cómo crear una sesión de VSR. En primer lugar, obtenga una instancia de ExecutionProviderCatalog y llame a EnsureAndRegisterCertifiedAsync para cargar los modelos disponibles. Llame a GetReadyState en la clase VideoScaler para determinar si el escalador de vídeo está listo para procesar fotogramas. Si no es así, llame a EnsureReadyAsync para inicializar el escalador de vídeo.

using Microsoft.Windows.AI;
using Microsoft.Windows.AI.MachineLearning;
using Microsoft.Windows.AI.Video;

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.NotSupportedOnCurrentSystem)
        {
            // VSR cannot run on this device. Fall back to a non-VSR pipeline
            // (for example, a bilinear or bicubic upscaler) or hide the feature.
            ShowException(null, "Video Super Resolution is not supported on this device.");
            return;
        }
        if (readyState == AIFeatureReadyState.NotReady)
        {
            var operation = await VideoScaler.EnsureReadyAsync();

            if (operation.Status != AIFeatureReadyResultState.Success)
            {
                ShowException(null, "Video Scaler is not available.");
                return;
            }
        }

        _videoScaler = await VideoScaler.CreateAsync();
    }
    catch (Exception ex)
    {
        ShowException(ex, "Failed to load model.");
    }

    sampleParams.NotifyCompletion();
}

Escalado de un videoframe

En el ejemplo de código siguiente se usa el método VideoScaler.Scale para escalar verticalmente los datos de imagen contenidos en un objeto VideoFrame . Puede obtener VideoFrame desde una cámara mediante la clase MediaFrameReader . Para obtener más información, vea Procesar fotogramas multimedia con MediaFrameReader. También puede usar el control CameraPreview del kit de herramientas de la comunidad winUI para obtener objetos VideoFrame de la cámara.

A continuación, se obtiene un Direct3DSurface del fotograma de vídeo de entrada y se crea otro Direct3DSurface para la salida del escalado ascendente. Se llama a VideoScaler.Scale para ampliar el fotograma. En este ejemplo, un control Image en la interfaz de usuario de la aplicación se actualiza con el marco escalado.

 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!.Scale(inputD3dSurface, _outputD3dSurface, new VideoScalerOptions());

            if (result.Status == VideoScalerStatus.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;
        }
    });
}

Escalar un SoftwareBitmap usando ImageBuffer

En el ejemplo de código siguiente se muestra el uso de la clase VideoScaler para escalar un softwareBitmap. Este ejemplo no representa un uso típico de las API de VSR. Es menos eficaz que usar Direct3D. Pero puede usar este ejemplo para experimentar con las API de VSR sin configurar una canalización de streaming de vídeo o cámara. Dado que el escalador de vídeo requiere un BGR8 al usar imageBuffer, se requieren algunos métodos auxiliares para convertir el formato de píxel del softwareBitmap proporcionado.

El código de ejemplo de este artículo se basa en el componente VSR de los ejemplos de la API de IA de 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 = _videoScaler!.ScaleImageBuffer(inputImageBuffer, outputImageBuffer, new VideoScalerOptions());
        if (result.Status != VideoScalerStatus.Success)
        {
            throw new Exception($"Failed to scale video frame: {result.Status}");
        }

        return SoftwareBitmapExtensions.ConvertBgr8ImageBufferToBgra8SoftwareBitmap(outputImageBuffer);
    }

Métodos de extensión para mapas de bits en software

Los siguientes métodos auxiliares convierten un softwareBitmap entre formatos BGRA8 y BGR8 para que coincidan con los requisitos de entrada y salida del 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;
    }

Inteligencia artificial responsable

Hemos seguido los principios y procedimientos básicos descritos en los estándares de inteligencia artificial responsable de Microsoft para garantizar que estas API sean confiables, seguras y creadas de forma responsable. Para obtener más información sobre la implementación de características de ia en la aplicación, consulte Desarrollo de IA generativa responsable en Windows.

Estas API de VSR usan modelos de Machine Learning (ML), se diseñaron específicamente para escenarios como videollamadas y conferencias y vídeos sociales y de formato corto que presentan caras humanas hablando. Por lo tanto, no se recomienda usar estas API para vídeos en los escenarios siguientes:

  • Cuando el vídeo contiene contenido potencialmente confidencial y escalado ascendente podría introducir detalles engañosos o modificar las características faciales o de identidad, como imágenes de personas, símbolos culturales o símbolos religiosos.
  • Cuando el vídeo fiel, inalterado es crítico, como para la creación de imágenes médicas, pruebas legales o forenses, o la verificación de identidad.

Consulte también