OpenCV如何使用GrabCut实现抠图功能

其他教程   发布日期:2023年06月22日   浏览次数:446

这篇文章主要介绍“OpenCV如何使用GrabCut实现抠图功能”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“OpenCV如何使用GrabCut实现抠图功能”文章能帮助大家解决问题。

1、概述

案例:使用OpenCV的GrapCut实现有用户交互的抠图

  1. grabCut( InputArray img, InputOutputArray mask, Rect rect,
  2. InputOutputArray bgdModel, InputOutputArray fgdModel,
  3. 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

实现算法的步骤:

1.创建一个遮罩,并初始化为背景GC_BGD

2.用户选定一个ROI区域初始化为前景GC_FGD

3.调用grabCut函数实现算法

4.输入mask即为目标抠图

2、代码示例

(这个例子不完善,图像的颜色输出有问题,先记录一下,后面改正。但是不影响整个算法的流程及效果,仅仅是RGB和BGR像素通道的问题)

  1. CrabCut_Matting::CrabCut_Matting(QWidget *parent)
  2. : MyGraphicsView{parent}
  3. {
  4. this->setWindowTitle("crabCut抠图");
  5. this->setMouseTracking(true);//设置鼠标事件可用
  6. init = false;
  7. numRun = false;
  8. }
  9. void CrabCut_Matting::dropEvent(QDropEvent*event){
  10. QString filePath = event->mimeData()->urls().at(0).toLocalFile();
  11. showCrabCutMatting(filePath.toStdString().c_str());
  12. }
  13. void CrabCut_Matting::showCrabCutMatting(const char* filePath){
  14. src = imread(filePath);
  15. if(src.empty()){
  16. qDebug()<<"输入图像为空";
  17. return;
  18. }
  19. //创建一个背景遮罩
  20. mMask = Mat::zeros(src.size(),CV_8UC1);
  21. mMask.setTo(Scalar::all(GC_BGD));
  22. convert2Sence(src);
  23. }
  24. void CrabCut_Matting::mouseMoveEvent(QMouseEvent *event){
  25. // if(event->button()==Qt::LeftButton){//鼠标左键
  26. rect = Rect(Point(rect.x, rect.y), Point(event->pos().x(), event->pos().y()));
  27. qDebug()<<"mouseMoveEvent:"<<rect.width<<"|"<<rect.height;
  28. showImage();
  29. // }
  30. }
  31. void CrabCut_Matting::mousePressEvent(QMouseEvent *event){
  32. grabMouse();
  33. if(event->button()==Qt::LeftButton){//鼠标左键
  34. rect.x = event->pos().x();
  35. rect.y = event->pos().y();
  36. rect.width = 1;
  37. rect.height = 1;
  38. init = false;
  39. numRun = 0;
  40. qDebug()<<"mousePressEvent:"<<event->pos().x()<<"|"<<event->pos().y();
  41. }
  42. }
  43. void CrabCut_Matting::mouseReleaseEvent(QMouseEvent *event){
  44. releaseMouse();
  45. if(event->button()==Qt::LeftButton){//鼠标左键
  46. if (rect.width > 1 && rect.height > 1) {
  47. setROIMask();
  48. qDebug()<<"mouseReleaseEvent:"<<rect.width<<"|"<<rect.height;
  49. //执行grabcut的代码
  50. runGrabCut();
  51. numRun++;
  52. showImage();
  53. }
  54. }
  55. }
  56. /**
  57. * 将选中的区域设置为前景
  58. * @brief CrabCut_Matting::setROIMask
  59. */
  60. void CrabCut_Matting::setROIMask(){
  61. // GC_FGD = 1
  62. // GC_BGD =0;
  63. // GC_PR_FGD = 3
  64. // GC_PR_BGD = 2
  65. mMask.setTo(GC_BGD);
  66. rect.x = max(0, rect.x);
  67. rect.y = max(0, rect.y);
  68. rect.width = min(rect.width, src.cols - rect.x);
  69. rect.height = min(rect.height, src.rows - rect.y);
  70. mMask(rect).setTo(Scalar(GC_PR_FGD));//将选中的区域设置为
  71. }
  72. void CrabCut_Matting::showImage(){
  73. Mat result, binMask;
  74. binMask.create(mMask.size(), CV_8UC1);
  75. binMask = mMask & 1;
  76. if (init) {
  77. src.copyTo(result, binMask);
  78. } else {
  79. src.copyTo(result);
  80. }
  81. rectangle(result, rect, Scalar(0, 0, 255), 2, 8);
  82. convert2Sence(result);
  83. }
  84. void CrabCut_Matting::runGrabCut(){
  85. if (rect.width < 2 || rect.height < 2) {
  86. return;
  87. }
  88. if (init) {
  89. grabCut(src, mMask, rect, bgModel, fgModel, 1);
  90. } {
  91. grabCut(src, mMask, rect, bgModel, fgModel, 1, GC_INIT_WITH_RECT);
  92. init = true;
  93. }
  94. }
  95. void CrabCut_Matting::convert2Sence(Mat target){
  96. scene.clear();
  97. QImage image = ImageUtils::matToQImage(target);
  98. QPixmap pixmap = QPixmap::fromImage(image);
  99. QGraphicsPixmapItem *item = new QGraphicsPixmapItem(pixmap.scaled(this->size(),Qt::KeepAspectRatio,Qt::SmoothTransformation));
  100. scene.addItem(item);
  101. }

以上就是OpenCV如何使用GrabCut实现抠图功能的详细内容,更多关于OpenCV如何使用GrabCut实现抠图功能的资料请关注九品源码其它相关文章!