QT中對(duì)Mat類的一些操作詳解
一、類型轉(zhuǎn)換
opencv在QT中的應(yīng)用通常會(huì)涉及到這三者的轉(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)的,那么將其返回為一個(gè)空對(duì)象
{
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ù)庫中,這個(gè)還是要好看項(xiàng)目需求,個(gè)人而言,我這個(gè)要更復(fù)雜一點(diǎn)。
演示效果如下:
1??:基礎(chǔ)界面

2??:磨皮處理

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

4??:核心代碼
注意: 創(chuàng)建數(shù)據(jù)表的時(shí)候,字段的類型,一定要滿足數(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ù)庫。(此時(shí)有小伙伴可能就要問了,為什么不直接從Image類型轉(zhuǎn)byte數(shù)組呢?當(dāng)然可以,不過我們饒了個(gè)彎子也是想讓大家學(xué)會(huì)如何將Mat類型轉(zhuǎn)成byte數(shù)組)
上傳數(shù)據(jù)庫,用戶名+圖片數(shù)據(jù)(這個(gè)看自身的需求)
準(zhǔn)備數(shù)據(jù)庫查詢語句query,用法如下圖所示

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

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)建一個(gè)字節(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個(gè)字符
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í)候,一定要注意數(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中對(duì)Mat類的一些操作詳解的文章就介紹到這了,更多相關(guān)QT Mat操作內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++實(shí)現(xiàn)賓館房間管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)賓館房間管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05
C++中Operator類型強(qiáng)制轉(zhuǎn)換成員函數(shù)解析
轉(zhuǎn)換函數(shù)定義了由<類型說明符1>到<類型說明符2>之間的映射關(guān)系??梢?,轉(zhuǎn)換函數(shù)是用來將一種類型的數(shù)據(jù)轉(zhuǎn)換成為另一種類型2013-09-09
大數(shù)據(jù)情況下桶排序算法的運(yùn)用與C++代碼實(shí)現(xiàn)示例
在排序元素很多的情況下,其實(shí)桶排序的性能并不是太高,這里我們配合單鏈表的直接插入排序,來看下一大數(shù)據(jù)情況下桶排序算法的運(yùn)用與C++代碼實(shí)現(xiàn)示例:2016-07-07
Opencv檢測(cè)多個(gè)圓形(霍夫圓檢測(cè),輪廓面積篩選)
本文主要介紹了Opencv檢測(cè)多個(gè)圓形(霍夫圓檢測(cè),輪廓面積篩選),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08
C++算法學(xué)習(xí)之分支限界法的應(yīng)用
分支限界法常以廣度優(yōu)先或以最小耗費(fèi)(最大效益)優(yōu)先的方式搜索問題的解空間樹。本文將詳細(xì)講解分支限界法的應(yīng)用,需要的可以參考一下2022-05-05

