1. GrabCut算法实现分割
GrabCut算法比较复杂,计算量也很大,但通常很精确。
#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>
int main()
{
cv::Mat_<cv::Vec3b> img = cv::imread("castle.jpg");
cv::resize(img, img, cv::Size(img.cols/3,img.rows/3));
cv::Mat result; // 分割结果,有四种可能的值
cv::Mat bgModel, fgModel; // 模型(算法内部使用)
/* 定义矩形,矩形外部的像素是背景 */
cv::Rect rectangle = cv::Rect(780 / 3, 410 / 3, 400 / 3, 400 / 3);
/* GrabCut分割算法 */
cv::grabCut(img, // 输入图像
result, // 分割结果
rectangle, // 指定的前景区域
bgModel, fgModel, // 存放算法构建的模型
5, // 迭代次数
cv::GC_INIT_WITH_RECT); // 使用矩形
/* 获取标记为“可能是前景”的像素 */
cv::compare(result, cv::GC_PR_FGD, result, cv::CMP_EQ);
/* 前景图像 */
cv::Mat foreground(img.size(), CV_8UC3, cv::Scalar(255, 255, 255));
/* 仅拷贝算法认为可能是前景的区域 */
img.copyTo(foreground, result);
cv::imshow("foreground", foreground);
cv::imshow("result", result);
cv::imshow("img", img);
cv::waitKey(0);
}
原图是图1(img),分割后二值图是图2(result),分割后前景图是图3(foreground)。
![ellipse](https://i-blog.csdnimg.cn/blog_migrate/b97df33f47e3f9f78988f5938430d8bc.jpeg)
图1 原图
![ellipse](https://i-blog.csdnimg.cn/blog_migrate/f48b528a0b15756f4569b87da0d42228.jpeg)
图2 分割前景二值图
![ellipse](https://i-blog.csdnimg.cn/blog_migrate/08ffe86869aad7c4ea5356a6559da205.jpeg)
图3 分割前景图