由于最近都有很多课,所以就好久没有写博客,今天抽空写一篇,不能落下太多了,要坚持有时间就写写博客,为自己留下一些回忆,也可以到后期忘记的时候及时复习,不积跬步,无以至千里。不积小流,无以成江海。脚踏实地,打好基础,那才是王道,感觉说了一大堆废话,哈哈,现在正式进入主题,今天要讲的内容就是GrabCut图像分割啦,关于图像分割的方法五花八门,非常多,大家都可以从网上找到,包括GrabCut也是,本人也是在网上学习后在这里做一下记录,顺便分析一下OpenCV自带grabCut函数的使用,和例子的分析,没有什么创新点,方便以后查阅。
1、算法原理
原理在这几篇博客里已经讲得很仔细了,涉及到的内容也比较多,大家可以查阅一下,它是一个系列来的
④、图像分割之(四)OpenCV的GrabCut函数使用和源码解读
总的来说,GrabCut算法时Graph Cut算法的改进,主要有以下几点的改进
①、Graph Cut的目标和背景的模型是灰度直方图,Grab Cut取代为RGB三通道的混合高斯模型GMM;
②、Graph Cut的能量最小化(分割)是一次达到的,而Grab Cut取代为一个不断进行分割估计和模型参数学习的交互迭代过程;
③、Grab Cut允许不完全的标注,Graph Cut需要用户指定目标和背景的一些种子点,但是Grab Cut只需要提供背景区域的像素集,最后如果需要得到更精确的分割,可以在初次分割的结果上加上一些确定的种子点,再运行算法。
2、代码实现
GCApplication.h
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
using namespace std;
using namespace cv;
const Scalar RED = Scalar(0,0,255);
const Scalar PINK = Scalar(230,130,255);
const Scalar BLUE = Scalar(255,0,0);
const Scalar LIGHTBLUE = Scalar(255,255,160);
const Scalar GREEN = Scalar(0,255,0);
const int BGD_KEY = CV_EVENT_FLAG_CTRLKEY;//当CTRL被按下时,flags返回的值
const int FGD_KEY = CV_EVENT_FLAG_SHIFTKEY;//当SHIFT被按下时,flags返回的值
static void getBinMask( const Mat& comMask, Mat& binMask )
{
if( comMask.empty() || comMask.type()!=CV_8UC1 )
CV_Error( CV_StsBadArg, "comMask is empty or has incorrect type (not CV_8UC1)" );
if( binMask.empty() || binMask.rows!=comMask.rows || binMask.cols!=comMask.cols )
binMask.create( comMask.size(), CV_8UC1 );
binMask = comMask & 1;
}
class GCApplication
{
public:
enum{ NOT_SET = 0, IN_PROCESS = 1, SET = 2 };
static const int radius = 2;
static const int thickness = -1;
void reset();
void setImageAndWinName( const Mat& _image, const string& _winName );
void showImage() const;
void mouseClick( int event, int x, int y, int flags, void* pa