近期做图像处理方面的项目比較多,非常多算法自己从头写的话太浪费时间,并且自己写的也不一定完好,早就听说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. 代码中实际运用memcached——java

    以下文章取自:http://jameswxx.iteye.com/blog/1168711 memcached的java客户端有好几种,http://code.google.com/p/memcach ...

  2. 虚拟化之KVM的安装续篇

    介于上篇文章用的网络的方式安装系统并且磁盘文件格式为raw,不支持快照,所以再写下这篇文章,方便后续查看. 目的:通过nfs安装系统,磁盘文件格式为qcow2(支持快照). 如下操作和上篇文章只有部分 ...

  3. js库开发

    <!DOCTYPE html><html>    <head>        <meta charset="UTF-8">      ...

  4. C#自定义控件在添加引用后不显示在工具箱的解决方法

    先说一些背景: 在开发C#项目时,发现很多控件存在复用的情况,控件的属性都是要设置成一样的,我就想,能不能设置一个类来存放这个控件,这样我每次用的时候直接加一些特殊的操作就可以了,不需要再次设置控件属 ...

  5. WPF中当鼠标移到按钮上时,按钮的背景图片消失的问题

    如果给按钮设置了背景图片,当鼠标移到按钮上的时候,按钮就好变成一个浅蓝色的按钮,背景图片就消失了,对于这个问题有很多解决方法,我只分享一下我的解决方法. 我第一次用的方式是在按钮中添加一个图片,不用背 ...

  6. 自定义的GitLab 头像无法正常显示以及URL总是指向localhost

    解决指向localhost的问题: 编辑gitlab的配置vi /etc/gitlab/gitlab.rb,修改external_url 参数值 [Mesogene@localhost ~]$ sud ...

  7. 【IOS学习基础】文件相关

    一.沙盒(SandBox) 1.沙盒机制 1> 每个应用都有属于自己的存储空间,即沙盒. 2> 应用只能访问自己的沙盒,不可访问其他区域. 3> 如果应用需要进行文件操作,则必须将文 ...

  8. css3:border-radius圆角边框详解 (变圆 图片)

    转:http://www.kuqin.com/shuoit/20141014/342620.html border-radius:50% 今天来聊聊这个border-radius属性,radius的英 ...

  9. 运行加速多线程和GPU

    http://blog.csdn.net/augusdi/article/details/11883003

  10. kettle查询出来的真实值被识别为null

    问题描述: 通过关联表查询出来的applyId(申请编号),在数据流里也是能看到的,但是在写入到数据表中的时候,由于设置了这个字段不能为空,所以一直报错. 问题实质: 数据流内存在的数据却不能保存,原 ...