图像分割:Grabcut算法小程序

OpenCV中的GrabCut

GrabCut是流行的图像分割算法之一,通过标记前景像素、相似色彩聚类、边界像素惩罚和迭代,寻找最优解。
本文用OpenCV实现的GrabCut算法,做了个小程序。至于该算法的详解可自行百度学习吧。
OpenCV中GrabCut算法函数原型:

void grabCut(InputArray image, InputOutputArray mask, Rect rect, InputOutputArray bgdModel, InputOutputArray fgdModel, int iterCount, int mode)

参数解释:
image:输入图像
mask:分割结果
rect:前景区域
bgdModel、fgdModel:(算法内部调用参数)
iterCount:迭代次数
mode:运行参数

算法调用流程:
(1)读取一张图片,用矩形标记出前景部分。
(2)调用grabCut(),获得分割结果。
(3)由于grabCut函数返回的分割结果,包含四种值:确定属于背景像素、可能属于背景像素、确定属于前景像素、可能属于前景像素。所以,根据需要,从返回结果中提取需要值。
(4)根据需要从结果提取需要的值(矩阵)后,通过掩码,对图片进行分割。

注意:程序有些耗时,选取完区域后。程序可能没反应(计算量较大),耐心等待一会即可。

具体程序:

GradCut.h

#include<opencv2\core\core.hpp>
#include<opencv2\highgui\highgui.hpp>
#include<opencv2\imgproc\imgproc.hpp>

class GrabCut
{
private:
    //保存结果
	cv::Mat result;
	cv::Mat bgmodle, fgmodel;
public:
    //调用grabCut函数
	void getGrabCut(const cv::Mat &image,cv::Rect &rect)
	{
	    //迭代次数设置为10,可以根据分割情况适量增减
		cv::grabCut(image, result, rect, bgmodle, fgmodel, 10, cv::GC_INIT_WITH_RECT);
	}
	//显示前景
	void showFg(const cv::Mat &image)
	{
		cv::compare(result, cv::GC_PR_FGD, result, cv::CMP_EQ);
		cv::Mat foreground(image.size(), CV_8UC3, cv::Scalar(255, 255, 255));
		//掩码,去掉非前景的像素区域
		image.copyTo(foreground, result);
		cv::imshow("result", result);
		cv::imshow("结果", foreground);
		cv::waitKey(0);
	}
};

源.cpp

#include"GradCut.h"
//声明鼠标回调函数,通过鼠标选取矩形区域
void mouse_callback(int event, int x, int y, int flags, void* param);
cv::Point p1;
cv::Point p2;
bool t=flase;
bool stop = false;
int main()
{
    //待分割的图片
	cv::Mat image = cv::imread("D:/images/240486-1211201T03719.jpg");
	cv::imshow("图片", image);
	//设置鼠标回调函数
	cvSetMouseCallback("图片", mouse_callback);
	while (!stop)
	{
		if(t)
		{
			cv::rectangle(image, cv::Rect(p1, p2), cv::Scalar(255, 0, 0));
			cv::imshow("图片", image);
			t = false;
			stop = true;
		}	
		if (cv::waitKey(100) == 27)
			break;
	}
	cv::Rect rect(p1, p2);
	//类对象
	GrabCut gbc;
	cv::Mat image1 = cv::imread("D:/images/240486-1211201T03719.jpg");
	//调用gradcut
	gbc.getGrabCut(image1, rect);
	//显示结果
	gbc.showFg(image1);
	return 0;
}
//鼠标回调函数定义
void mouse_callback(int event, int x, int y, int flags, void* param)
{
	switch (event)
	{
		case CV_EVENT_LBUTTONDOWN:
		{
			p1 = cv::Point(x, y);
			break;
		}
		case CV_EVENT_LBUTTONUP:
		{
			p2 = cv::Point(x, y);
			t = true;
			break;
		}
	}
}

结果

这里写图片描述
这里写图片描述
这里写图片描述

  • 0
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林多

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值