opencvGrabcut图像分割前景与背景

lm.jpg

#include<opencv2/opencv.hpp>
#include<iostream>


int main(int argc, char** argv) {

    cv::Mat img = cv::imread("D:/bb/tu/lm.jpg");
    imshow("原图像", img);

    //绘制矩形
    cv::Mat imgRect;
    img.copyTo(imgRect);  //备份图像
    cv::Rect rect(49, 27, 205, 300);  //前景区域
    rectangle(imgRect, rect, cv::Scalar(255, 255, 255), 1);
    imshow("选择的矩形区域", imgRect);

    //进行分割
    cv::Mat bgdmod = cv::Mat::zeros(1, 65, CV_64FC1);
    cv::Mat fgdmod = cv::Mat::zeros(1, 65, CV_64FC1);
    cv::Mat mask = cv::Mat::zeros(img.size(), CV_8UC1);
    grabCut(img, mask, rect, bgdmod, fgdmod, 5, cv::GC_INIT_WITH_RECT);//分割前景和背景
    /*
    参数1:img输入的待分割图像,数据类型为CV_8U的三通道图像
    参数2:mask用于输入、输出的CV_8U单通道掩码图像,图像中像素值的取值范围以及含义在表8-4给出
    参数3:rect包含对象的ROI区域,该参数仅在mode == GC_INIT_WITH_RECT时使用
    参数4:bgdmod背景模型的临时数组
    参数5:fgdmod前景模型的临时数组
    参数6:算法需要进行的迭代次数
    参数7:mode:分割模式标志,该参数值可选择范围以及含义在表8-5给出
    */


    //将分割出的前景绘制回来
    cv::Mat result;
    for (int row = 0; row < mask.rows; row++) {
        for (int col = 0; col < mask.cols; col++) {
            int n = mask.at<uchar>(row, col);
            if (n == 1 || n == 3) {     //将明显是前景和可能是前景的区域都保留
                mask.at<uchar>(row, col) = 255;
            }
            else {   //将明显是背景和可能是背景的区域都删除
                mask.at<uchar>(row, col) = 0;
            }

        }
    }

    bitwise_and(img, img, result, mask);
    //mask为0的像素变为0,255的像素不变,结果放到result中
    imshow("分割结果", result);

    cv::waitKey(0);
    return 0;
}

表8-5 grabCut()函数中分割模式标志取值范围和含义

 

原文地址:https://www.cnblogs.com/liming19680104/p/15791211.html