图像分割:Grabcut算法小程序

来源:互联网 发布:奔驰g63网络图片 编辑:程序博客网 时间:2024/05/18 17:00

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 0