QT中对Mat类的一些操作

❤️:如果这篇文章对你有帮助的话,别忘了点赞👍收藏⭐️哦,您的鼓励就是我创作的动力,谢谢😃

一、类型转换

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

  1. Mat转QImage
  2. QImage转Mat
  3. 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()<<"从数据库获取图片失败";
    }

}

❤️:这篇文章到此就结束了,如果意犹未尽的话,可以移步至我的个人主页查看其他文章,感谢您的点赞👍收藏⭐️😃

  • 9
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
Qt使用matlab库对mat文件进行读写操作,需要使用Matlab Engine API。以下是一个示例代码,演示了如何读取和写入一个包含cell型的mat文件: ```cpp #include <QCoreApplication> #include <engine.h> #include <iostream> #include <string> #include <vector> #include <mat.h> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); // Start a MATLAB engine Engine *ep = engOpen(nullptr); if (!ep) { std::cerr << "Failed to open MATLAB engine" << std::endl; return 1; } // Load the mat file MATFile *pmat = matOpen("example.mat", "r"); if (!pmat) { std::cerr << "Failed to open mat file" << std::endl; return 1; } // Get the variable from the mat file mxArray *pa = matGetVariable(pmat, "cellVar"); if (!pa) { std::cerr << "Failed to get variable from mat file" << std::endl; return 1; } // Get the data from the mxArray int nRows = mxGetM(pa); int nCols = mxGetN(pa); std::vector<std::vector<double>> data(nRows, std::vector<double>(nCols)); for (int i = 0; i < nRows; ++i) { for (int j = 0; j < nCols; ++j) { mxArray *elem = mxGetCell(pa, i + nRows*j); data[i][j] = mxGetScalar(elem); } } // Close the mat file matClose(pmat); // Do something with the data std::cout << "Read data from mat file:" << std::endl; for (int i = 0; i < nRows; ++i) { for (int j = 0; j < nCols; ++j) { std::cout << data[i][j] << " "; } std::cout << std::endl; } // Write data to a new mat file MATFile *pmatNew = matOpen("exampleNew.mat", "w"); if (!pmatNew) { std::cerr << "Failed to create new mat file" << std::endl; return 1; } mxArray *paNew = mxCreateNumericMatrix(nRows, nCols, mxDOUBLE_CLASS, mxREAL); for (int i = 0; i < nRows; ++i) { for (int j = 0; j < nCols; ++j) { mxArray *elem = mxCreateDoubleScalar(data[i][j]); mxSetCell(paNew, i + nRows*j, elem); } } matPutVariable(pmatNew, "cellVarNew", paNew); // Close the new mat file matClose(pmatNew); // Close the MATLAB engine engClose(ep); return 0; } ``` 在此示例,我们打开了一个名为 `example.mat` 的mat文件,并从获取了名为 `cellVar` 的变量。这个变量包含了一个 `nRows` 行 `nCols` 列的cell数组,其每个元素都是一个double型的数值。我们将数据存储在一个 `std::vector<std::vector<double>>` ,并打印出来。然后,我们将这个数据写入一个新的mat文件 `exampleNew.mat` ,其变量名为 `cellVarNew`。 需要注意的是,这个示例代码假设了mat文件包含了一个名为 `cellVar` 的变量,并且这个变量是一个 `nRows` 行 `nCols` 列的cell数组,其每个元素都是一个double型的数值。如果你的mat文件包含了其他型的变量,或者变量的尺寸和型与上述描述不同,你需要根据实际情况进行修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

枫恋蝶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值