QT中對Mat類的一些操作詳解
一、類型轉(zhuǎn)換
opencv在QT中的應(yīng)用通常會涉及到這三者的轉(zhuǎn)換,即Mat、QImage、QPixmap。
下面分別給出了
- Mat轉(zhuǎn)QImage
- QImage轉(zhuǎn)Mat
- Mat轉(zhuǎn)QPixmap
1??:Mat轉(zhuǎn)QImage
QImage MainWindow::MatToImage(const Mat &m) //Mat轉(zhuǎn)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(); //因?yàn)樵赒T中彩色圖象是RGB的順序,但是在OPENCV中是BGR的順序,所以要轉(zhuǎn)一下
}
break;
case CV_8UC4:
{
QImage img((uchar *)m.data,m.cols,m.rows,m.cols * 4, QImage::Format_ARGB32);
return img;
}
break;
default: //如果是默認(rèn)的,那么將其返回為一個空對象
{
QImage img;
return img;
}
}
}
2??:QImage轉(zhuǎn)Mat
Mat MainWindow::ImageToMat(const QImage &img,bool inCloneImageData) //Image轉(zhuǎn)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: //這種寫法表示并列關(guān)系
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(); //因?yàn)樵赒T中彩色圖象是RGB的順序,但是在OPENCV中是BGR的順序,所以要轉(zhuǎn)一下
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轉(zhuǎn)QPixmap
QPixmap MainWindow::MatToPixmap(const Mat &m)
{
return QPixmap::fromImage(MatToImage(m)); //相當(dāng)于先將Mat轉(zhuǎn)成Image,再轉(zhuǎn)成Pixmap
}
二、保存至數(shù)據(jù)庫
我這里是直接將Mat類型的數(shù)據(jù)以二進(jìn)制數(shù)據(jù)流的方式保存到數(shù)據(jù)庫中,有些文章是將文件名及其所在的路徑保存到數(shù)據(jù)庫中,這個還是要好看項(xiàng)目需求,個人而言,我這個要更復(fù)雜一點(diǎn)。
演示效果如下:
1??:基礎(chǔ)界面

2??:磨皮處理

3??:數(shù)據(jù)庫中的數(shù)據(jù)

4??:核心代碼
注意: 創(chuàng)建數(shù)據(jù)表的時候,字段的類型,一定要滿足數(shù)據(jù)的大小,比方說保存圖片一般使用blob相關(guān)的類型,其中blob最大為64k,mediumblob最大為16M。
思路,先捕獲ui控件(我用于顯示圖片的控件是QLabel)中的數(shù)據(jù),然后進(jìn)行數(shù)據(jù)庫操作。具體步驟如下:
數(shù)據(jù)類型:Image —>Mat。
然后再將Mat類型保存到byte數(shù)組中,再上傳到數(shù)據(jù)庫。(此時有小伙伴可能就要問了,為什么不直接從Image類型轉(zhuǎn)byte數(shù)組呢?當(dāng)然可以,不過我們饒了個彎子也是想讓大家學(xué)會如何將Mat類型轉(zhuǎn)成byte數(shù)組)
上傳數(shù)據(jù)庫,用戶名+圖片數(shù)據(jù)(這個看自身的需求)
準(zhǔn)備數(shù)據(jù)庫查詢語句query,用法如下圖所示

驗(yàn)證階段,取回圖片,然后顯示在右側(cè)的QLabel中,因?yàn)槲掖a中取回的是用戶id為33的圖片數(shù)據(jù),所以顯示的是一個水瓶。

void MainWindow::Upmysql() //將處理的圖片上傳至數(shù)據(jù)庫
{
QImage pix=ui->Process_image->pixmap()->toImage();
Mat m=ImageToMat(pix); //QImage--->Mat格式轉(zhuǎn)換
int height = pix.height(); //定義這兩者的目的是為了傳給Mat的構(gòu)造函數(shù)
int width = pix.width();
int iSize = m.total() * m.elemSize(); //記錄Mat圖像的大小,以便于創(chuàng)建同等大小的字節(jié)數(shù)組
unsigned char* bytes = new unsigned char[iSize]; //創(chuàng)建一個字節(jié)數(shù)組,用于保存二進(jìn)制數(shù)據(jù)
memcpy(bytes, m.data, iSize * sizeof(unsigned char)); //將Mat類型的數(shù)據(jù)賦給byte數(shù)組
//qDebug()<<QByteArray((char*)bytes, 100); //查看前100個字符
QByteArray sbuf = QByteArray::fromRawData((char *)bytes, iSize * sizeof(unsigned char)); //將unsigned char轉(zhuǎn)為QByteArray類型
QVariant var(sbuf); //將QByteArray類型轉(zhuǎn)成QVariant以便于插入到MYSql
QSqlQuery query; //下面為數(shù)據(jù)庫查詢的一種方式,要特別注意格式的要求
//創(chuàng)建數(shù)據(jù)表的時候,一定要注意數(shù)據(jù)的大小,比方說圖片blob為64k,mediumblob為16m
query.prepare("INSERT INTO Image_All (id, img_data) "
"VALUES (:id, :img_data)");
query.bindValue(":id", 77877); //我這里隨便設(shè)的
query.bindValue(":img_data",var);
if(query.exec())
{
qDebug()<<"圖片成功上傳至數(shù)據(jù)庫";
}
else{
qDebug()<<"圖片上傳數(shù)據(jù)庫失敗";
}
QString sql1=QString("select img_data from Image_All where id='33'"); //獲取數(shù)據(jù)庫中圖片數(shù)據(jù)
if(query.exec(sql1)) //執(zhí)行sql語句是否成功
{
while(query.next())//指向下一條
{
//根據(jù)下標(biāo)將返回結(jié)果進(jìn)行分割
QByteArray TEXT1=query.value(0).toByteArray(); //將查詢結(jié)果以QByteArray形式返回
unsigned char *data2;
data2 = reinterpret_cast<unsigned char*>(TEXT1.data()); //將QByteArray類型轉(zhuǎn)為unsigned char
Mat image=Mat(height,width,CV_8UC3,data2); //將unsigned char轉(zhuǎn)成Mat類型的數(shù)據(jù)
QPixmap temp = MatToPixmap(image);
ui->Process_image->setPixmap(temp);
}
}else
{
qDebug()<<"從數(shù)據(jù)庫獲取圖片失敗";
}
}
到此這篇關(guān)于QT中對Mat類的一些操作詳解的文章就介紹到這了,更多相關(guān)QT Mat操作內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++實(shí)現(xiàn)十大排序算法及排序算法常見問題
法是程序的靈魂,無論學(xué)習(xí)什么語言,做什么工程項(xiàng)目,都要考慮算法的效率實(shí)現(xiàn),下面這篇文章主要給大家介紹了關(guān)于C++實(shí)現(xiàn)十大排序算法及排序算法常見問題的相關(guān)資料,需要的朋友可以參考下2021-09-09
嵌入式項(xiàng)目使用C語言結(jié)構(gòu)體位段特性實(shí)現(xiàn)斷言宏校驗(yàn)數(shù)據(jù)范圍有效性的方法
今天小編就為大家分享一篇關(guān)于嵌入式項(xiàng)目使用C語言結(jié)構(gòu)體位段特性實(shí)現(xiàn)斷言宏校驗(yàn)數(shù)據(jù)范圍有效性的方法,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2018-12-12
C++編程使用findfirst和findnext查找及遍歷文件實(shí)現(xiàn)示例
這篇文章主要為大家介紹了C++編程如何使用findfirst和findnext查找及遍歷文件實(shí)現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助2021-10-10
Visual Studio調(diào)試C/C++教程指南
VisualStudio是微軟開發(fā)的一款集成開發(fā)環(huán)境軟件,本文主要介紹了Visual Studio調(diào)試C/C++教程指南,熟悉地掌握基于VS的C/C++調(diào)試技術(shù),可以大幅提升調(diào)試性能,感興趣的可以了解一下2024-06-06
C++ OpenCV實(shí)戰(zhàn)之標(biāo)記點(diǎn)檢測的實(shí)現(xiàn)
這篇文章主要介紹了如何利用C++ OpenCV實(shí)現(xiàn)關(guān)鍵點(diǎn)的檢測,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)OpenCV有一定幫助,感興趣的小伙伴可以了解一下2022-03-03

