QT中对Mat类的一些操作详解

 更新时间:2022年6月8日 16:58  点击:549 作者:桂花年糕仔

一、类型转换

opencv在QT中的应用通常会涉及到这三者的转换,即MatQImageQPixmap
下面分别给出了

  • Mat转QImage
  • QImage转Mat
  • Mat转QPixmap

1️⃣:Mat转QImage

QImage MainWindow::MatToImage(const Mat &m)  //Mat转Image
{
    switch(m.type())
    {
        case CV_8UC1:
        {
            QImage img((uchar *)m.data,m.cols,m.rows,m.cols * 1, QImage::Format_Grayscale8);
            return img;
        }
            break;
        case CV_8UC3:
        {
            QImage img((uchar *)m.data,m.cols,m.rows,m.cols * 3, QImage::Format_RGB888);
            return img.rgbSwapped();  //因为在QT中彩色图象是RGB的顺序,但是在OPENCV中是BGR的顺序,所以要转一下
        }
            break;
        case CV_8UC4:
        {
            QImage img((uchar *)m.data,m.cols,m.rows,m.cols * 4, QImage::Format_ARGB32);
            return img;
        }
            break;
        default:     //如果是默认的,那么将其返回为一个空对象
        {
            QImage img;
            return img;
        }
    }
}

2️⃣:QImage转Mat

Mat MainWindow::ImageToMat(const QImage &img,bool inCloneImageData)  //Image转Mat
{
    switch(img.format())
    {
        case QImage::Format_Indexed8:   //单通道
        {
            Mat  mat( img.height(), img.width(), CV_8UC1,
                          const_cast<uchar*>(img.bits()), static_cast<size_t>(img.bytesPerLine()) );

            return (inCloneImageData ? mat.clone() : mat);
        }
        // 8-bit, 3 通道
        case QImage::Format_RGB32:   //这种写法表示并列关系
        case QImage::Format_RGB888:
        {
            if ( !inCloneImageData )
            {
                qWarning() << "CVS::QImageToCvMat() - Conversion requires cloning because we use a temporary QImage";
            }

            QImage  swapped = img;

            if ( img.format() == QImage::Format_RGB32 )
            {
                swapped = swapped.convertToFormat( QImage::Format_RGB888 );
            }

            swapped = swapped.rgbSwapped();  //因为在QT中彩色图象是RGB的顺序,但是在OPENCV中是BGR的顺序,所以要转一下

            return Mat( swapped.height(), swapped.width(), CV_8UC3,
                        const_cast<uchar*>(swapped.bits()), static_cast<size_t>(swapped.bytesPerLine()) ).clone();
        }
        // 8-bit, 4 channel
        case QImage::Format_ARGB32:
        case QImage::Format_ARGB32_Premultiplied:
        {
            Mat  mat( img.height(), img.width(), CV_8UC4,
                          const_cast<uchar*>(img.bits()), static_cast<size_t>(img.bytesPerLine()) );

            return (inCloneImageData ? mat.clone() : mat);
        }

        // 8-bit, 1 channel
        default:
            qWarning() << "CVS::QImageToCvMat() - QImage format not handled in switch:" << img.format();
            break;
        }
    return Mat();
}

3️⃣:Mat转QPixmap

QPixmap MainWindow::MatToPixmap(const Mat &m)
{
    return QPixmap::fromImage(MatToImage(m));   //相当于先将Mat转成Image,再转成Pixmap
}

二、保存至数据库

我这里是直接将Mat类型的数据以二进制数据流的方式保存到数据库中,有些文章是将文件名及其所在的路径保存到数据库中,这个还是要好看项目需求,个人而言,我这个要更复杂一点。
演示效果如下:

1️⃣:基础界面

2️⃣:磨皮处理

3️⃣:数据库中的数据

4️⃣:核心代码

注意: 创建数据表的时候,字段的类型,一定要满足数据的大小,比方说保存图片一般使用blob相关的类型,其中blob最大为64k,mediumblob最大为16M。

思路,先捕获ui控件(我用于显示图片的控件是QLabel)中的数据,然后进行数据库操作。具体步骤如下:

数据类型:Image —>Mat。

然后再将Mat类型保存到byte数组中,再上传到数据库。(此时有小伙伴可能就要问了,为什么不直接从Image类型转byte数组呢?当然可以,不过我们饶了个弯子也是想让大家学会如何将Mat类型转成byte数组)

上传数据库,用户名+图片数据(这个看自身的需求)

准备数据库查询语句query,用法如下图所示

验证阶段,取回图片,然后显示在右侧的QLabel中,因为我代码中取回的是用户id为33的图片数据,所以显示的是一个水瓶。

void MainWindow::Upmysql()   //将处理的图片上传至数据库
{
    QImage pix=ui->Process_image->pixmap()->toImage();
    Mat m=ImageToMat(pix);  //QImage--->Mat格式转换
    int height = pix.height();   //定义这两者的目的是为了传给Mat的构造函数
    int width = pix.width();
    int iSize = m.total() * m.elemSize();   //记录Mat图像的大小,以便于创建同等大小的字节数组
    unsigned char* bytes = new unsigned char[iSize];   //创建一个字节数组,用于保存二进制数据
    memcpy(bytes, m.data, iSize * sizeof(unsigned char));    //将Mat类型的数据赋给byte数组
    //qDebug()<<QByteArray((char*)bytes, 100);    //查看前100个字符
    QByteArray sbuf = QByteArray::fromRawData((char *)bytes, iSize * sizeof(unsigned char));   //将unsigned char转为QByteArray类型

    QVariant var(sbuf);   //将QByteArray类型转成QVariant以便于插入到MYSql
    QSqlQuery query;   //下面为数据库查询的一种方式,要特别注意格式的要求
    //创建数据表的时候,一定要注意数据的大小,比方说图片blob为64k,mediumblob为16m
    query.prepare("INSERT INTO Image_All (id, img_data) "
                        "VALUES (:id, :img_data)");
    query.bindValue(":id", 77877);    //我这里随便设的
    query.bindValue(":img_data",var);
    if(query.exec())
    {
        qDebug()<<"图片成功上传至数据库";
    }
    else{
        qDebug()<<"图片上传数据库失败";
    }

    QString sql1=QString("select img_data from Image_All where id='33'");   //获取数据库中图片数据
    if(query.exec(sql1)) //执行sql语句是否成功
    {
        while(query.next())//指向下一条
        {
            //根据下标将返回结果进行分割
            QByteArray TEXT1=query.value(0).toByteArray();  //将查询结果以QByteArray形式返回
            unsigned char *data2;
             data2 = reinterpret_cast<unsigned char*>(TEXT1.data());   //将QByteArray类型转为unsigned char
            Mat image=Mat(height,width,CV_8UC3,data2);      //将unsigned char转成Mat类型的数据
            QPixmap temp = MatToPixmap(image);
            ui->Process_image->setPixmap(temp);
        }

    }else
    {
        qDebug()<<"从数据库获取图片失败";
    }

}

到此这篇关于QT中对Mat类的一些操作详解的文章就介绍到这了,更多相关QT Mat操作内容请搜索猪先飞以前的文章或继续浏览下面的相关文章希望大家以后多多支持猪先飞! 

原文出处:https://blog.csdn.net/qq_40077565/article/details/125161507

[!--infotagslink--]

相关文章

  • php svn操作类

    以前我们开发大型项目时都会用到svn来同步,因为开发产品的人过多,所以我们会利用软件来管理,今天发有一居然可以利用php来管理svn哦,好了看看吧。 代码如下 ...2016-11-25
  • C#操作config文件的具体方法

    这篇文章介绍了在C#中对config文件的操作,有需要的朋友可以参考一下...2020-06-25
  • python自动化办公操作PPT的实现

    这篇文章主要介绍了python自动化办公操作PPT的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-02-05
  • Jackson反序列化@JsonFormat 不生效的解决方案

    这篇文章主要介绍了Jackson反序列化@JsonFormat 不生效的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-08-10
  • nodejs文件操作模块FS(File System)常用函数简明总结

    件系统操作相关的函数挺多的。首先可以分为两大类。一类是异步+回调的。 一类是同步的。在这里只对异步的进行整理,同步的只需要在函数名称后面加上Sync即可1. 首先是一类最常规的读写函数,函数名称和形式,应该是起源于C...2014-06-07
  • C#模拟window操作鼠标的方法

    这篇文章主要介绍了C#模拟window操作鼠标的方法,可实现模拟鼠标移动到固定位置后点击右键的功能,涉及鼠标常用事件的操作技巧,需要的朋友可以参考下...2020-06-25
  • python读取和保存mat文件的方法

    本文主要介绍了python读取和保存mat文件的方法,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-08-25
  • 微信小程序手势操作之单触摸点与多触摸点

    这篇文章主要介绍了微信小程序手势操作之单触摸点与多触摸点的相关资料,需要的朋友可以参考下...2017-03-13
  • C#中string.format用法详解

    这篇文章主要介绍了C#中string.format用法,以实例形式较为详细的讲述了string.format格式化的各种用法,非常具有实用价值,需要的朋友可以参考下...2020-06-25
  • python中字符串最常用的十三个处理操作记录

    这篇文章主要给大家介绍了关于python中字符串最常用的13个处理操作的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-03-09
  • 使用@JsonFormat和@DateTimeFormat对Date格式化操作

    这篇文章主要介绍了使用@JsonFormat和@DateTimeFormat对Date格式化操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-08-10
  • Qt 使用Poppler实现pdf阅读器的示例代码

    下面小编就为大家分享一篇Qt 使用Poppler实现pdf阅读器的示例代码,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-04-25
  • 将matplotlib绘图嵌入pyqt的方法示例

    这篇文章主要介绍了将matplotlib绘图嵌入pyqt的方法示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-04-27
  • js操作XML文件的实现方法兼容IE与FireFox

    下面小编就为大家带来一篇js操作XML文件的实现方法兼容IE与FireFox。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2016-07-01
  • C# 模拟浏览器并自动操作的实例代码

    这篇文章主要介绍了C# 模拟浏览器并自动操作的实例代码,文中讲解非常细致,帮助大家更好的理解和学习,感兴趣的朋友可以了解下...2020-11-03
  • c#对字符串操作的技巧小结

    c#对字符串操作的技巧小结,需要的朋友可以参考一下...2020-06-25
  • C#操作PowerPoint的方法

    这篇文章主要介绍了C#操作PowerPoint的方法,涉及C#针对PowerPoint的打开、读取、播放等技巧,非常具有实用价值,需要的朋友可以参考下...2020-06-25
  • Python数据分析之pandas比较操作

    比较操作是很简单的基础知识,不过Pandas中的比较操作有一些特殊的点,本文介绍的非常详细,对正在学习python的小伙伴们很有帮助.需要的朋友可以参考下...2021-05-20
  • Qt定时器和随机数详解

    在前一篇中我们介绍了键盘和鼠标事件,其实还有一个非常常用的事件,就是定时器事件,如果要对程序实现时间上的控制,那么就要使用到定时器。而随机数也是很常用的一个功能,在我们要想产生一个随机的结果时就要使用到随机数。本文我们就来简单介绍一下定时器和随机数。...2020-04-25
  • OpenCvSharp实现Mat对象简单的像素操作

    这篇文章主要介绍了OpenCvSharp实现Mat对象简单的像素操作,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-11-17