OpenCV使用GrabCut實(shí)現(xiàn)摳圖功能
1、概述
案例:使用OpenCV的GrapCut實(shí)現(xiàn)有用戶(hù)交互的摳圖
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)使用用戶(hù)提供的roi時(shí)候使用GC_INIT_WITH_RECT
實(shí)現(xiàn)算法的步驟:
1.創(chuàng)建一個(gè)遮罩,并初始化為背景GC_BGD
2.用戶(hù)選定一個(gè)ROI區(qū)域初始化為前景GC_FGD
3.調(diào)用grabCut函數(shù)實(shí)現(xiàn)算法
4.輸入mask即為目標(biāo)摳圖
2、代碼示例
(這個(gè)例子不完善,圖像的顏色輸出有問(wèn)題,先記錄一下,后面改正。但是不影響整個(gè)算法的流程及效果,僅僅是RGB和BGR像素通道的問(wèn)題)
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語(yǔ)言代碼轉(zhuǎn)換為應(yīng)用程序(也就是編譯)
有時(shí)候我們將讓我們的c語(yǔ)言代碼保存為一個(gè)exe方便,方便使用,實(shí)際就是我們俗說(shuō)的編譯2013-07-07
C語(yǔ)言如何寫(xiě)類(lèi)實(shí)現(xiàn)教程示例
這篇文章主要為大家介紹了C語(yǔ)言如何寫(xiě)類(lèi)的實(shí)現(xiàn)教程示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04
詳解C語(yǔ)言中index()函數(shù)和rindex()函數(shù)的用法
這篇文章主要介紹了C語(yǔ)言中index()函數(shù)和rndex()函數(shù)的用法,是C語(yǔ)言入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),要的朋友可以參考下2015-08-08
C++中的explicit關(guān)鍵字實(shí)例淺析
在C++程序中很少有人去使用explicit關(guān)鍵字,不可否認(rèn),在平時(shí)的實(shí)踐中確實(shí)很少能用的上,再說(shuō)C++的功能強(qiáng)大,往往一個(gè)問(wèn)題可以利用好幾種C++特性去解決。接下來(lái)給大家介紹 C++中的explicit關(guān)鍵字,需要的朋友可以參考下2017-03-03

