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

目录
  • 一、类型转换
  • 二、保存至数据库

一、类型转换

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操作内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 在Qt中正确的设置窗体的背景图片的几种方法总结

    Qt中正确的设置窗体的背景图片的方法大致有两种,下面将逐个讲解: 一. 利用styleSheet设置窗体的背景图片 使用stylesheet设置窗体的背景图片的时候,可以直接按照下图的操作去进行即可,如下图所示: 但是,需要注意的是: 1.在QWidget中这种方法是不行的,如果你足够细心的话,你会发现使用同样的设置背景图片的方法,背景图片其实并没有发生真实改变,但是它的子窗体背景图片是会发生改变的. 其实我们可以通过在添加一个i额QWidget来解决这个问题,即在QtDesigner中添加一个

  • Qt串口通信开发之QSerialPort模块详细使用方法与实例

    Qt串口通信基础及名词说明 串口通信(Serial Communications)的概念非常简单,串口按位(bit)发送和接收字节.尽管比按字节(byte)的并行通信慢,但是串口可以在使用一根线发送数据的同时用另一根线接收数据.它很简单并且能够实现远距离通信.比如IEEE488定义并行通行状态时,规定设备线总长不得超过20米,并且任意两个设备间的长度不得超过2米: 而对于串口而言,长度可达1200米.典型地,串口用于ASCII码字符的传输.通信使用3根线完成,分别是地线.发送.接收.由于串口通信

  • Qt GUI图形图像开发之QT表格控件QTableView详细使用方法与实例

    QT表格控件QTableView简介 ​ 表格视图控件QTableView,需要和QStandardItemModel, 配套使用,这套框架是基于MVC设计模式设计的,M(Model)是QStandardItemModel数据模型,不能单独显示出来.V(view)是指QTableView视图,要来显示数据模型,C(controllor)控制在Qt中被弱化,与View合并到一起. QTableView简单使用实例 ​ QStandardItmeModel表格的数据模型,那么这个模型需要填上每一行每

  • Qt串口通信开发之Qt串口通信模块QSerialPort开发完整实例(串口助手开发)

    之前自己写了用于上位机做基本收发的界面,独立出来相当于一个串口助手,先贴图: 功能作为串口助手来说还算完善,五个发送槽,一个接收槽,可以检测可用串口并加上相关标志,串口设置,记数功能,还有菜单栏上的文件操作和一些选择功能. 下面说一说这个项目: 做这个串口助手分为两步,第一步是设计界面,第二部是功能的代码实现. 一.界面设计 界面设计用Qt Designer,当然用Qt Creator的界面编辑器也可以,只不过感觉Qt Designer更好用一点,因为可以随时运行查看你的界面效果而不用编译整个项

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

    目录 一.类型转换 二.保存至数据库 一.类型转换 opencv在QT中的应用通常会涉及到这三者的转换,即Mat.QImage.QPixmap.下面分别给出了 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

  • 基于Qt OpenCV的图像灰度化像素操作详解

    效果图 实现代码 #ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include<opencv2/opencv.hpp> using namespace cv; QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACE class Widget : public QWidget { Q_OBJECT public: Widget(QWidget *

  • python 中Mixin混入类的使用方法详解

    目录 前言 Mixin 与继承的区别 总结 前言 最近在看sanic的源码,发现有很多Mixin的类,大概长成这个样子 class BaseSanic(    RouteMixin,    MiddlewareMixin,    ListenerMixin,    ExceptionMixin,    SignalMixin,    metaclass=SanicMeta, ): 于是对于这种 Mixin 研究了一下,其实也没什么新的东西,Mixin 又称混入,只是一种编程思想的体现,但是在使用

  • Java中的Collections类的使用示例详解

    Collections的常用方法及其简单使用 代码如下: package Collections; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Stack; public class collections { public static void main(String[]args){ int array[]={125,75,56,7}; Li

  • 工作中Java集合的规范使用操作详解

    目录 一.前言 二.规范使用Java集合 一.前言 现代软件行业的高速发展对开发者的综合素质要求越来越高,因为不仅是编程知识点,其它维度的知识点也会影响到软件的最终交付质量.比如:五花八门的错误码会人为地增加排查问题的难度:数据库的表结构和索引设计缺陷带来的系统架构缺陷或性能风险:工程结构混乱导致后续项目维护艰难:没有鉴权的漏洞代码容易被黑客攻击等.依据约束力强弱及故障敏感性,规约依次分为[强制].[推荐].[参考]三大类.在延伸的信息中,“说明”对规约做了适当扩展和解释:“正例”提倡什么样的编

  • Java中对List集合的常用操作详解

    目录: 1.list中添加,获取,删除元素: 2.list中是否包含某个元素: 3.list中根据索引将元素数值改变(替换): 4.list中查看(判断)元素的索引: 5.根据元素索引位置进行的判断: 6.利用list中索引位置重新生成一个新的list(截取集合): 7.对比两个list中的所有元素: 8.判断list是否为空: 9.返回Iterator集合对象: 10.将集合转换为字符串: 11.将集合转换为数组: 12.集合类型转换: 备注:内容中代码具有关联性. 1.list中添加,获取,

  • 对tensorflow中cifar-10文档的Read操作详解

    前言 在tensorflow的官方文档中得卷积神经网络一章,有一个使用cifar-10图片数据集的实验,搭建卷积神经网络倒不难,但是那个cifar10_input文件着实让我费了一番心思.配合着官方文档也算看的七七八八,但是中间还是有一些不太明白,不明白的mark一下,这次记下一些已经明白的. 研究 cifar10_input.py文件的read操作,主要的就是下面的代码: if not eval_data: filenames = [os.path.join(data_dir, 'data_b

  • c# Thread类线程常用操作详解

    创建线程 线程是通过扩展 Thread 类创建的.扩展的 Thread 类调用 Start() 方法来开始子线程的执行. 下面的程序演示了这个概念: class ThreadCreationProgram { public static void CallToChildThread() { Console.WriteLine("Child thread starts"); } static void Main(string[] args) { ThreadStart childref

  • Qt开发之QString类的使用教程详解

    目录 介绍 QString常用函数 常用四则运算符 介绍 采用Unicode编码 采用隐式共享技术,节省内存和不必要的数据拷贝 隐式共享介于浅拷贝和深拷贝之间,当两个string对象赋值时,会实现浅拷贝(共享一块内存),如果某个对象被修改了,则会实现深拷贝(从新开辟内存) 跨平台使用,不需要考虑不同平台的兼容性 QString直接支持字符串与数字的相互转换 QString直接支持字符串大小比较 QString直接支持不同字符编码间的相互转换 QString直接支持std::string和std:

  • JS利用prototype给类添加方法操作详解

    本文实例讲述了JS利用prototype给类添加方法操作.分享给大家供大家参考,具体如下: 1.如何定义一个简单的类? 以下是一个没有任何属性和方法的类的定义: function MyClass(){}; 你可能会想,这不就是个简单的函数声明?没错,这个函数就是一个类的定义的实现.如何使用这个类呢?看下面的代码: var cls1 = new MyClass(); 这样,利用new就可以生成MyClass的一个实例了.所以在js中可以说函数就是类,类就是函数. 2.给类增加属性和方法 funct

随机推荐