OpenCV使用GrabCut實(shí)現(xiàn)摳圖功能
1、概述
案例:使用OpenCV的GrapCut實(shí)現(xiàn)有用戶交互的摳圖
grabCut( InputArray img, InputOutputArray mask, Rect rect, InputOutputArray bgdModel, InputOutputArray fgdModel, int iterCount, int mode = GC_EVAL );
- img --> 輸入的三通道圖像;
- mask --> 輸入的單通道圖像,初始化方式為GC_INIT_WITH_RECT表示ROI區(qū)域可以被初始化為:
- GC_BGD --> 定義為明顯的背景像素 0
- GC_FGD --> 定義為明顯的前景像素 1
- GC_PR_BGD --> 定義為可能的背景像素 2
- GC_PR_FGD --> 定義為可能的前景像素 3
- rect --> 表示roi區(qū)域;
- bgdModel --> 表示臨時(shí)背景模型數(shù)組;
- fgdModel --> 表示臨時(shí)前景模型數(shù)組;
- iterCount --> 表示圖割算法迭代次數(shù), 次數(shù)越多,效果越好;
- mode --> 當(dāng)使用用戶提供的roi時(shí)候使用GC_INIT_WITH_RECT
實(shí)現(xiàn)算法的步驟:
1.創(chuàng)建一個(gè)遮罩,并初始化為背景GC_BGD
2.用戶選定一個(gè)ROI區(qū)域初始化為前景GC_FGD
3.調(diào)用grabCut函數(shù)實(shí)現(xiàn)算法
4.輸入mask即為目標(biāo)摳圖
2、代碼示例
(這個(gè)例子不完善,圖像的顏色輸出有問題,先記錄一下,后面改正。但是不影響整個(gè)算法的流程及效果,僅僅是RGB和BGR像素通道的問題)
CrabCut_Matting::CrabCut_Matting(QWidget *parent) : MyGraphicsView{parent} { this->setWindowTitle("crabCut摳圖"); this->setMouseTracking(true);//設(shè)置鼠標(biāo)事件可用 init = false; numRun = false; } void CrabCut_Matting::dropEvent(QDropEvent*event){ QString filePath = event->mimeData()->urls().at(0).toLocalFile(); showCrabCutMatting(filePath.toStdString().c_str()); } void CrabCut_Matting::showCrabCutMatting(const char* filePath){ src = imread(filePath); if(src.empty()){ qDebug()<<"輸入圖像為空"; return; } //創(chuàng)建一個(gè)背景遮罩 mMask = Mat::zeros(src.size(),CV_8UC1); mMask.setTo(Scalar::all(GC_BGD)); convert2Sence(src); } void CrabCut_Matting::mouseMoveEvent(QMouseEvent *event){ // if(event->button()==Qt::LeftButton){//鼠標(biāo)左鍵 rect = Rect(Point(rect.x, rect.y), Point(event->pos().x(), event->pos().y())); qDebug()<<"mouseMoveEvent:"<<rect.width<<"|"<<rect.height; showImage(); // } } void CrabCut_Matting::mousePressEvent(QMouseEvent *event){ grabMouse(); if(event->button()==Qt::LeftButton){//鼠標(biāo)左鍵 rect.x = event->pos().x(); rect.y = event->pos().y(); rect.width = 1; rect.height = 1; init = false; numRun = 0; qDebug()<<"mousePressEvent:"<<event->pos().x()<<"|"<<event->pos().y(); } } void CrabCut_Matting::mouseReleaseEvent(QMouseEvent *event){ releaseMouse(); if(event->button()==Qt::LeftButton){//鼠標(biāo)左鍵 if (rect.width > 1 && rect.height > 1) { setROIMask(); qDebug()<<"mouseReleaseEvent:"<<rect.width<<"|"<<rect.height; //執(zhí)行g(shù)rabcut的代碼 runGrabCut(); numRun++; showImage(); } } } /** * 將選中的區(qū)域設(shè)置為前景 * @brief CrabCut_Matting::setROIMask */ void CrabCut_Matting::setROIMask(){ // GC_FGD = 1 // GC_BGD =0; // GC_PR_FGD = 3 // GC_PR_BGD = 2 mMask.setTo(GC_BGD); rect.x = max(0, rect.x); rect.y = max(0, rect.y); rect.width = min(rect.width, src.cols - rect.x); rect.height = min(rect.height, src.rows - rect.y); mMask(rect).setTo(Scalar(GC_PR_FGD));//將選中的區(qū)域設(shè)置為 } void CrabCut_Matting::showImage(){ Mat result, binMask; binMask.create(mMask.size(), CV_8UC1); binMask = mMask & 1; if (init) { src.copyTo(result, binMask); } else { src.copyTo(result); } rectangle(result, rect, Scalar(0, 0, 255), 2, 8); convert2Sence(result); } void CrabCut_Matting::runGrabCut(){ if (rect.width < 2 || rect.height < 2) { return; } if (init) { grabCut(src, mMask, rect, bgModel, fgModel, 1); } { grabCut(src, mMask, rect, bgModel, fgModel, 1, GC_INIT_WITH_RECT); init = true; } } void CrabCut_Matting::convert2Sence(Mat target){ scene.clear(); QImage image = ImageUtils::matToQImage(target); QPixmap pixmap = QPixmap::fromImage(image); QGraphicsPixmapItem *item = new QGraphicsPixmapItem(pixmap.scaled(this->size(),Qt::KeepAspectRatio,Qt::SmoothTransformation)); scene.addItem(item); }
3、示例圖片
以上就是OpenCV使用GrabCut實(shí)現(xiàn)摳圖功能的詳細(xì)內(nèi)容,更多關(guān)于OpenCV GrabCut摳圖的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C++實(shí)現(xiàn)四則運(yùn)算器(帶括號(hào))
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)四則運(yùn)算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-11-11Qt出現(xiàn)假死凍結(jié)現(xiàn)象的原因及解決方法
應(yīng)用程序出現(xiàn)假死或凍結(jié)現(xiàn)象通常是由于一些常見問題所導(dǎo)致的,本文主要介紹了Qt出現(xiàn)假死凍結(jié)現(xiàn)象的原因及解決方法,具有一定的參考價(jià)值,感興趣的可以了解一下2023-10-10c++ 寫注冊(cè)表方式讓程序開機(jī)自啟動(dòng)
這篇文章主要介紹了c++ 寫注冊(cè)表方式讓程序開機(jī)自啟動(dòng),需要的朋友可以參考下2017-09-09opencv實(shí)現(xiàn)機(jī)器視覺檢測和計(jì)數(shù)的方法
在機(jī)器視覺中,有時(shí)需要對(duì)產(chǎn)品進(jìn)行檢測和計(jì)數(shù)。其難點(diǎn)無非是對(duì)于產(chǎn)品的圖像分割。本文就來介紹一下機(jī)器視覺檢測和計(jì)數(shù)的實(shí)現(xiàn),感興趣的可以參考一下2021-05-05