OpenCV Mat类型转化为QImage

本文介绍了在QT项目中处理图像时,如何优化OpenCV的Mat类型到QImage类型的转换过程,以提高视频处理的帧率。通过在转换前使用cv::cvtColor将BGR转为RGB,将平均转换时间从50ms降低到10ms,显著提升了处理速度。

        在QT中做项目时如果需要对图像进行处理,经常需要用到Mat类型与QImage类型的项目转换。我最近在利用QT做的视频处理,应用的是VideoCapture类,最后在现实环节需要将Mat转换成QImage类型。视频流态的处理,对单帧的响应速度要求较高,一开始我也是直接用的别人的函数,最后发现Mat转QImage时间太长,做了一个小改进。2592*2048*3的图像的转换速度从平均50ms变成10ms(i5-9300H)。原因主要OpenCV的BGR类型与QImage的RGB类型不同造成,因此在转换时需要将BGR转换为RGB类型。

        我的主要改变是在使用QImage::rgbSwapped()函数前使用:cv::cvtColor(mat,mat,cv::COLOR_BGR2RGB),可以有效提高效率。

        下面直接放代码:

QImage cvMat2QImage(const cv::Mat &mat)
{

        // 8-bits unsigned, NO. OF CHANNELS = 1
        if(mat.type() == CV_8UC1)
        {
            QImage image(mat.cols, mat.rows, QImage::Format_Indexed8);
            image.setColorCount(256);
            for(int i = 0; i < 256; i++)
            {
                image.setColor(i, qRgb(i, i, i));
            }
            uchar *pSrc = mat.data;
            for(int row = 0; row < mat.rows; row ++)
            {
  
OpenCvSharp 中,`Mat` 是用于存储图像数据的核心类,而 `Image` 通常指的是 .NET 中的 `System.Drawing.Image` 或其派生类(如 `Bitmap`)。将 `Mat` 转换为 `Image` 是在图像处理和用户界面交互中常见的需求。以下是几种实现 `Mat` 到 `Image` 转换的方法。 ### 1. 使用 `Cv2.CvtColor` 和 `Mat.ToBitmap()` 方法 OpenCvSharp 提供了扩展方法 `ToBitmap()`,可以将 `Mat` 对象直接转换为 `Bitmap`,这是 `Image` 的一个具体实现。 ```csharp using OpenCvSharp; using System.Drawing; // 读取图像 Mat mat = Cv2.ImRead("test.jpg"); // 转换为 Bitmap Bitmap bitmap = mat.ToBitmap(); // 显示图像 using (var form = new Form()) { var pictureBox = new PictureBox { Image = bitmap, Dock = DockStyle.Fill }; form.Controls.Add(pictureBox); Application.Run(form); } ``` 需要注意的是,如果 `Mat` 的颜色空间不是 BGR(例如是灰度图或 HSV 图像),则需要先进行颜色空间转换[^3]。例如,从 BGR 转换为 RGB: ```csharp Cv2.CvtColor(mat, mat, ColorConversionCodes.BGR2RGB); Bitmap bitmap = mat.ToBitmap(); ``` ### 2. 手动创建 `Bitmap` 并复制数据 如果你希望更细粒度地控制图像数据的复制过程,可以手动创建 `Bitmap` 并使用 `Mat.Data` 来访问原始像素数据: ```csharp using OpenCvSharp; using System.Drawing; using System.Drawing.Imaging; Mat mat = Cv2.ImRead("test.jpg"); // 确保图像是 BGR 格式 if (mat.Channels() == 3) { // 创建 Bitmap Bitmap bitmap = new Bitmap(mat.Width, mat.Height, PixelFormat.Format24bppRgb); BitmapData bitmapData = bitmap.LockBits( new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb); // 复制数据 unsafe { byte* src = mat.Data; byte* dst = (byte*)bitmapData.Scan0.ToPointer(); for (int y = 0; y < mat.Height; y++) { System.Buffer.MemoryCopy( src + y * mat.Step(), dst + y * bitmapData.Stride, mat.Width * 3, mat.Width * 3); } } bitmap.UnlockBits(bitmapData); // 显示图像 using (var form = new Form()) { var pictureBox = new PictureBox { Image = bitmap, Dock = DockStyle.Fill }; form.Controls.Add(pictureBox); Application.Run(form); } } ``` ### 3. 使用 `Cv2.ImEncode` 和 `Image.FromStream` 如果你需要将 `Mat` 转换为 `Image` 并支持多种图像格式(如 JPEG、PNG 等),可以先将 `Mat` 编码为字节流,然后通过 `Image.FromStream` 加载: ```csharp using OpenCvSharp; using System.Drawing; using System.IO; Mat mat = Cv2.ImRead("test.jpg"); // 编码为 JPEG 格式 byte[] imageData; using (Mat temp = new Mat()) { Cv2.CvtColor(mat, temp, ColorConversionCodes.BGR2RGB); // 可选:转换颜色空间 Cv2.ImEncode(".jpg", temp, out imageData); } // 从字节流中加载为 Image using (MemoryStream ms = new MemoryStream(imageData)) { Image image = Image.FromStream(ms); // 显示图像 using (var form = new Form()) { var pictureBox = new PictureBox { Image = image, Dock = DockStyle.Fill }; form.Controls.Add(pictureBox); Application.Run(form); } } ``` ### 注意事项 - `Mat.ToBitmap()` 是最简单的方式,但仅适用于 BGR 或 RGB 格式的图像。如果是其他颜色空间(如 HSV),需要先使用 `Cv2.CvtColor` 进行转换[^2]。 - 在手动复制数据时,需要确保 `PixelFormat` 与 `Mat` 的通道数和数据格式匹配。 - 使用 `ImEncode` 和 `Image.FromStream` 的方式适用于需要保存或传输图像数据的场景,但会带来额外的性能开销。 ---
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值