Opencv Mat 转 ImageSource,WinUI3 极致性能版

Opencv Mat 转 ImageSource,WinUI3 极致性能版 说明参考了网上一些资料从 Opencv Mat 转换到 ImageSource 过程中会有1~3次额外的全量复制操作。通过优化可以把额外的全量复制操作都省略掉。下面的代码经过测试目前没有问题。C/WinRT 版本代码如下winrt::Windows::Foundation::IAsyncOperationwinrt::Microsoft::UI::Xaml::Media::ImageSource MatConverter::ToImageSourceAsync(cv::Mat const mat) { // 1. 创建一个 SoftwareBitmap winrt::Windows::Graphics::Imaging::SoftwareBitmap bitmap{ winrt::Windows::Graphics::Imaging::BitmapPixelFormat::Bgra8, mat.cols, mat.rows, winrt::Windows::Graphics::Imaging::BitmapAlphaMode::Premultiplied }; // 2. 将 Mat 复制到 SoftwareBitmap { winrt::Windows::Graphics::Imaging::BitmapBuffer buffer bitmap.LockBuffer( winrt::Windows::Graphics::Imaging::BitmapBufferAccessMode::Write ); winrt::Windows::Foundation::IMemoryBufferReference reference buffer.CreateReference(); uint8_t* dataIn{ nullptr }; uint32_t capacity{}; reference.as::Windows::Foundation::IMemoryBufferByteAccess()-GetBuffer( dataIn, capacity ); cv::Mat bgrMat( cv::Size{mat.cols, mat.rows}, CV_8UC4, dataIn); cv::cvtColor(mat, bgrMat, cv::ColorConversionCodes::COLOR_BGR2BGRA); } winrt::Microsoft::UI::Xaml::Media::Imaging::SoftwareBitmapSource source{}; co_await source.SetBitmapAsync(bitmap); co_return source; }C# 版本代码如下// 为了访问 SoftwareBitmap 的数据地址需要使用以下 Com 接口 [GeneratedComInterface] [Guid(5b0d3235-4dba-4d44-865e-8f1d0e4fd04d)] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal unsafe partial interface IMemoryBufferByteAccess { void GetBuffer(out byte* buffer, out uint capacity); } // Mat 转 ImageSource public static async TaskSoftwareBitmapSource ToImageSourceAsync(Mat mat) { using var bitmap new SoftwareBitmap( BitmapPixelFormat.Bgra8, mat.Width, mat.Height, BitmapAlphaMode.Premultiplied); BitmapBuffer buffer bitmap.LockBuffer(BitmapBufferAccessMode.Write); var reference buffer.CreateReference(); var byteAccess reference.AsIMemoryBufferByteAccess(); unsafe { byteAccess.GetBuffer(out byte* pDest, out uint capacity); using var bgrMat Mat.FromPixelData(mat.Rows, mat.Cols, MatType.CV_8UC4, (nint)pDest); Cv2.CvtColor(mat, bgrMat, ColorConversionCodes.BGR2BGRA); } reference.Dispose(); buffer.Dispose(); var source new SoftwareBitmapSource(); await source.SetBitmapAsync(bitmap); return source; }