- 操作系统:ubuntu22.04
- OpenCV版本:OpenCV4.9
- IDE:Visual Studio Code
- 编程语言:C++11
算法描述
运行 GrabCut 算法。
该函数实现了 GrabCut 图像分割算法
OpenCV 中的 grabCut() 函数是一种用于图像分割的技术,它可以帮助用户从图像中分割出感兴趣的区域(ROI)。grabCut() 使用了一种基于图割(graph cut)的方法来进行分割,可以有效地将前景和背景分离。
函数原型
void cv::grabCut
(InputArray img,InputOutputArray mask,Rect rect,InputOutputArray bgdModel,InputOutputArray fgdModel,int iterCount,int mode = GC_EVAL
)
参数
- 参数img 输入的8位3通道图像。
- 参数mask 输入/输出的8位单通道掩码。当模式被设置为GC_INIT_WITH_RECT时,此掩码由函数初始化。其元素可以是GrabCutClasses中的某一种。
- 参数rect 包含分割对象的ROI(感兴趣区域)。ROI之外的像素被标记为“明显的背景”。此参数仅在mode==GC_INIT_WITH_RECT时使用。
- 参数bgdModel 用于背景模型的临时数组。在处理同一张图像期间请勿修改它。
- 参数fgdModel 用于前景模型的临时数组。在处理同一张图像期间请勿修改它。
- 参数iterCount 算法在返回结果前应该执行的迭代次数。注意,结果可以通过mode设置为GC_INIT_WITH_MASK或mode设置为GC_EVAL的进一步调用来优化。
- 参数mode 操作模式,可以是GrabCutModes中的任意一种。
代码示例
#include <iostream>
#include <opencv2/opencv.hpp>int main()
{// 读取图像cv::Mat img = cv::imread( "/media/dingxin/data/study/OpenCV/sources/images/qiu.jpg" );if ( img.empty() ){std::cout << "Could not open or find the image!" << std::endl;return -1;}// 初始化掩码cv::Mat mask( img.size(), CV_8UC1, cv::Scalar::all( cv::GC_PR_BGD ) );// 选择一个矩形区域作为前景cv::Rect rect( 200, 200, 400, 400 ); // 以左上角坐标 (200, 200) 和宽度高度 (400, 400) 为例// 初始化背景和前景模型cv::Mat bgdModel, fgdModel;// 应用 grabCutcv::grabCut( img, mask, rect, bgdModel, fgdModel, 5, cv::GC_INIT_WITH_RECT );// 将掩码转换为可视化的结果cv::Mat segmented;segmented.create( img.size(), img.type() ); // 确保 segmented 与 img 具有相同的尺寸和类型// 确保 mask 和 segmented 的尺寸一致assert( mask.size() == img.size() );for ( int i = 0; i < mask.rows; ++i ){for ( int j = 0; j < mask.cols; ++j ){// 确保 i 和 j 不越界if ( i >= 0 && i < segmented.rows && j >= 0 && j < segmented.cols ){if ( mask.at< uchar >( i, j ) == cv::GC_PR_BGD || mask.at< uchar >( i, j ) == cv::GC_BGD ){segmented.at< cv::Vec3b >( i, j ) = cv::Vec3b( 0, 0, 0 ); // 黑色背景}else if ( mask.at< uchar >( i, j ) == cv::GC_FGD || mask.at< uchar >( i, j ) == cv::GC_PR_FGD ){segmented.at< cv::Vec3b >( i, j ) = img.at< cv::Vec3b >( i, j ); // 原始图像的前景}}}}// 显示结果cv::imshow( "Original Image", img );cv::imshow( "Segmented Image", segmented );cv::waitKey( 0 );return 0;
}