Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Video Super Resolution (VSR) to oparta na sztucznej inteligencji technologia zwiększania rozdzielczości wideo, która inteligentnie skaluje w górę strumienie wideo o niskiej rozdzielczości, przywracając ostrość i szczegóły, które w przeciwnym razie mogłyby zostać utracone z powodu ograniczeń przepustowości, słabych warunków sieciowych, kompresji lub zawartości źródłowej niższej jakości.
Dodawanie możliwości usługi VSR do aplikacji umożliwia scenariusze, w tym następujące:
- Poprawa jakości wideo za pośrednictwem słabych połączeń sieciowych
- Optymalizacja przepustowości w celu zmniejszenia kosztów usługi CDN
- Scenariusze o wysokiej przepustowości, takie jak połączenia wideo grupowe z wieloma uczestnikami
- Poprawianie jakości wideo w mediach społecznościowych podczas edytowania, przekazywania lub wyświetlania
Funkcja VSR obecnie wymaga komputera Copilot+ z procesorem NPU. Aby uzyskać więcej informacji, zobacz Develop AI applications for Copilot+ PCs (Tworzenie aplikacji sztucznej inteligencji dla komputerów Copilot+).
Te interfejsy API VSR korzystają z modeli uczenia maszynowego (ML), zostały zaprojektowane specjalnie dla scenariuszy takich jak rozmowy wideo i konferencje oraz społecznościowe i krótkie filmy wideo, które pokazują mówiące ludzkie twarze.
Usługa VSR obsługuje obecnie następujące zakresy rozdzielczości, formatu i klatek na sekundę:
| Attribute | Obsługiwana zawartość |
|---|---|
| Rozdzielczość danych wejściowych | 240p – 1440p |
| Rozdzielczość danych wyjściowych | 480p – 1440p |
| Zakres klatek na sekundę (FPS) | 15 kl./s – 60 kl./s |
| Format pikseli wejściowych | BGR (interfejs API ImageBuffer), NV12 (interfejs API Direct3D) |
| Format pikseli wyjściowych | BGR (interfejs API ImageBuffer), BGRA (interfejs API Direct3D) |
Tworzenie sesji usługi VideoScaler
W poniższym przykładzie pokazano, jak utworzyć sesję VSR. Najpierw pobierz wystąpienie ExecutionProviderCatalog i wywołaj EnsureAndRegisterCertifiedAsync, aby załadować dostępne modele. Wywołaj metodę GetReadyState w klasie VideoScalar , aby określić, czy program video scaler jest gotowy do przetwarzania ramek. Jeśli nie, wywołaj metodę EnsureReadyAsync, aby zainicjować video scaler.
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();
}
Skalowanie VideoFrame
W poniższym przykładzie kodu użyto metody VideoScaler.ScaleFrame w celu skalowania danych obrazów w górę zawartych w obiekcie VideoFrame . VideoFrame można pobrać z kamery przy użyciu klasy MediaFrameReader. Aby uzyskać więcej informacji, zobacz Przetwarzanie ramek multimedialnych za pomocą elementu MediaFrameReader. Możesz również użyć kontrolki CameraPreview zestawu narzędzi WinUI Community Toolkit, aby pobrać obiekty VideoFrame z kamery.
Następnie element Direct3DSurface jest uzyskiwany z wejściowej ramki wideo, a kolejny element Direct3DSurface tworzony jest dla wyniku skalowania w górę. Element VideoScaler.ScaleFrame jest wywoływany w celu skalowania w górę ramki. W tym przykładzie kontrolka Obraz w interfejsie użytkownika aplikacji jest aktualizowana za pomocą powiększonej ramki.
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;
}
});
}
Skalowanie obiektu SoftwareBitmap przy użyciu bufora obrazu
W poniższym przykładzie kodu pokazano użycie klasy VideoScalar do skalowania w górę mapy SoftwareBit. Ten przykład nie reprezentuje typowego użycia interfejsów API usługi VSR. Jest ona mniej wydajna niż w przypadku używania funkcji Direct3D. Możesz jednak użyć tego przykładu do eksperymentowania z interfejsami API VSR bez konfigurowania potoku przesyłania strumieniowego aparatu lub kamery wideo. Ponieważ scaler wideo wymaga BGR8 podczas korzystania z ImageBuffer, potrzebne są pewne metody pomocnicze do przekonwertowania formatu pikseli dostarczonego SoftwareBitmap.
Przykładowy kod w tym artykule jest oparty na składniku VSR w przykładach interfejsu 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);
}
Metody rozszerzenia mapy bitowej oprogramowania
Poniższe metody pomocnicze konwertują mapę SoftwareBit między formatami BGRA8 i BGR8 , aby odpowiadały wymaganiom wejściowym i wyjściowym skalara wideo.
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;
}
Odpowiedzialne używanie sztucznej inteligencji
Użyliśmy kombinacji poniższych kroków, aby upewnić się, że te interfejsy API obrazowania są wiarygodne, bezpieczne i tworzone odpowiedzialnie. Zalecamy zapoznanie się z najlepszymi rozwiązaniami opisanymi w temacie Odpowiedzialne tworzenie sztucznej inteligencji w systemie Windows podczas implementowania funkcji sztucznej inteligencji w aplikacji.
Te interfejsy API VSR używają modeli uczenia maszynowego (ML), zostały zaprojektowane specjalnie do scenariuszy, takich jak połączenia wideo i aplikacje konferencyjne oraz filmy społecznościowe i krótkie filmy, które zawierają mówiące ludzkie twarze. W związku z tym nie zalecamy używania tych interfejsów API dla obrazów w następujących scenariuszach:
- Gdzie obrazy zawierają potencjalnie wrażliwą zawartość i niedokładne opisy mogą być kontrowersyjne, takie jak flagi, mapy, globy, symbole kulturowe lub symbole religijne.
- Dokładne opisy mają krytyczne znaczenie, na przykład w przypadku porad medycznych lub diagnostyki, treści prawnych lub dokumentów finansowych.