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 criar um componente de Windows Runtime C++/WinRT nativo que converte objetos SoftwareBitmap no tipo OpenCVMat. Isso permite que você use os amplos algoritmos de processamento de imagem do OpenCV em quadros capturados com as APIs da câmera Windows e exiba os resultados em seu aplicativo WinUI 3.
Visão geral
A SoftwareBitmap classe é o formato de imagem comum usado pelas APIs de mídia Windows, enquanto o OpenCV usa a Mat classe. Para fazer a ponte entre esses formatos, crie um componente de runtime do C++/WinRT que:
- Aceita uma
SoftwareBitmapentrada. - Converte-o em um OpenCV
Mat. - Aplica o processamento de imagem desejado.
- Retorna o resultado como um
SoftwareBitmap.
Como o OpenCV é uma biblioteca C++ nativa, você usa um projeto C++/WinRT Windows Runtime Component para criar a ponte. Seu aplicativo WinUI 3 em C# faz referência a esse componente.
Configurar o projeto de componente C++/WinRT
Em Visual Studio, adicione um novo projeto do componente Windows Runtime (C++/WinRT) à sua solução. Nomeie-o como
OpenCVBridge.Baixe o pacote NuGet do OpenCV executando o seguinte comando no Console do Gerenciador de Pacotes para o projeto de bridge:
Install-Package OpenCV.Windows -ProjectName OpenCVBridgeComo alternativa, baixe a versão do OpenCV de opencv.org e configure manualmente os caminhos de inclusão e biblioteca do projeto.
No projeto de bridge
pch.h, adicione os cabeçalhos do OpenCV:#include <opencv2/core.hpp> #include <opencv2/imgproc.hpp> #include <robuffer.h> #include <windows.foundation.h>
Criar a classe de runtime OpenCVHelper
Definir uma classe de runtime que fornece métodos para converter entre SoftwareBitmap e OpenCV Mat. Crie o arquivo OpenCVHelper.idlIDL:
// OpenCVHelper.idl
namespace OpenCVBridge
{
runtimeclass OpenCVHelper
{
OpenCVHelper();
void ProcessBitmap(
Windows.Graphics.Imaging.SoftwareBitmap input,
Windows.Graphics.Imaging.SoftwareBitmap output);
}
}
Implementar a conversão
Em OpenCVHelper.cpp, implemente a conversão de SoftwareBitmap para Mat e vice-versa:
#include "pch.h"
#include "OpenCVHelper.h"
#include "OpenCVHelper.g.cpp"
#include <opencv2/imgproc.hpp>
using namespace winrt;
using namespace Windows::Graphics::Imaging;
namespace winrt::OpenCVBridge::implementation
{
void OpenCVHelper::ProcessBitmap(
SoftwareBitmap const& input,
SoftwareBitmap const& output)
{
// Lock the input buffer for reading
auto inputBuffer = input.LockBuffer(
BitmapBufferAccessMode::Read);
auto inputRef = inputBuffer.CreateReference();
uint8_t* inputData = nullptr;
uint32_t inputSize = 0;
winrt::check_hresult(
inputRef.as<::Windows::Foundation::
IMemoryBufferByteAccess>()->GetBuffer(
&inputData, &inputSize));
auto inputDesc =
inputBuffer.GetPlaneDescription(0);
// Create a Mat from the input data (use Stride for correct row size)
cv::Mat inputMat(
inputDesc.Height,
inputDesc.Width,
CV_8UC4,
inputData,
inputDesc.Stride);
// Lock the output buffer for writing
auto outputBuffer = output.LockBuffer(
BitmapBufferAccessMode::Write);
auto outputRef = outputBuffer.CreateReference();
uint8_t* outputData = nullptr;
uint32_t outputSize = 0;
winrt::check_hresult(
outputRef.as<::Windows::Foundation::
IMemoryBufferByteAccess>()->GetBuffer(
&outputData, &outputSize));
auto outputDesc =
outputBuffer.GetPlaneDescription(0);
cv::Mat outputMat(
outputDesc.Height,
outputDesc.Width,
CV_8UC4,
outputData,
outputDesc.Stride);
// Apply image processing - example: blur
cv::GaussianBlur(inputMat, outputMat, cv::Size(15, 15), 5);
}
}
Note
O código acima usa IMemoryBufferByteAccess para acessar os dados de pixel brutos. Os objetos de entrada e saída SoftwareBitmap devem usar o Bgra8 formato de pixel. Se os quadros de MediaFrameReader usarem um formato diferente, converta-os primeiro com SoftwareBitmap.Convert.
Use o componente de C#
No aplicativo WinUI 3 do C#, adicione uma referência de projeto ao OpenCVBridge componente. Em seguida, chame ProcessBitmap a partir do seu código de processamento de quadros:
using OpenCVBridge;
using Windows.Graphics.Imaging;
private readonly OpenCVHelper _openCVHelper = new();
private void ProcessFrameWithOpenCV(
SoftwareBitmap inputBitmap)
{
// Ensure the bitmap is in Bgra8 format
if (inputBitmap.BitmapPixelFormat != BitmapPixelFormat.Bgra8)
{
inputBitmap = SoftwareBitmap.Convert(
inputBitmap, BitmapPixelFormat.Bgra8);
}
// Create an output bitmap with the same dimensions
var outputBitmap = new SoftwareBitmap(
BitmapPixelFormat.Bgra8,
inputBitmap.PixelWidth,
inputBitmap.PixelHeight,
BitmapAlphaMode.Premultiplied);
// Process with OpenCV
_openCVHelper.ProcessBitmap(inputBitmap, outputBitmap);
// Display the result
DispatcherQueue.TryEnqueue(async () =>
{
var source =
new Microsoft.UI.Xaml.Media.Imaging
.SoftwareBitmapSource();
await source.SetBitmapAsync(outputBitmap);
OutputImage.Source = source;
});
}
Adicionar mais operações de processamento
Você pode estender a OpenCVHelper classe com métodos adicionais para operações específicas. Atualize a IDL e a implementação:
// Add to OpenCVHelper.idl
void ApplyCannyEdges(
Windows.Graphics.Imaging.SoftwareBitmap input,
Windows.Graphics.Imaging.SoftwareBitmap output,
Double threshold1,
Double threshold2);
// Implementation
void OpenCVHelper::ApplyCannyEdges(
SoftwareBitmap const& input,
SoftwareBitmap const& output,
double threshold1,
double threshold2)
{
// ... lock buffers as above ...
cv::Mat grayMat;
cv::cvtColor(inputMat, grayMat, cv::COLOR_BGRA2GRAY);
cv::Mat edges;
cv::Canny(grayMat, edges, threshold1, threshold2);
cv::cvtColor(edges, outputMat, cv::COLOR_GRAY2BGRA);
}
Conteúdo relacionado
Windows developer