Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
W tym artykule opisano sposób używania funkcji SceneAnalysisEffect i FaceDetectionEffect do analizowania zawartości strumienia podglądu przechwytywania multimediów.
Efekt analizy sceny
Funkcja SceneAnalysisEffect analizuje ramki wideo w strumieniu podglądu przechwytywania multimediów i zaleca opcje przetwarzania, aby poprawić wynik przechwytywania. Obecnie funkcja umożliwia wykrywanie, czy przechwytywanie można byłoby ulepszyć przy użyciu przetwarzania High Dynamic Range (HDR).
Jeśli efekt zaleca korzystanie z HDR, możesz to zrobić w następujący sposób:
Użyj klasy AdvancedPhotoCapture do przechwytywania zdjęć przy użyciu wbudowanego algorytmu przetwarzania HDR systemu Windows. Aby uzyskać więcej informacji, zobacz wysoki zakres dynamiki (HDR) i fotografowanie w warunkach słabego oświetlenia.
Użyj funkcji HdrVideoControl do przechwytywania wideo przy użyciu wbudowanego algorytmu przetwarzania HDR w systemie Windows. Aby uzyskać więcej informacji, zobacz Kontrolki urządzeń do przechwytywania wideo.
Użyj VariablePhotoSequenceControl, aby przechwycić sekwencję ramek, którą można następnie złożyć przy użyciu niestandardowej implementacji HDR. Aby uzyskać więcej informacji, zobacz Zmienna sekwencja zdjęć.
Inicjowanie efektu analizy sceny i dodawanie go do strumienia podglądu
Efekty wideo są implementowane przy użyciu dwóch interfejsów API: definicji efektu, która zapewnia ustawienia, jakie urządzenie przechwytywania musi uruchomić, oraz instancji efektu, która może być używana do jego kontrolowania. Ponieważ możesz uzyskać dostęp do wystąpienia efektu z wielu miejsc w kodzie, zazwyczaj należy zadeklarować zmienną składową do przechowywania obiektu.
private SceneAnalysisEffect m_sceneAnalysisEffect;
W aplikacji po zainicjowaniu obiektu MediaCapture utwórz nowe wystąpienie obiektu SceneAnalysisEffectDefinition.
Zarejestruj efekt przy użyciu urządzenia przechwytywania, wywołując metodę AddVideoEffectAsync w obiekcie MediaCapture , udostępniając element SceneAnalysisEffectDefinition i określając parametr MediaStreamType.VideoPreview , aby wskazać, że efekt powinien zostać zastosowany do strumienia podglądu wideo, w przeciwieństwie do strumienia przechwytywania. Funkcja AddVideoEffectAsync zwraca wystąpienie dodanego efektu. Ponieważ ta metoda może być używana z wieloma typami efektów, należy rzutować zwrócone wystąpienie na obiekt SceneAnalysisEffect .
Aby uzyskać wyniki analizy sceny, należy zarejestrować program obsługi zdarzenia SceneAnalyzed .
Obecnie efekt analizy sceny obejmuje tylko analizator wysokiego zakresu dynamicznego. Włącz analizę HDR, ustawiając wartość true dla efektu HighDynamicRangeControl.Enabled .
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml;
using System;
using Windows.Media.Devices;
using System.Linq;
using Microsoft.UI.Xaml.Input;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Media.MediaProperties;
using Windows.Graphics.Display;
using Windows.Media.Capture;
using System.Collections.Generic;
using Windows.Media.Capture.Frames;
using Windows.Media.Core;
using Windows.Media.Effects;
using Windows.Media;
using Windows.UI.Core;
//using MyVideoEffect;
using Windows.Graphics.Imaging;
namespace CameraWinUI
{
public sealed partial class MainWindow : Window
{
#region Basic add/remove
IVideoEffectDefinition myEffectDefinition;
IMediaExtension myPreviewEffect;
IMediaExtension myRecordEffect;
private async void bBasicAddEffect_Click(object sender, RoutedEventArgs e)
{
myEffectDefinition = new VideoEffectDefinition("MyVideoEffect.ExampleVideoEffect");
// <SnippetBasicAddEffect>
if (m_mediaCapture.MediaCaptureSettings.VideoDeviceCharacteristic == VideoDeviceCharacteristic.AllStreamsIdentical ||
m_mediaCapture.MediaCaptureSettings.VideoDeviceCharacteristic == VideoDeviceCharacteristic.PreviewRecordStreamsIdentical)
{
// This effect will modify both the preview and the record streams, because they are the same stream.
myRecordEffect = await m_mediaCapture.AddVideoEffectAsync(myEffectDefinition, MediaStreamType.VideoRecord);
}
else
{
myRecordEffect = await m_mediaCapture.AddVideoEffectAsync(myEffectDefinition, MediaStreamType.VideoRecord);
myPreviewEffect = await m_mediaCapture.AddVideoEffectAsync(myEffectDefinition, MediaStreamType.VideoPreview);
}
// </SnippetBasicAddEffect>
}
public async void RemoveOneEffect()
{
// <SnippetRemoveOneEffect>
if (myRecordEffect != null)
{
await m_mediaCapture.RemoveEffectAsync(myRecordEffect);
}
if (myPreviewEffect != null)
{
await m_mediaCapture.RemoveEffectAsync(myPreviewEffect);
}
// </SnippetRemoveOneEffect>
}
public async void RemoveAllEffects()
{
// <SnippetClearAllEffects>
await m_mediaCapture.ClearEffectsAsync(MediaStreamType.VideoPreview);
await m_mediaCapture.ClearEffectsAsync(MediaStreamType.VideoRecord);
// </SnippetClearAllEffects>
}
#endregion
#region Video stabilization effect
// <SnippetDeclareVideoStabilizationEffect>
//
private VideoStabilizationEffect m_videoStabilizationEffect;
private VideoEncodingProperties m_inputPropertiesBackup;
private VideoEncodingProperties m_outputPropertiesBackup;
private MediaEncodingProfile m_encodingProfile;
// </SnippetDeclareVideoStabilizationEffect>
private async void bSetupVideoStabilizationEffect_Click(object sender, RoutedEventArgs e)
{
// <SnippetEncodingProfileMember>
m_encodingProfile = MediaEncodingProfile.CreateMp4(VideoEncodingQuality.Auto);
// </SnippetEncodingProfileMember>
// <SnippetCreateVideoStabilizationEffect>
// Create the effect definition
VideoStabilizationEffectDefinition stabilizerDefinition = new VideoStabilizationEffectDefinition();
// Add the video stabilization effect to media capture
m_videoStabilizationEffect =
(VideoStabilizationEffect)await m_mediaCapture.AddVideoEffectAsync(stabilizerDefinition, MediaStreamType.VideoRecord);
m_videoStabilizationEffect.EnabledChanged += VideoStabilizationEffect_EnabledChanged;
await SetUpVideoStabilizationRecommendationAsync();
m_videoStabilizationEffect.Enabled = true;
// </SnippetCreateVideoStabilizationEffect>
}
// <SnippetSetUpVideoStabilizationRecommendationAsync>
private async Task SetUpVideoStabilizationRecommendationAsync()
{
// Get the recommendation from the effect based on our current input and output configuration
var recommendation = m_videoStabilizationEffect.GetRecommendedStreamConfiguration(m_mediaCapture.VideoDeviceController, m_encodingProfile.Video);
// Handle the recommendation for the input into the effect, which can contain a larger resolution than currently configured, so cropping is minimized
if (recommendation.InputProperties != null)
{
// Back up the current input properties from before VS was activated
m_inputPropertiesBackup = m_mediaCapture.VideoDeviceController.GetMediaStreamProperties(MediaStreamType.VideoRecord) as VideoEncodingProperties;
// Set the recommendation from the effect (a resolution higher than the current one to allow for cropping) on the input
await m_mediaCapture.VideoDeviceController.SetMediaStreamPropertiesAsync(MediaStreamType.VideoRecord, recommendation.InputProperties);
await m_mediaCapture.VideoDeviceController.SetMediaStreamPropertiesAsync(MediaStreamType.VideoPreview, recommendation.InputProperties);
}
// Handle the recommendations for the output from the effect
if (recommendation.OutputProperties != null)
{
// Back up the current output properties from before VS was activated
m_outputPropertiesBackup = m_encodingProfile.Video;
// Apply the recommended encoding profile for the output
m_encodingProfile.Video = recommendation.OutputProperties;
}
}
// </SnippetSetUpVideoStabilizationRecommendationAsync>
// <SnippetVideoStabilizationEnabledChanged>
private async void VideoStabilizationEffect_EnabledChanged(VideoStabilizationEffect sender, VideoStabilizationEffectEnabledChangedEventArgs args)
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
// Update your UI to reflect the change in status
tbStatus.Text = "video stabilization status: " + sender.Enabled + ". Reason: " + args.Reason;
});
}
// </SnippetVideoStabilizationEnabledChanged>
private async void bCleanupVideoStabilizationEffect_Click(object sender, RoutedEventArgs e)
{
// <SnippetCleanUpVisualStabilizationEffect>
// Clear all effects in the pipeline
await m_mediaCapture.RemoveEffectAsync(m_videoStabilizationEffect);
// If backed up settings (stream properties and encoding profile) exist, restore them and clear the backups
if (m_inputPropertiesBackup != null)
{
await m_mediaCapture.VideoDeviceController.SetMediaStreamPropertiesAsync(MediaStreamType.VideoRecord, m_inputPropertiesBackup);
m_inputPropertiesBackup = null;
}
if (m_outputPropertiesBackup != null)
{
m_encodingProfile.Video = m_outputPropertiesBackup;
m_outputPropertiesBackup = null;
}
m_videoStabilizationEffect.EnabledChanged -= VideoStabilizationEffect_EnabledChanged;
m_videoStabilizationEffect = null;
// </SnippetCleanUpVisualStabilizationEffect>
}
#endregion Video stabilization effect
#region scene analyis effect
// <SnippetDeclareSceneAnalysisEffect>
private SceneAnalysisEffect m_sceneAnalysisEffect;
// </SnippetDeclareSceneAnalysisEffect>
private async void bCreateSceneAnalysisEffect_Click(object sender, RoutedEventArgs e)
{
// <SnippetCreateSceneAnalysisEffectAsync>
// Create the definition
var definition = new SceneAnalysisEffectDefinition();
// Add the effect to the video record stream
m_sceneAnalysisEffect = (SceneAnalysisEffect)await m_mediaCapture.AddVideoEffectAsync(definition, MediaStreamType.VideoPreview);
// Subscribe to notifications about scene information
m_sceneAnalysisEffect.SceneAnalyzed += SceneAnalysisEffect_SceneAnalyzed;
// Enable HDR analysis
m_sceneAnalysisEffect.HighDynamicRangeAnalyzer.Enabled = true;
// </SnippetCreateSceneAnalysisEffectAsync>
}
double MyCertaintyCap = .5;
// <SnippetSceneAnalyzed>
private void SceneAnalysisEffect_SceneAnalyzed(SceneAnalysisEffect sender, SceneAnalyzedEventArgs args)
{
double hdrCertainty = args.ResultFrame.HighDynamicRange.Certainty;
// Certainty value is between 0.0 and 1.0
if (hdrCertainty > MyCertaintyCap)
{
DispatcherQueue.TryEnqueue(() =>
{
tbStatus.Text = "Enabling HDR capture is recommended.";
});
}
}
// </SnippetSceneAnalyzed>
private async void bCleanupSceneAnalysisEffect_Click(object sender, RoutedEventArgs e)
{
// <SnippetCleanUpSceneAnalysisEffectAsync>
// Disable detection
m_sceneAnalysisEffect.HighDynamicRangeAnalyzer.Enabled = false;
m_sceneAnalysisEffect.SceneAnalyzed -= SceneAnalysisEffect_SceneAnalyzed;
// Remove the effect from the preview stream
await m_mediaCapture.ClearEffectsAsync(MediaStreamType.VideoPreview);
// Clear the member variable that held the effect instance
m_sceneAnalysisEffect = null;
// </SnippetCleanUpSceneAnalysisEffectAsync>
}
#endregion scene analyis effect
#region Face detection
// <SnippetDeclareFaceDetectionEffect>
FaceDetectionEffect m_faceDetectionEffect;
// </SnippetDeclareFaceDetectionEffect>
private async void bCreateFaceDetectionEffect_Click(object sender, RoutedEventArgs e)
{
// <SnippetCreateFaceDetectionEffectAsync>
// Create the definition, which will contain some initialization settings
var definition = new FaceDetectionEffectDefinition();
// To ensure preview smoothness, do not delay incoming samples
definition.SynchronousDetectionEnabled = false;
// In this scenario, choose detection speed over accuracy
definition.DetectionMode = FaceDetectionMode.HighPerformance;
// Add the effect to the preview stream
m_faceDetectionEffect = (FaceDetectionEffect)await m_mediaCapture.AddVideoEffectAsync(definition, MediaStreamType.VideoPreview);
// Choose the shortest interval between detection events
m_faceDetectionEffect.DesiredDetectionInterval = TimeSpan.FromMilliseconds(33);
// Start detecting faces
m_faceDetectionEffect.Enabled = true;
// </SnippetCreateFaceDetectionEffectAsync>
// <SnippetRegisterFaceDetectionHandler>
// Register for face detection events
m_faceDetectionEffect.FaceDetected += FaceDetectionEffect_FaceDetected;
// </SnippetRegisterFaceDetectionHandler>
// <SnippetAreFaceFocusAndExposureSupported>
var regionsControl = m_mediaCapture.VideoDeviceController.RegionsOfInterestControl;
bool faceDetectionFocusAndExposureSupported =
regionsControl.MaxRegions > 0 &&
(regionsControl.AutoExposureSupported || regionsControl.AutoFocusSupported);
// </SnippetAreFaceFocusAndExposureSupported>
}
private async void bCleanipFaceDetectionEffect_Click(object sender, RoutedEventArgs e)
{
// <SnippetCleanUpFaceDetectionEffectAsync>
// Disable detection
m_faceDetectionEffect.Enabled = false;
// Unregister the event handler
m_faceDetectionEffect.FaceDetected -= FaceDetectionEffect_FaceDetected;
// Remove the effect from the preview stream
await m_mediaCapture.ClearEffectsAsync(MediaStreamType.VideoPreview);
// Clear the member variable that held the effect instance
m_faceDetectionEffect = null;
// </SnippetCleanUpFaceDetectionEffectAsync>
}
// <SnippetFaceDetected>
private void FaceDetectionEffect_FaceDetected(FaceDetectionEffect sender, FaceDetectedEventArgs args)
{
foreach (Windows.Media.FaceAnalysis.DetectedFace face in args.ResultFrame.DetectedFaces)
{
BitmapBounds faceRect = face.FaceBox;
// Draw a rectangle on the preview stream for each face
}
}
// </SnippetFaceDetected>
#endregion Face detection
}
}
Implementowanie programu obsługi zdarzeń SceneAnalyzed
Wyniki analizy sceny są zwracane w procedurze obsługi zdarzeń SceneAnalyzed . Obiekt SceneAnalyzedEventArgs przekazany do programu obsługi ma obiekt SceneAnalysisEffectFrame , który ma obiekt HighDynamicRangeOutput . Właściwość Pewność danych wyjściowych o wysokim zakresie dynamicznym zapewnia wartość z zakresu od 0 do 1,0, gdzie 0 wskazuje, że przetwarzanie HDR nie pomoże poprawić wyniku przechwytywania i 1,0 wskazuje, że przetwarzanie HDR pomoże. Możesz zdecydować o punkcie progu, w którym chcesz użyć formatu HDR lub pokazać użytkownikowi wyniki i pozwolić użytkownikowi zdecydować.
private void SceneAnalysisEffect_SceneAnalyzed(SceneAnalysisEffect sender, SceneAnalyzedEventArgs args)
{
double hdrCertainty = args.ResultFrame.HighDynamicRange.Certainty;
// Certainty value is between 0.0 and 1.0
if (hdrCertainty > MyCertaintyCap)
{
DispatcherQueue.TryEnqueue(() =>
{
tbStatus.Text = "Enabling HDR capture is recommended.";
});
}
}
Obiekt HighDynamicRangeOutput przekazany do programu obsługi ma również właściwość FrameControllers zawierającą sugerowane kontrolery ramek do przechwytywania zmiennej sekwencji zdjęć na potrzeby przetwarzania HDR. Aby uzyskać więcej informacji, zobacz Zmienna sekwencja zdjęć.
Czyszczenie efektu analizy sceny
Po zakończeniu przechwytywania aplikacji, przed usunięciem obiektu MediaCapture, należy wyłączyć efekt analizy sceny, ustawiając właściwość HighDynamicRangeAnalyzer.Enabled na wartość false i wyrejestrowując procedurę obsługi zdarzeń SceneAnalyzed. Wywołaj metodę MediaCapture.ClearEffectsAsync, określając strumień podglądu wideo, ponieważ był to strumień, do którego dodano efekt. Na koniec ustaw zmienną składową na wartość null.
// Disable detection
m_sceneAnalysisEffect.HighDynamicRangeAnalyzer.Enabled = false;
m_sceneAnalysisEffect.SceneAnalyzed -= SceneAnalysisEffect_SceneAnalyzed;
// Remove the effect from the preview stream
await m_mediaCapture.ClearEffectsAsync(MediaStreamType.VideoPreview);
// Clear the member variable that held the effect instance
m_sceneAnalysisEffect = null;
Efekt wykrywania twarzy
Funkcja FaceDetectionEffect identyfikuje lokalizację twarzy w strumieniu podglądu przechwytywania multimediów. Efekt umożliwia odbieranie powiadomienia za każdym razem, gdy twarz zostanie wykryta w strumieniu podglądowym, i udostępnia ramkę ograniczającą dla każdej wykrytej twarzy w klatce podglądowej. Na obsługiwanych urządzeniach efekt wykrywania twarzy zapewnia również zwiększoną ekspozycję i skupienie się na najważniejszej twarzy na scenie.
Zainicjuj efekt wykrywania twarzy i dodaj go do strumienia podglądu
Efekty wideo są implementowane za pomocą dwóch interfejsów API: definicji efektu, która dostarcza ustawień potrzebnych do zainicjowania efektu przez urządzenie przechwytujące, oraz wystąpienia efektu, które może być używane do sterowania efektem. Ponieważ możesz uzyskać dostęp do wystąpienia efektu z wielu miejsc w kodzie, zazwyczaj należy zadeklarować zmienną składową do przechowywania obiektu.
FaceDetectionEffect m_faceDetectionEffect;
W aplikacji po zainicjowaniu obiektu MediaCapture utwórz nowe wystąpienie obiektu FaceDetectionEffectDefinition. Ustaw właściwość DetectionMode , aby określić priorytety szybszego wykrywania twarzy lub dokładniejszego wykrywania twarzy. Ustaw SynchronousDetectionEnabled, aby określić, że przychodzące ramki nie są opóźniane oczekiwaniem na zakończenie wykrywania twarzy, co może prowadzić do przerywanego podglądu.
Zarejestruj efekt przy użyciu urządzenia przechwytywania, wywołując metodę AddVideoEffectAsync w obiekcie MediaCapture , podając element FaceDetectionEffectDefinition i określając parametr MediaStreamType.VideoPreview , aby wskazać, że efekt powinien zostać zastosowany do strumienia podglądu wideo, w przeciwieństwie do strumienia przechwytywania. Funkcja AddVideoEffectAsync zwraca wystąpienie dodanego efektu. Ponieważ ta metoda może być używana z wieloma typami efektów, należy przekształcić zwrócony obiekt na obiekt FaceDetectionEffect.
Włącz lub wyłącz efekt, ustawiając właściwość FaceDetectionEffect.Enabled . Dostosuj częstotliwość analizowania ramek przez ustawienie właściwości FaceDetectionEffect.DesiredDetectionInterval . Obie te właściwości można dostosować, gdy przechwytywanie multimediów trwa.
// Create the definition, which will contain some initialization settings
var definition = new FaceDetectionEffectDefinition();
// To ensure preview smoothness, do not delay incoming samples
definition.SynchronousDetectionEnabled = false;
// In this scenario, choose detection speed over accuracy
definition.DetectionMode = FaceDetectionMode.HighPerformance;
// Add the effect to the preview stream
m_faceDetectionEffect = (FaceDetectionEffect)await m_mediaCapture.AddVideoEffectAsync(definition, MediaStreamType.VideoPreview);
// Choose the shortest interval between detection events
m_faceDetectionEffect.DesiredDetectionInterval = TimeSpan.FromMilliseconds(33);
// Start detecting faces
m_faceDetectionEffect.Enabled = true;
Odbieranie powiadomień po wykryciu twarzy
Jeśli chcesz wykonać jakąś akcję w przypadku wykrycia twarzy, takich jak rysowanie pola wokół wykrytych twarzy w podglądzie wideo, możesz zarejestrować się w przypadku zdarzenia FaceDetected .
// Register for face detection events
m_faceDetectionEffect.FaceDetected += FaceDetectionEffect_FaceDetected;
W procedurze obsługi zdarzenia można uzyskać listę wszystkich twarzy wykrytych w ramce, korzystając z właściwości FaceDetectionEffectFrame.DetectedFaces właściwości FaceDetectedEventArgs. Właściwość FaceBox to struktura BitmapBounds , która opisuje prostokąt zawierający wykrytą twarz w jednostkach względem wymiarów strumienia podglądu. Aby wyświetlić przykładowy kod, który przekształca współrzędne strumienia podglądu na współrzędne ekranu, zobacz przykład dotyczący wykrywania twarzy platformy UWP.
private void FaceDetectionEffect_FaceDetected(FaceDetectionEffect sender, FaceDetectedEventArgs args)
{
foreach (Windows.Media.FaceAnalysis.DetectedFace face in args.ResultFrame.DetectedFaces)
{
BitmapBounds faceRect = face.FaceBox;
// Draw a rectangle on the preview stream for each face
}
}
Czyszczenie efektu wykrywania twarzy
Po zakończeniu przechwytywania przez aplikację, przed usunięciem obiektu MediaCapture, należy wyłączyć efekt wykrywania twarzy za pomocą funkcji FaceDetectionEffect.Enabled i wyrejestrować obsługę zdarzenia FaceDetected, jeśli została wcześniej zarejestrowana. Wywołaj metodę MediaCapture.ClearEffectsAsync, określając strumień podglądu wideo, ponieważ był to strumień, do którego dodano efekt. Na koniec ustaw zmienną składową na wartość null.
// Disable detection
m_faceDetectionEffect.Enabled = false;
// Unregister the event handler
m_faceDetectionEffect.FaceDetected -= FaceDetectionEffect_FaceDetected;
// Remove the effect from the preview stream
await m_mediaCapture.ClearEffectsAsync(MediaStreamType.VideoPreview);
// Clear the member variable that held the effect instance
m_faceDetectionEffect = null;
Sprawdź obsługę fokusu i ekspozycji dla wykrytych twarzy
Nie wszystkie urządzenia mają urządzenie przechwytywania, które może dostosować jego fokus i ekspozycję na podstawie wykrytych twarzy. Ponieważ wykrywanie twarzy zużywa zasoby urządzenia, możesz włączyć wykrywanie twarzy tylko na urządzeniach, które mogą używać tej funkcji do ulepszania przechwytywania. Aby sprawdzić, czy optymalizacja przechwytywania oparta na rozpoznawaniu twarzy jest dostępna, pobierz element VideoDeviceController dla zainicjowanego MediaCapture, a następnie uzyskaj dostęp do RegionsOfInterestControl kontrolera urządzenia wideo. Sprawdź, czy region MaxRegions obsługuje co najmniej jeden region. Następnie sprawdź, czy AutoExposureSupported lub AutoFocusSupported jest "true". Jeśli te warunki zostaną spełnione, urządzenie może skorzystać z funkcji wykrywania twarzy w celu ulepszenia przechwytywania.
var regionsControl = m_mediaCapture.VideoDeviceController.RegionsOfInterestControl;
bool faceDetectionFocusAndExposureSupported =
regionsControl.MaxRegions > 0 &&
(regionsControl.AutoExposureSupported || regionsControl.AutoFocusSupported);
Tematy pokrewne