图像分割:Grabcut算法小程序
2016-04-25 17:05
501 查看
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; } } }
结果
相关文章推荐
- Android App仿微信界面切换时Tab图标变色效果的制作方法
- 微信中链接 访问公众号
- 微信模板消息
- 微信展示
- Android接入微信开发注意事项
- 微信网页调用腾讯视频去广告,视频预览截图去腾讯logo
- Java小程序之字符串倒置
- 微信企业号的JAVA开发平台
- 微信上传图片
- JAVA微信扫码支付模式二功能实现以及回调
- C#开发微信门户及应用(33)--微信现金红包的封装及使用
- Android应用加入微信分享
- JEEWX微信企业号管家,开源免费,1.0版本发布
- WWeChat仿微信应用源码带IM服务端源码完整版
- android实现微信网页浏览、QQ下拉效果SlidingLayout
- dcloud打包ecshop程序的支付宝和微信接口开发
- 微信公众平台的接口url
- 微信开发
- 微信文章排版
- 微信文章如何获得上万次转载?