Qt QImage 与 OpenCV 的 Mat 类型的相互转化(2)
在我的以前的一篇博客中其实已经介绍过转化方法。
https://blog.csdn.net/liyuanbhu/article/details/46662115
但是那篇博客里的代码不够完善。主要是转化后的图像与转化前的图像是否共享内存数据比较的乱。有些情况是共享内存的,有些情况又没有共享内存。代码的说明里也没有交代清楚。给使用我这个代码的人可能会造成困扰。所以就又写了篇博客。把代码进一步完善。
这一版的代码可以控制是否共享内存,对于 RGB24 格式的图像,也可以控制是否交换 R 与 B 的位置。通过这两点改进,可以在某些应用场景下大大的提高代码的运行速度。
下面是代码:
/****************************************************************************
** file: convert.h
** brief: cv::Mat 与 QImage 之间的转换函数。在 Qt 程序中使用 OpenCV 时有用。
** Copyright (C) LiYuan
** Author: LiYuan
** E-Mail: 18069211#qq(.)com
** Version 2.0.1
** Last modified: 2019.01.11
** Modified By: LiYuan
****************************************************************************/
#ifndef QT_OPENCV_CONVERT_H
#define QT_OPENCV_CONVERT_H
#include <QtCore/QDebug>
#include <QtGui/QImage>
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/opencv.hpp"
/**
* @brief 将 OpenCV 的 cv::Mat 类型图像转换为 QImage 类型
* @param mat 待转换的图像,支持 CV_8UC1、CV_8UC3、CV_8UC4 三种OpenCV 的数据类型
* @param clone true 表示与 Mat 不共享内存,更改生成的 mat 不会影响原始图像,false 则会与 mat 共享内存
* @param rb_swap 只针对 CV_8UC3 格式,如果 true 则会调换 R 与 B RGB->BGR,如果共享内存的话原始图像也会发生变化
* @return 转换后的 QImage 图像
*/
QImage cvMat2QImage(const cv::Mat& mat, bool clone = true, bool rb_swap = true);
/**
* @brief 将 QImage 的类型图像转换为 cv::Mat 类型
* @param image 待转换的图像,支持 Format_Indexed8/Format_Grayscale、24 位彩色、32 位彩色格式,
* @param clone true 表示与 QImage 不共享内存,更改生成的 mat 不会影响原始图像,false 则会与 QImage 共享内存
* @param rg_swap 只针对 RGB888 格式,如果 true 则会调换 R 与 B RGB->BGR,如果共享内存的话原始图像也会发生变化
* @return 转换后的 cv::Mat 图像
*/
cv::Mat QImage2cvMat(QImage &image, bool clone = false, bool rb_swap = true);
#endif
/****************************************************************************
** file: convert.cpp
** brief: cv::Mat 与 QImage 之间的转换函数。在 Qt 程序中使用 OpenCV 时有用。
** Copyright (C) LiYuan
** Author: LiYuan
** E-Mail: 18069211#qq(.)com
** Version 2.0.1
** Last modified: 2019.01.11
** Modified By: LiYuan
****************************************************************************/
#include "convert.h"
QImage cvMat2QImage(const cv::Mat& mat, bool clone, bool rb_swap)
{
const uchar *pSrc = (const uchar*)mat.data;
// 8-bits unsigned, NO. OF CHANNELS = 1
if(mat.type() == CV_8UC1)
{
//QImage image(mat.cols, mat.rows, QImage::Format_Grayscale8);
QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_Grayscale8);
if(clone) return image.copy();
return image;
}
// 8-bits unsigned, NO. OF CHANNELS = 3
else if(mat.type() == CV_8UC3)
{
// Create QImage with same dimensions as input Mat
QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);
if(clone)
{
if(rb_swap) return image.rgbSwapped();
return image.copy();
}
else
{
if(rb_swap)
{
cv::cvtColor(mat, mat, CV_BGR2RGB);
}
return image;
}
}
else if(mat.type() == CV_8UC4)
{
qDebug() << "CV_8UC4";
QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_ARGB32);
if(clone) return image.copy();
return image;
}
else
{
qDebug() << "ERROR: Mat could not be converted to QImage.";
return QImage();
}
}
cv::Mat QImage2cvMat(QImage &image, bool clone, bool rb_swap)
{
cv::Mat mat;
//qDebug() << image.format();
switch(image.format())
{
case QImage::Format_ARGB32:
case QImage::Format_RGB32:
case QImage::Format_ARGB32_Premultiplied:
mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void *)image.constBits(), image.bytesPerLine());
if(clone) mat = mat.clone();
break;
case QImage::Format_RGB888:
mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void *)image.constBits(), image.bytesPerLine());
if(clone) mat = mat.clone();
if(rb_swap) cv::cvtColor(mat, mat, CV_BGR2RGB);
break;
case QImage::Format_Indexed8:
case QImage::Format_Grayscale8:
mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void *)image.bits(), image.bytesPerLine());
if(clone) mat = mat.clone();
break;
}
return mat;
}
欢迎大家使用。也欢迎反馈使用中遇到的问题。