Efeitos para análise de quadros de câmeraEffects for analyzing camera frames

Este artigo descreve como usar o SceneAnalysisEffect e o FaceDetectionEffect para analisar o conteúdo do fluxo de visualização de captura de mídia.This article describes how to use the SceneAnalysisEffect and the FaceDetectionEffect to analyze the content of the media capture preview stream.

Efeito de análise de cenaScene analysis effect

SceneAnalysisEffect analisa os quadros de vídeo no fluxo de visualização de captura de mídia e recomenda opções de processamento para melhorar o resultado da captura.The SceneAnalysisEffect analyzes the video frames in the media capture preview stream and recommends processing options to improve the capture result. Atualmente, o efeito permite detectar se a captura poderia ser melhorada usando o processamento em HDR (High Dynamic Range).Currently, the effect supports detecting whether the capture would be improved by using High Dynamic Range (HDR) processing.

Se o efeito recomendar o uso de HDR, você pode fazer isso das seguintes maneiras:If the effect recommends using HDR, you can do this in the following ways:

Namespaces de análise de cenaScene analysis namespaces

Para usar a análise de cena, seu aplicativo deve incluir os namespaces a seguir, além dos namespaces necessários para a captura de mídia básica.To use scene analysis, your app must include the following namespaces in addition to the namespaces required for basic media capture.

using Windows.Media.Core;
using Windows.Media.Devices;

Inicializar o efeito de análise de cena e adicioná-lo ao fluxo de visualizaçãoInitialize the scene analysis effect and add it to the preview stream

Os efeitos de vídeo são implementados usando-se duas APIs, uma definição de efeito, que fornece as configurações que o dispositivo de captura precisa para inicializar o efeito, e uma instância de efeito, que pode ser usada para controlar o efeito.Video effects are implemented using two APIs, an effect definition, which provides settings that the capture device needs to initialize the effect, and an effect instance, which can be used to control the effect. Como você pode querer acessar a instância de efeito de vários locais dentro do seu código, normalmente você deve declarar uma variável de membro para manter o objeto.Since you may want to access the effect instance from multiple places within your code, you should typically declare a member variable to hold the object.

private SceneAnalysisEffect _sceneAnalysisEffect;

No seu aplicativo, depois de você ter inicializado o objeto MediaCapture, crie uma nova instância de SceneAnalysisEffectDefinition.In your app, after you have initialized the MediaCapture object, create a new instance of SceneAnalysisEffectDefinition.

Registre o efeito com o dispositivo de captura chamando AddVideoEffectAsync no seu objeto MediaCapture, fornecendo SceneAnalysisEffectDefinition e especificando MediaStreamType.VideoPreview para indicar que o efeito deve ser aplicado ao fluxo de visualização de vídeo, em vez do fluxo de captura.Register the effect with the capture device by calling AddVideoEffectAsync on your MediaCapture object, providing the SceneAnalysisEffectDefinition and specifying MediaStreamType.VideoPreview to indicate that the effect should be applied to the video preview stream, as opposed to the capture stream. AddVideoEffectAsync retorna uma instância do efeito adicionado.AddVideoEffectAsync returns an instance of the added effect. Como esse método pode ser usado com vários tipos de efeito, você deve converter a instância retornada em um objeto SceneAnalysisEffect.Because this method can be used with multiple effect types, you must cast the returned instance to a SceneAnalysisEffect object.

Para receber os resultados da análise de cena, você deve registrar um manipulador para o evento SceneAnalyzed.To receive the results of the scene analysis, you must register a handler for the SceneAnalyzed event.

Atualmente, o efeito de análise de cena inclui somente o analisador de HDR.Currently, the scene analysis effect only includes the high dynamic range analyzer. Habilite a análise de HDR definindo o efeito HighDynamicRangeControl.Enabled como true.Enable HDR analysis by setting the effect's HighDynamicRangeControl.Enabled to true.

// Create the definition
var definition = new SceneAnalysisEffectDefinition();

// Add the effect to the video record stream
_sceneAnalysisEffect = (SceneAnalysisEffect)await _mediaCapture.AddVideoEffectAsync(definition, MediaStreamType.VideoPreview);

// Subscribe to notifications about scene information
_sceneAnalysisEffect.SceneAnalyzed += SceneAnalysisEffect_SceneAnalyzed;

// Enable HDR analysis
_sceneAnalysisEffect.HighDynamicRangeAnalyzer.Enabled = true;

Implementar o manipulador de eventos SceneAnalyzedImplement the SceneAnalyzed event handler

Os resultados da análise de cena são retornados no manipulador de eventos SceneAnalyzed.The results of the scene analysis are returned in the SceneAnalyzed event handler. O objeto SceneAnalyzedEventArgs passado para o manipulador tem um objeto SceneAnalysisEffectFrame que possui um objeto HighDynamicRangeOutput.The SceneAnalyzedEventArgs object passed into the handler has a SceneAnalysisEffectFrame object which has a HighDynamicRangeOutput object. A propriedade Certainty da saída de HDR fornece um valor entre 0 e 1,0, onde 0 indica que o processamento em HDR não ajudaria a melhorar o resultado da captura e 1,0 indica que o processamento em HDR ajudaria.The Certainty property of the high dynamic range output provides a value between 0 and 1.0 where 0 indicates that HDR processing would not help improve the capture result and 1.0 indicates that HDR processing would help. Você pode decidir o ponto de limite no qual deseja usar HDR ou mostrar os resultados ao usuário e permitir que ele decida.Your can decide the threshold point at which you want to use HDR or show the results to the user and let the user decide.

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)
    {
        ShowMessageToUser("Enabling HDR capture is recommended.");
    }
}

O objeto HighDynamicRangeOutput passado para o manipulador também tem uma propriedade FrameControllers, que contém controladores de quadro sugeridos para capturar uma sequência de fotos variável para processamento em HDR.The HighDynamicRangeOutput object passed into the handler also has a FrameControllers property which contains suggested frame controllers for capturing a variable photo sequence for HDR processing. Para obter mais informações, consulte Sequência de fotos variável.For more information, see Variable photo sequence.

Limpar o efeito da análise de cenaClean up the scene analysis effect

Quando seu aplicativo terminar a captura, antes de descartar o objeto MediaCapture, você deve desabilitar o efeito de análise de cena definindo a propriedade HighDynamicRangeAnalyzer.Enabled do efeito como false e cancelar o registro de seu manipulador de eventos SceneAnalyzed.When your app is done capturing, before disposing of the MediaCapture object, you should disable the scene analysis effect by setting the effect's HighDynamicRangeAnalyzer.Enabled property to false and unregister your SceneAnalyzed event handler. Chame MediaCapture.ClearEffectsAsync especificando o fluxo de visualização de vídeo, desde que tenha sido o fluxo ao qual o efeito foi adicionado.Call MediaCapture.ClearEffectsAsync, specifying the video preview stream since that was the stream to which the effect was added. Por fim, defina a variável de membro como nula.Finally, set your member variable to null.

// Disable detection
_sceneAnalysisEffect.HighDynamicRangeAnalyzer.Enabled = false;

_sceneAnalysisEffect.SceneAnalyzed -= SceneAnalysisEffect_SceneAnalyzed;

// Remove the effect from the preview stream
await _mediaCapture.ClearEffectsAsync(MediaStreamType.VideoPreview);

// Clear the member variable that held the effect instance
_sceneAnalysisEffect = null;

Efeito de detecção de rostoFace detection effect

O FaceDetectionEffect identifica a localização de rostos dentro do fluxo de visualização da captura de mídia.The FaceDetectionEffect identifies the location of faces within the media capture preview stream. O efeito permite que você receba uma notificação sempre que um rosto for detectado no fluxo de visualização e fornece a caixa delimitadora para cada rosto detectado dentro do quadro de visualização.The effect allows you to receive a notification whenever a face is detected in the preview stream and provides the bounding box for each detected face within the preview frame. Em dispositivos com suporte, o efeito de detecção de rosto também fornece exposição avançada e foco no rosto mais importante na cena.On supported devices, the face detection effect also provides enhanced exposure and focus on the most important face in the scene.

Namespaces de detecção de rostoFace detection namespaces

Para usar a detecção de rosto, seu aplicativo deve incluir os namespaces a seguir, além dos namespaces necessários para a captura de mídia básica.To use face detection, your app must include the following namespaces in addition to the namespaces required for basic media capture.

using Windows.Media.Core;

Inicializar o efeito de detecção de rosto e adicioná-lo ao fluxo de visualizaçãoInitialize the face detection effect and add it to the preview stream

Os efeitos de vídeo são implementados usando-se duas APIs, uma definição de efeito, que fornece as configurações que o dispositivo de captura precisa para inicializar o efeito, e uma instância de efeito, que pode ser usada para controlar o efeito.Video effects are implemented using two APIs, an effect definition, which provides settings that the capture device needs to initialize the effect, and an effect instance, which can be used to control the effect. Como você pode querer acessar a instância de efeito de vários locais dentro do seu código, normalmente você deve declarar uma variável de membro para manter o objeto.Since you may want to access the effect instance from multiple places within your code, you should typically declare a member variable to hold the object.

FaceDetectionEffect _faceDetectionEffect;

No seu aplicativo, depois de você ter inicializado o objeto MediaCapture, crie uma nova instância de FaceDetectionEffectDefinition.In your app, after you have initialized the MediaCapture object, create a new instance of FaceDetectionEffectDefinition. Defina a propriedade DetectionMode para priorizar a detecção de rosto mais rápida ou a mais precisa.Set the DetectionMode property to prioritize faster face detection or more accurate face detection. Defina SynchronousDetectionEnabled para especificar que os quadros recebidos não atrasem aguardando a detecção de rosto ser concluída, já que isso pode resultar em uma experiência de visualização truncada.Set SynchronousDetectionEnabled to specify that incoming frames are not delayed waiting for face detection to complete as this can result in a choppy preview experience.

Registre o efeito com o dispositivo de captura chamando AddVideoEffectAsync no seu objeto MediaCapture, fornecendo FaceDetectionEffectDefinition e especificando MediaStreamType.VideoPreview para indicar que o efeito deve ser aplicado ao fluxo de visualização de vídeo, em vez do fluxo de captura.Register the effect with the capture device by calling AddVideoEffectAsync on your MediaCapture object, providing the FaceDetectionEffectDefinition and specifying MediaStreamType.VideoPreview to indicate that the effect should be applied to the video preview stream, as opposed to the capture stream. AddVideoEffectAsync retorna uma instância do efeito adicionado.AddVideoEffectAsync returns an instance of the added effect. Como esse método pode ser usado com vários tipos de efeito, você deve converter a instância retornada em um objeto FaceDetectionEffect.Because this method can be used with multiple effect types, you must cast the returned instance to a FaceDetectionEffect object.

Habilite ou desabilite os efeitos definindo a propriedade FaceDetectionEffect.Enabled.Enable or disable the effect by setting the FaceDetectionEffect.Enabled property. Ajuste quantas vezes o efeito analisa os quadros definindo a propriedade FaceDetectionEffect.DesiredDetectionInterval.Adjust how often the effect analyzes frames by setting the FaceDetectionEffect.DesiredDetectionInterval property. Ambas as propriedades podem ser ajustadas enquanto captura de mídia está em andamento.Both of these properties can be adjusted while media capture is ongoing.


// 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
_faceDetectionEffect = (FaceDetectionEffect)await _mediaCapture.AddVideoEffectAsync(definition, MediaStreamType.VideoPreview);

// Choose the shortest interval between detection events
_faceDetectionEffect.DesiredDetectionInterval = TimeSpan.FromMilliseconds(33);

// Start detecting faces
_faceDetectionEffect.Enabled = true;

Receber notificações quando os rostos forem detectadosReceive notifications when faces are detected

Se você deseja executar algumas ações quando rostos forem detectados, como desenhar uma caixa ao redor dos rostos detectados na visualização de vídeo, você pode registrar o evento FaceDetected.If you want to perform some action when faces are detected, such as drawing a box around detected faces in the video preview, you can register for the FaceDetected event.

// Register for face detection events
_faceDetectionEffect.FaceDetected += FaceDetectionEffect_FaceDetected;

No manipulador do evento, você pode obter uma lista de todos os rostos detectados em um quadro acessando a propriedade FaceDetectionEffectFrame.DetectedFaces do FaceDetectedEventArgs.In the handler for the event, you can get a list of all faces detected in a frame by accessing the FaceDetectionEffectFrame.DetectedFaces property of the FaceDetectedEventArgs. A propriedade FaceBox é uma estrutura BitmapBounds que descreve o retângulo contendo o rosto detectado em unidades relativas às dimensões do fluxo de visualização.The FaceBox property is a BitmapBounds structure that describes the rectangle containing the detected face in units relative to the preview stream dimensions. Para ver o código de amostra que transforma as coordenadas do fluxo de visualização em coordenadas de tela, consulte o amostra UWP de detecção de rosto.To view sample code that transforms the preview stream coordinates into screen coordinates, see the face detection UWP sample.

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
    }
}

Limpar o efeito de detecção de rostoClean up the face detection effect

Quando seu aplicativo terminar a captura, antes de descartar o objeto MediaCapture, você deve desabilitar o efeito de detecção de rosto com FaceDetectionEffect.Enabled e cancelar o registro do seu manipulador de eventos FaceDetected se tiver registrado um anteriormente.When your app is done capturing, before disposing of the MediaCapture object, you should disable the face detection effect with FaceDetectionEffect.Enabled and unregister your FaceDetected event handler if you previously registered one. Chame MediaCapture.ClearEffectsAsync especificando o fluxo de visualização de vídeo, desde que tenha sido o fluxo ao qual o efeito foi adicionado.Call MediaCapture.ClearEffectsAsync, specifying the video preview stream since that was the stream to which the effect was added. Por fim, defina a variável de membro como nula.Finally, set your member variable to null.

// Disable detection
_faceDetectionEffect.Enabled = false;

// Unregister the event handler
_faceDetectionEffect.FaceDetected -= FaceDetectionEffect_FaceDetected;

// Remove the effect from the preview stream
await _mediaCapture.ClearEffectsAsync(MediaStreamType.VideoPreview);

// Clear the member variable that held the effect instance
_faceDetectionEffect = null;

Verificar se há suporte para foco e exposição para os rostos detectadosCheck for focus and exposure support for detected faces

Nem todos os dispositivos têm um mecanismo de captura que possa ajustar o foco e a exposição com base nos rostos detectados.Not all devices have a capture device that can adjust its focus and exposure based on detected faces. Como a detecção de rosto consome recursos do dispositivo, você pode querer apenas ativar a detecção de rosto em dispositivos que possam usar o recurso para aprimorar a captura.Because face detection consumes device resources, you may only want to enable face detection on devices that can use the feature to enhance capture. Para ver se a otimização de captura com base no rosto está disponível, obtenha o VideoDeviceController para sua MediaCapture inicializada e baixe o RegionsOfInterestControl do controlador de dispositivo de vídeo.To see if face-based capture optimization is available, get the VideoDeviceController for your initialized MediaCapture and then get the video device controller's RegionsOfInterestControl. Verifique se o MaxRegions dá suporte a pelo menos uma região.Check to see if the MaxRegions supports at least one region. Em seguida, verifique se AutoExposureSupported ou AutoFocusSupported estão definidas como true.Then check to see if either AutoExposureSupported or AutoFocusSupported are true. Se essas condições forem atendidas, o dispositivo poderá aproveitar a detecção de rosto para melhorar a captura.If these conditions are met, then the device can take advantage of face detection to enhance capture.

var regionsControl = _mediaCapture.VideoDeviceController.RegionsOfInterestControl;
bool faceDetectionFocusAndExposureSupported =
    regionsControl.MaxRegions > 0 &&
    (regionsControl.AutoExposureSupported || regionsControl.AutoFocusSupported);