You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C++/winrt中将winrt::ImageSource转换为OpenCV的cv::Mat?

WinRT ImageSource 转 cv::Mat 实现方案

ImageSource 是WinRT中的抽象基类,本身没有直接暴露像素数据的接口,必须先将其转换为具体的派生类型(比如SoftwareBitmapSource、WriteableBitmap),再借助你已实现的转换函数完成操作。

步骤1:修正现有SoftwareBitmap转换函数的小问题

你现有的ToMat(SoftwareBitmap)函数存在未定义变量reference的错误,先修正这个问题:

cv::Mat ImageConverter::ToMat(winrt::SoftwareBitmap const& from)
{
    winrt::BitmapBuffer buffer = from.LockBuffer(winrt::BitmapBufferAccessMode::ReadWrite);
    auto reference = buffer.CreateReference(); // 补全变量定义
    auto interop = reference.as<Windows::Foundation::IMemoryBufferByteAccess>();
    uint8_t* pixels{};
    uint32_t capacity{};
    winrt::check_hresult(interop->GetBuffer(&pixels, &capacity));
    cv::Mat mat(from.PixelHeight(), from.PixelWidth(), CV_8UC4);
    memcpy(mat.data, pixels, 4ull * from.PixelHeight() * from.PixelWidth());
    return mat;
}

步骤2:实现ImageSource到cv::Mat的转换函数

通过try_as安全判断ImageSource的实际类型,分情况处理:

cv::Mat ToMat(winrt::Microsoft::UI::Xaml::Media::ImageSource const& from)
{
    // 尝试转换为WriteableBitmap,复用现有转换函数
    if (auto writeableBitmap = from.try_as<winrt::WriteableBitmap>())
    {
        return ToMat(writeableBitmap);
    }

    // 尝试转换为SoftwareBitmapSource,获取内部SoftwareBitmap后转换
    if (auto softwareBitmapSource = from.try_as<winrt::SoftwareBitmapSource>())
    {
        winrt::SoftwareBitmap softwareBitmap;
        winrt::check_hresult(softwareBitmapSource.GetSoftwareBitmap(softwareBitmap));
        return ImageConverter::ToMat(softwareBitmap);
    }

    // 扩展处理BitmapImage类型(可选)
    if (auto bitmapImage = from.try_as<winrt::BitmapImage>())
    {
        // 从Uri获取数据流并解码为SoftwareBitmap
        auto streamRef = bitmapImage.UriSource().OpenReadAsync().get();
        auto decoder = winrt::BitmapDecoder::CreateAsync(streamRef).get();
        auto softwareBitmap = decoder.GetSoftwareBitmapAsync().get();
        
        // 统一格式为BGRA8(匹配CV_8UC4)
        if (softwareBitmap.BitmapPixelFormat() != winrt::BitmapPixelFormat::Bgra8 ||
            softwareBitmap.BitmapAlphaMode() != winrt::BitmapAlphaMode::Premultiplied)
        {
            softwareBitmap = winrt::SoftwareBitmap::Convert(softwareBitmap, 
                winrt::BitmapPixelFormat::Bgra8, 
                winrt::BitmapAlphaMode::Premultiplied);
        }
        return ImageConverter::ToMat(softwareBitmap);
    }

    // 不支持的类型返回空Mat
    return cv::Mat();
}

关键说明

  • try_as是WinRT安全类型转换的标准方式,避免强制转换失败导致崩溃。
  • 处理BitmapImage时需要先解码为SoftwareBitmap,并确保格式与OpenCV的CV_8UC4(BGRA8)一致。
  • 异步函数需通过.get()同步等待,确保数据加载完成再进行转换。

内容的提问来源于stack exchange,提问作者CpTea

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 15:34:59