近期做图像处理方面的项目比較多,非常多算法自己从头写的话太浪费时间,并且自己写的也不一定完好,早就听说OpenCV在图像处理算法方面功能非常强大,一直没时间学习,这次正好项目用到了。暂时抱佛脚学习些OpenCV入门知识。由于我的程序界面都是用Qt写的,因此也花了点时间研究了怎样将OpenCV 和Qt 融合在一起,协同工作。

Qt 中处理图像主要用的是QImage类。OpenCV中主要用的是cv::Mat类。以下的两个函数能够用来实现这两个类相互转换。

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);
// Set the color table (used to translate colour indexes to qRgb values)
image.setColorCount(256);
for(int i = 0; i < 256; i++)
{
image.setColor(i, qRgb(i, i, i));
}
// Copy input Mat
uchar *pSrc = mat.data;
for(int row = 0; row < mat.rows; row ++)
{
uchar *pDest = image.scanLine(row);
memcpy(pDest, pSrc, mat.cols);
pSrc += mat.step;
}
return image;
}
// 8-bits unsigned, NO. OF CHANNELS = 3
else if(mat.type() == CV_8UC3)
{
// Copy input Mat
const uchar *pSrc = (const uchar*)mat.data;
// Create QImage with same dimensions as input Mat
QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);
return image.rgbSwapped();
}
else if(mat.type() == CV_8UC4)
{
qDebug() << "CV_8UC4";
// Copy input Mat
const uchar *pSrc = (const uchar*)mat.data;
// Create QImage with same dimensions as input Mat
QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_ARGB32);
return image.copy();
}
else
{
qDebug() << "ERROR: Mat could not be converted to QImage.";
return QImage();
}
}
cv::Mat QImage2cvMat(QImage image)
{
    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());
        break;
    case QImage::Format_RGB888:
        mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine());
        cv::cvtColor(mat, mat, CV_BGR2RGB);
        break;
    case QImage::Format_Indexed8:
        mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine());
        break;
    }
    return mat;
}

程序比較简单,就不多说明了。唯一须要注意的是cvMat 和QImage 对于RGBA 这四个分量的排列顺序是不同样的。转换的时候须要调换一下。可是Qt 的文档中说的非常明白,QImage内部数据存储的方式不能保证以后永远不变。

所以这个代码也不能保证一直是可用的。

以下是五个測试用例。基本上把各种常见情况都覆盖了。

void test1()
{
cv::Mat mat = cv::imread("Q:\\Koala.jpg", cv::IMREAD_UNCHANGED);
cv::cvtColor(mat, mat, CV_BGR2BGRA);
QImage image = cvMat2QImage(mat);
qDebug() << (mat.type() == CV_8UC4);
cvNamedWindow("cvMat2QImage RGB32", CV_WINDOW_AUTOSIZE);
imshow("cvMat2QImage RGB32", mat);
QLabel label;
label.setPixmap(QPixmap::fromImage(image));
label.show();
cv::waitKey(10000);
}
void test2()
{
cv::Mat mat = cv::imread("Q:\\Koala.jpg", cv::IMREAD_UNCHANGED);
cv::cvtColor(mat, mat, CV_BGR2GRAY);
QImage image = cvMat2QImage(mat);
cvNamedWindow("cvMat2QImage gray", CV_WINDOW_AUTOSIZE);
imshow("cvMat2QImage gray", mat);
QLabel label;
label.setPixmap(QPixmap::fromImage(image));
label.show();
cv::waitKey(10000);
}
void test3()
{
QImage image("Q:\\Koala.jpg");
image = image.convertToFormat(QImage::Format_RGB32);
cv::Mat mat = QImage2cvMat(image);
//cv::cvtColor(mat, mat, CV_BGR2RGB);
imshow("QImage2cvMat RGB32", mat);
cv::waitKey(10000);
} void test4()
{
QImage image("Q:\\Koala.jpg");
image = image.convertToFormat(QImage::Format_RGB888);
cv::Mat mat = QImage2cvMat(image);
imshow("QImage2cvMat RGB24", mat);
cv::waitKey(10000);
}
void test5()
{
QImage image("Q:\\Koala.jpg");
image = image.convertToFormat(QImage::Format_Indexed8);
cv::Mat mat = QImage2cvMat(image);
imshow("QImage2cvMat Indexed8", mat);
cv::waitKey(10000);
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
//test1();
//test2();
//test3();
//test4();
//test5();
test1();
return a.exec();
}

QImage 与 cv::Mat 之间的相互转换的更多相关文章

  1. QImage与cv::Mat转换;

    QImage主要格式有QImage::Format_RGB32, QImage::Format_RGB888, QImage::Format_Index8, 不同的格式有不同的排布: 格式部分可以参考 ...

  2. unity3d的Texture2D与opencv的Mat之间的相互转换

    这里的opencv使用的是opencvsharp,它是c#语言对c++的opencv的一层封装,使得c#开发者可以更方便的使用opencv,而不必纠结于跨语言调用的问题. 因此,这里使用的opencv ...

  3. 【资料收集】Converting Between cv::Mat and QImage or QPixmap

    参考: 方法一 Convert between cv::Mat and QImage 两种图片类转换 - Grandyang - 博客园 http://www.cnblogs.com/grandyan ...

  4. Qt QImage与OpenCV Mat转换

    本系列文章由 @yhl_leo 出品,转载请注明出处. 文章链接: http://blog.csdn.net/yhl_leo/article/details/51029382 应一个朋友的要求,整理总 ...

  5. OpenCV图片类cv::Mat和QImage之间进行转换(好多相关文章)

    在使用Qt和OpenCV混合编程时,我们有时需要在两种图片类cv::Mat和QImage之间进行转换,下面的代码参考了网上这个帖子: //##### cv::Mat ---> QImage ## ...

  6. Convert between cv::Mat and QImage 两种图片类转换

    在使用Qt和OpenCV混合编程时,我们有时需要在两种图片类cv::Mat和QImage之间进行转换,下面的代码参考了网上这个帖子: //##### cv::Mat ---> QImage ## ...

  7. Write cv::Mat to a file

    如果我们想把OpenCV中的矩阵数据类型cv::Mat保存在一个文件中,可以使用如下的代码: void writeMatToFile(cv::Mat& m, const char* filen ...

  8. cv::mat转换成QImage的问题

    在进行cv::mat转换为QImage过程中,经常出现问题: cv::Mat image; ...QImage img=QImage((const unsigned char*)(image.data ...

  9. cv::Mat转换QImage

    cvtColor(img, img, CV_BGR2RGB); QImage image((uchar*)img.data,img.cols,img.rows,QImage::Format_RGB88 ...

随机推荐

  1. Unity 集成联通SDK

    我相信Unity程序员都会遇到加入SDK的问题,我相信如果你不会android编程,我相信你的CPU当场计算过快而爆炸!  这里也写笔记希望能帮助大家 如果有讲错的地方,希望大家能回复并且提供答案!  ...

  2. linux虚拟主机管理系统wdcp系列教程之三

    我们安装了网站服务管理系统wdcp之后,在使用过程中可能会出现这样或那样的疑问,下面给大家整理几点出来,方便大家学习.还有不懂的可以到wdlinux论坛寻找相关教程. 1.wdcp后台访问安全设置即限 ...

  3. 对‘pthread_create’未定义的引用

    由于pthread库不是Linux系统默认的库,连接时需要使用库libpthread.a,所以在使用pthread_create创建线程时,在编译中要加-l pthread参数: gcc exampl ...

  4. Bestcoder HDU5059 Help him 字符串处理

    Help him Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total S ...

  5. 图解MapReduceMapReduce整体流程图

    1.图解MapReduceMapReduce整体流程图 并行读取文本中的内容,然后进行MapReduce操作 Map过程:并行读取三行,对读取的单词进行map操作,每个词都以<key,value ...

  6. First Bad Version

    You are a product manager and currently leading a team to develop a new product. Unfortunately, the ...

  7. C++标准程序读书笔记-第三章错误和异常处理

    1.命名空间(namespace)std C++标准程序库中的所有标示符都被定义于一个名为std的namespace 2.标准异常类别 (1)语言本身或标准程序库所抛出的所有异常,都派生自基类exce ...

  8. Haproxy+PXC实现负载均衡

    软件负载均衡一般通过两种方式来实现:基于操作系统的软负载实现和基于第 三方应用的软负载实现.LVS就是基于Linux操作系统实现的一种软负载,HAProxy就是开源的并且基于第三应用实现的软负载.HA ...

  9. python super研究

    # encoding=utf-8 class A(object): def __init__(self): print "初始化a" def run(self): print &q ...

  10. flask-script 安装问题

    > 昨天开始看 flask,第二章最后提到使用 Flask-Script 支持命令行选项,但是用书上的方法安装却出现了问题. 错误信息: 注意最后两行: Could not find a ver ...