服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - QT中对Mat类的一些操作详解

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

2022-12-21 14:43桂花年糕仔 C/C++

本文主要介绍了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️⃣:基础界面

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

2️⃣:磨皮处理

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

3️⃣:数据库中的数据

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

4️⃣:核心代码

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

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

数据类型:Image —>Mat。

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

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

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

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

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

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

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

延伸 · 阅读

精彩推荐
  • C/C++c++ 形状类Shape(派生出圆类Circle和矩形类Rectangle)

    c++ 形状类Shape(派生出圆类Circle和矩形类Rectangle)

    通过C++方式,建立一个形状类Shape作为基类,派生出圆类Circle和矩形类Rectangle 求出面积并获取相关信息...

    DB伟5732021-10-08
  • C/C++贪吃蛇C语言代码实现(难度可选)

    贪吃蛇C语言代码实现(难度可选)

    这篇文章主要为大家详细介绍了贪吃蛇C语言代码实现,游戏难度可供选择,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参...

    小-立子11232021-06-19
  • C/C++C++ STL 四种智能指针的用法详解

    C++ STL 四种智能指针的用法详解

    C++ 标准模板库 STL(Standard Template Library) 一共给我们提供了四种智能指针:auto_ptr、unique_ptr、shared_ptr 和 weak_ptr,今天给大家详细介绍这几种指针的具体用...

    青年夏日10642021-11-19
  • C/C++C语言学生信息管理系统

    C语言学生信息管理系统

    这篇文章主要为大家详细介绍了C语言学生信息管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    Combatting9252021-10-15
  • C/C++C++数字三角形问题与dp算法

    C++数字三角形问题与dp算法

    这篇文章主要介绍了C++数字三角形问题与dp算法的相关知识,非常不错,具有一定的参考借鉴价值 ,需要的朋友可以参考下...

    会武术之白猫6572021-07-01
  • C/C++浅析C++内存布局

    浅析C++内存布局

    本文给大家介绍了C++内存布局的相关知识,通过进程间通信比线程间通信难也是因为进程间的用户空间是相互隔离的,无法相互访问,需要通过进程间通信...

    ~怎么回事啊~7852022-01-21
  • C/C++C++中约数定理的实例详解

    C++中约数定理的实例详解

    这篇文章主要介绍了C++中约数定理的实例详解的相关资料,需要的朋友可以参考下...

    ruangongshi10692021-05-23
  • C/C++C语言编程PAT乙级学习笔记示例分享

    C语言编程PAT乙级学习笔记示例分享

    这篇文章主要为大家介绍了C语言编程PAT乙级学习笔记实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪...

    今年的浙江省状元6312022-12-07