优化 OpenCV Mat 到 BitmapSource 的转换以用于 WPF 显示

问题描述 投票:0回答:1

Stack Overflow 社区您好,

我正在使用 C# 中的 OpenCvSharp 开发实时人脸检测应用程序。当前的代码从视频源捕获帧并对其进行处理以检测面部并在其周围绘制边界框。然后,这些处理过的帧将显示在 WPF 图像控件中。

当前的实现感觉优化不够。具体来说,将 Mat 转换为 WPF 显示的 BitmapSource 可能会引入不必要的开销。

这是我的代码的主要部分:

调用updatedisplay方法的方法

public async Task Main(int selectedItemIndex, Image imageControl, CancellationToken token)
    {
        Mat frame = new Mat();
        await UpdateDisplay(frame, imageControl);
    }

这就是我转换框架的方式

    private async Task UpdateDisplay(Mat frame, Image imageControl)
        {
            await System.Windows.Application.Current.Dispatcher.InvokeAsync(() =>
            {
                var bitmap = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(frame);
                var bitmapSource = ConvertToBitmap(bitmap);
                imageControl.Source = bitmapSource;
            });
        }



        public static BitmapSource ConvertToBitmap(System.Drawing.Bitmap bitmap)
        {
            var bitmapData = bitmap.LockBits(
                new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height),
                System.Drawing.Imaging.ImageLockMode.ReadOnly, bitmap.PixelFormat);

            try
            {
                var bitmapSource = new WriteableBitmap(bitmapData.Width, bitmapData.Height,
                    bitmap.HorizontalResolution, bitmap.VerticalResolution,
                    PixelFormats.Bgr24, null);

                bitmapSource.Lock();
                bitmapSource.WritePixels(new Int32Rect(0, 0, bitmapData.Width, bitmapData.Height),
                    bitmapData.Scan0, bitmapData.Stride * bitmapData.Height, bitmapData.Stride);
                bitmapSource.Unlock();

                return bitmapSource;
            }
            finally
            {
                bitmap.UnlockBits(bitmapData);
            }
        }

我需要帮助的一些事情:

  1. 有没有更优化的方式来转换Mat对象 toBitmapSource 用于 WPF 显示而不使用 System.Drawing.Bitmap 作为中介?
  2. 您推荐的任何其他性能改进或最佳实践 了解应用程序的整体流程和设计?
  3. 我也热衷于了解任何陷阱或潜在的记忆 当前方法的泄漏以及如何解决这些问题。

预先感谢您的见解和建议!

c# wpf opencv bitmap mat
1个回答
0
投票

我的建议是使用WriteableBitmap,然后从矩阵复制数据。这应该避免任何不必要的分配和数据复制

首先创建与矩阵具有相同大小和类型的像素的可写位图。如果大小或像素格式可以更改,您可能需要在更新之前进行检查。

那就打电话吧

myWriteableBitmap.WritePixels(
    new Int32Rect(0, 0, image.Width, image.Height)
    frame.Data, // pointer to buffer
    frame.AllocatedMemorySize, // buffer size
    frame.Width * bytesPerPixel // stride of source, i.e. number of bytes used for each row
); 

如果您只处理一种类型的图像或查找表,或者由某些现有方法提供,则每个像素的字节数可以是常量。

© www.soinside.com 2019 - 2024. All rights reserved.