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.
Este artigo mostra como usar a OpenCV (Biblioteca de Pesquisa Visual Computacional de Software Livre), uma biblioteca de código nativa que fornece uma ampla variedade de algoritmos de processamento de imagem, com a classe MediaFrameReader que pode ler quadros de mídia de várias fontes simultaneamente. O código de exemplo neste artigo orienta você na criação de um aplicativo simples que obtém quadros de um sensor de cores, desfoca cada quadro usando a biblioteca OpenCV e exibe a imagem processada em um controle de imagem XAML.
Observação
OpenCV.Win.Core e OpenCV.Win.ImgProc não são atualizados regularmente e não passam nas verificações de conformidade da Loja, portanto, esses pacotes são destinados apenas para experimentação.
Este artigo baseia-se no conteúdo de dois outros artigos:
Processar quadros de mídia com MediaFrameReader – este artigo fornece informações detalhadas sobre como usar MediaFrameReader para obter quadros de uma ou mais fontes de quadro de mídia e descreve, em detalhes, a maior parte do código de exemplo neste artigo. Em particular, Processar quadros de mídia com MediaFrameReader fornece a listagem de código para uma classe auxiliar, FrameRenderer, que lida com a apresentação de quadros de mídia em um elemento XAML Image . O código de exemplo neste artigo também usa essa classe auxiliar.
Processar bitmaps de software com OpenCV – este artigo orienta você na criação de um componente de código nativo do Windows Runtime, OpenCVBridge, que ajuda a converter entre o objeto SoftwareBitmap , usado pelo MediaFrameReader, e o tipo Mat usado pela biblioteca OpenCV. O código de exemplo neste artigo pressupõe que você seguiu as etapas para adicionar o componente OpenCVBridge à sua solução de aplicativo UWP.
Além desses artigos, para exibir e baixar um exemplo de trabalho completo de ponta a ponta do cenário descrito neste artigo, consulte o exemplo de quadros de câmera + OpenCV no repositório GitHub de Exemplos Universais do Windows.
Para começar a desenvolver rapidamente, você pode incluir a biblioteca OpenCV em um projeto de aplicativo UWP usando pacotes NuGet, mas esses pacotes podem não passar no processo de certificação de aplicativo quando você envia seu aplicativo para a Loja, portanto, é recomendável baixar o código-fonte da biblioteca OpenCV e criar os binários por conta própria antes de enviar seu aplicativo. As informações em desenvolvimento com o OpenCV podem ser encontradas em https://opencv.org
Implementar o componente nativo do Tempo de Execução do Windows OpenCVHelper
Siga as etapas em Processar bitmaps de software com OpenCV para criar o componente auxiliar do Tempo de Execução do Windows do OpenCV e adicionar uma referência ao projeto de componente à sua solução de aplicativo UWP.
Localizar grupos de origem de quadros disponíveis
Primeiro, você precisa encontrar um grupo de origem de quadros de mídia do qual os quadros de mídia serão obtidos. Obtenha a lista de grupos de origem disponíveis no dispositivo atual chamando MediaFrameSourceGroup.FindAllAsync. Em seguida, selecione os grupos de origem que fornecem os tipos de sensor necessários para o cenário do aplicativo. Para este exemplo, precisamos simplesmente de um grupo de origem que forneça quadros de uma câmera RGB.
var frameSourceGroups = await MediaFrameSourceGroup.FindAllAsync();
var selectedGroupObjects = frameSourceGroups.Select(group =>
new
{
sourceGroup = group,
colorSourceInfo = group.SourceInfos.FirstOrDefault((sourceInfo) =>
{
// On Xbox/Kinect, omit the MediaStreamType and EnclosureLocation tests
return sourceInfo.SourceKind == MediaFrameSourceKind.Color;
})
}).Where(t => t.colorSourceInfo != null)
.FirstOrDefault();
MediaFrameSourceGroup selectedGroup = selectedGroupObjects?.sourceGroup;
MediaFrameSourceInfo colorSourceInfo = selectedGroupObjects?.colorSourceInfo;
if (selectedGroup == null)
{
return;
}
Inicializar o objeto MediaCapture
Em seguida, você precisa inicializar o objeto MediaCapture para usar o grupo de origem de quadros selecionado na etapa anterior, definindo a propriedade SourceGroup do MediaCaptureInitializationSettings.
Observação
A técnica usada pelo componente OpenCVHelper, descrita em detalhes em Processar bitmaps de software com OpenCV, requer que os dados da imagem residam na memória da CPU, não na memória da GPU. Portanto, você deve especificar MemoryPreference.CPU para o campo MemoryPreference do MediaCaptureInitializationSettings.
Depois que o objeto MediaCapture for inicializado, obtenha uma referência à origem do quadro RGB acessando a propriedade MediaCapture.FrameSources .
mediaCapture = new MediaCapture();
var settings = new MediaCaptureInitializationSettings()
{
SourceGroup = selectedGroup,
SharingMode = MediaCaptureSharingMode.ExclusiveControl,
MemoryPreference = MediaCaptureMemoryPreference.Cpu,
StreamingCaptureMode = StreamingCaptureMode.Video
};
try
{
await mediaCapture.InitializeAsync(settings);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("MediaCapture initialization failed: " + ex.Message);
return;
}
var colorFrameSource = mediaCapture.FrameSources[colorSourceInfo.Id];
Inicializar o MediaFrameReader
Em seguida, crie um MediaFrameReader para a origem do quadro RGB recuperada na etapa anterior. Para manter uma boa taxa de quadros, você pode querer processar quadros que tenham uma resolução menor do que a resolução do sensor. Este exemplo fornece o argumento BitmapSize opcional para o método MediaCapture.CreateFrameReaderAsync para solicitar que os quadros fornecidos pelo leitor de quadros sejam redimensionados para 640 x 480 pixels.
Depois de criar o leitor de quadros, registre um manipulador para o evento FrameArrived. Em seguida, crie um novo objeto SoftwareBitmapSource, que a classe auxiliar FrameRenderer usará para apresentar a imagem processada. Em seguida, chame o construtor para o FrameRenderer. Inicialize a instância da classe OpenCVHelper definida no componente OpenCVBridge Windows Runtime. Essa classe auxiliar é usada no manipulador FrameArrived para processar cada quadro. Por fim, inicie o leitor de quadros chamando StartAsync.
BitmapSize size = new BitmapSize() // Choose a lower resolution to make the image processing more performant
{
Height = 480,
Width = 640
};
mediaFrameReader = await mediaCapture.CreateFrameReaderAsync(colorFrameSource, MediaEncodingSubtypes.Argb32, size);
mediaFrameReader.FrameArrived += ColorFrameReader_FrameArrived_OpenCV;
imageElement.Source = new SoftwareBitmapSource();
_frameRenderer = new FrameRenderer(imageElement);
await mediaFrameReader.StartAsync();
Manipular o evento FrameArrived
O evento FrameArrived é gerado sempre que um novo quadro está disponível no leitor de quadros. Chame TryAcquireLatestFrame para obter o quadro, se ele existir. Obtenha o SoftwareBitmap do MediaFrameReference. Observe que a classe CVHelper usada neste exemplo requer que as imagens usem o formato de pixel BRGA8 com alfa pré-multiplicado. Se o quadro passado para o evento tiver um formato diferente, converta o SoftwareBitmap para o formato correto. Em seguida, crie um SoftwareBitmap para ser usado como destino da operação de desfoque. As propriedades da imagem de origem são usadas como argumentos para o construtor criar um bitmap com formato correspondente. Chame o método Blur da classe auxiliar para processar o quadro. Por fim, passe a imagem de saída da operação de desfoque para PresentSoftwareBitmap, o método da classe auxiliar FrameRenderer que exibe a imagem no controle de imagem XAML com o qual ela foi inicializada.
private void ColorFrameReader_FrameArrived_OpenCV(MediaFrameReader sender, MediaFrameArrivedEventArgs args)
{
var mediaFrameReference = sender.TryAcquireLatestFrame();
if (mediaFrameReference != null)
{
SoftwareBitmap openCVInputBitmap = null;
var inputBitmap = mediaFrameReference.VideoMediaFrame?.SoftwareBitmap;
if (inputBitmap != null)
{
//The XAML Image control can only display images in BRGA8 format with premultiplied or no alpha
if (inputBitmap.BitmapPixelFormat == BitmapPixelFormat.Bgra8
&& inputBitmap.BitmapAlphaMode == BitmapAlphaMode.Premultiplied)
{
openCVInputBitmap = SoftwareBitmap.Copy(inputBitmap);
}
else
{
openCVInputBitmap = SoftwareBitmap.Convert(inputBitmap, BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied);
}
SoftwareBitmap openCVOutputBitmap = new SoftwareBitmap(BitmapPixelFormat.Bgra8, openCVInputBitmap.PixelWidth, openCVInputBitmap.PixelHeight, BitmapAlphaMode.Premultiplied);
// operate on the image and render it
openCVHelper.Blur(openCVInputBitmap, openCVOutputBitmap);
_frameRenderer.PresentSoftwareBitmap(openCVOutputBitmap);
}
}
}
Tópicos relacionados
- Câmera
- Captura básica de fotos, áudio e vídeo com MediaCapture
- Processar quadros de mídia com o MediaFrameReader
- Processe bitmaps de software com OpenCV
- Exemplo de quadros de câmera
- Molduras de câmera + amostra de OpenCV