OpenCV中怎么使用GrabCut实现抠图功能
这篇文章主要讲解了“OpenCV中怎么使用GrabCut实现抠图功能”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“OpenCV中怎么使用GrabCut实现抠图功能”吧!
1、概述
grabCut( InputArray img, InputOutputArray mask, Rect rect, InputOutputArray bgdModel, InputOutputArray fgdModel, int iterCount, int mode = GC_EVAL );
img --> 输入的三通道图像;
mask --> 输入的单通道图像,初始化方式为GC_INIT_WITH_RECT表示ROI区域可以被初始化为:
GC_BGD --> 定义为明显的背景像素 0
GC_FGD --> 定义为明显的前景像素 1
GC_PR_BGD --> 定义为可能的背景像素 2
GC_PR_FGD --> 定义为可能的前景像素 3
rect --> 表示roi区域;
bgdModel --> 表示临时背景模型数组;
fgdModel --> 表示临时前景模型数组;
iterCount --> 表示图割算法迭代次数, 次数越多,效果越好;
mode --> 当使用用户提供的roi时候使用GC_INIT_WITH_RECT
实现算法的步骤:
创建一个遮罩,并初始化为背景GC_BGD
用户选定一个ROI区域初始化为前景GC_FGD
调用grabCut函数实现算法
输入mask即为目标抠图
2、代码示例
(这个例子不完善,图像的颜色输出有问题,先记录一下,后面改正。但是不影响整个算法的流程及效果,仅仅是RGB和BGR像素通道的问题)
CrabCut_Matting::CrabCut_Matting(QWidget *parent) : MyGraphicsView{parent}{ this->setWindowTitle("crabCut抠图"); this->setMouseTracking(true);//设置鼠标事件可用 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){ class="lazy" data-src = imread(filePath); if(class="lazy" data-src.empty()){ qDebug()<<"输入图像为空"; return; } //创建一个背景遮罩 mMask = Mat::zeros(class="lazy" data-src.size(),CV_8UC1); mMask.setTo(Scalar::all(GC_BGD)); convert2Sence(class="lazy" data-src);}void CrabCut_Matting::mouseMoveEvent(QMouseEvent *event){ // if(event->button()==Qt::LeftButton){//鼠标左键 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){//鼠标左键 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){//鼠标左键 if (rect.width > 1 && rect.height > 1) { setROIMask(); qDebug()<<"mouseReleaseEvent:"<<rect.width<<"|"<<rect.height; //执行grabcut的代码 runGrabCut(); numRun++; showImage(); } }}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, class="lazy" data-src.cols - rect.x); rect.height = min(rect.height, class="lazy" data-src.rows - rect.y); mMask(rect).setTo(Scalar(GC_PR_FGD));//将选中的区域设置为} void CrabCut_Matting::showImage(){ Mat result, binMask; binMask.create(mMask.size(), CV_8UC1); binMask = mMask & 1; if (init) { class="lazy" data-src.copyTo(result, binMask); } else { class="lazy" data-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(class="lazy" data-src, mMask, rect, bgModel, fgModel, 1); } { grabCut(class="lazy" data-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);}
感谢各位的阅读,以上就是“OpenCV中怎么使用GrabCut实现抠图功能”的内容了,经过本文的学习后,相信大家对OpenCV中怎么使用GrabCut实现抠图功能这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341