OpenCV 学习笔记(Watershed)

Watershed,中文一般翻译为分水岭算法。分水岭算法是一种图像区域分割算法,它把位置接近,灰度值也接近的像素点连接起来形成一个封闭的区域。关于分水岭算法的具体原理可以参考下面的网址:

wiki 百科 Watershed

这里只介绍在 OpenCV中的如何使用 Watershed 算法。Opencv 中 watershed函数原型如下:

void watershed( InputArray image, InputOutputArray markers );

image 是 3 通道彩色(CV_8UC3)图像,markers 是单通道(CV_32S) 图像。为什么 markers 要求是CV_32S 呢,我觉得应该是图像的区域数可能会很大,CV_8U 不够用,索性就搞个 CV_32S,这个类型是绝对够用的。

这里重点说说markers 的作用,传统的 watershed 算法是不需要markers 的。但是经常会把图像分割成太多的小区域。markers 的作用就是我们预先把一些区域标注好,这些标注了的区域称之为种子点。watershed 算法会把这些标记的区域慢慢膨胀填充整个图像。

如何预先的标记这些区域呢?这就是个关键的问题了。我们可以交互式的人为的标记。也可以通过一些其他的算法来确定一部分区域。下面的例子就会讲解如何用 connectedComponents 函数来自动的标记区域。

首先我们来看看我们要标注的图像是什么样的:
这幅图像中有很多个小球。我们就是要标记出这些小球来。首先这幅图像中有些噪声,我们先进行滤波操作。这个噪声类似于椒盐噪声,所以用 medianBlur 效果会比较好。之后我们再用 GaussianBlur 进一步平滑图像。之后就可以做二值化了。做完二值化后再把图像腐蚀一下以确保小球之间不会相连。

cv::Mat image = cv::imread("zeiss.jpg");
cv::cvtColor(image(cv::Rect(0, 0, 1024, 700)), image, CV_BGRA2BGR);
cv::Mat imageBlur;
cv::medianBlur(image, imageBlur, 7);
cv::GaussianBlur(imageBlur, imageBlur, cv::Size(5, 5), 0);
cv::Mat grayMat, grayMatBW;
cv::cvtColor(imageBlur, grayMat, CV_BGR2GRAY);
cv::imshow("zeiss",  grayMat);
cv::threshold( grayMat, grayMatBW, 0, 255 ,cv::THRESH_OTSU );
cv::Mat foreground;
cv::erode(grayMatBW, foreground, cv::Mat(), cv::Point(-1, -1), 4);
cv::imshow("foreground",  foreground);


下面把每个小球都标记成不同的数字。这个可以使用 connectedComponents 函数。标记完小球后还要标记背景区域。方法类似。最后把小球和背景区域叠加到一张图中。

cv::Mat foreground;
cv::erode(grayMatBW, foreground, cv::Mat(), cv::Point(-1, -1), 4);
cv::imshow("foreground",  foreground);
cv::connectedComponents(foreground, foreground, 4, CV_32S);
foreground.convertTo(foreground, CV_8U);cv::Mat background;
cv::dilate(grayMatBW, background, cv::Mat(), cv::Point(-1, -1), 4);
cv::threshold(background, background, 1, 128, cv::THRESH_BINARY_INV);
bg.convertTo(bg, CV_32S);cv::Mat marker = background + foreground;
marker.convertTo(marker, CV_32S);

至此,我们就准备好marker 了, 下面调用 watershed 函数。

cv::watershed(image, marker);
cv::Mat segment;
marker.convertTo(segment, CV_8U);
std::vector<cv::Vec3b> colormap = buildRandomColormap(255);
cv::Mat outcolor = imageFromColormap(segment, colormap);
cv::imshow("out", outcolor);

segment 就是我们分隔出的各个区域,取值为 128 的是背景区域。其余的各个小球。为了更好的显示,我们还写了两个辅助函数。

std::vector<cv::Vec3b> buildRandomColormap(int N)
{
cv::RNG rng;std::vector<cv::Vec3b> colormap;for(int i = 0; i < N; i++){colormap.push_back( cv::Vec3b(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)) );}return colormap;
}cv::Mat imageFromColormap(const cv::Mat &grayImage, const std::vector<cv::Vec3b> &colormap)
{cv::Mat out(grayImage.size(), CV_8UC3);out = cv::Scalar(0, 0, 0);int N = colormap.size();//cv::Mat_<cv::Vec3b> img(out);for(int row = 0; row < grayImage.rows; row ++){cv::Vec3b * pDest = out.ptr<cv::Vec3b>(row);const uchar *pSrc = grayImage.ptr<const uchar>(row);for(int col = 0; col < grayImage.cols; col ++){if(pSrc[col] >= N){pDest[col] = cv::Vec3b(pSrc[col], pSrc[col], pSrc[col]);}else{pDest[col] = colormap[pSrc[col]];}}}return out;
}

最终的输出效果如下图。可以看到各个区域都填充了不同的颜色。但是小球的边界找的不是特别的理想。这也是 watershed 算法的缺点吧。

OpenCV 学习笔记(Watershed)相关推荐

  1. opencv学习笔记(二):基于肤色的人手检测

    opencv学习笔记(二):基于肤色的人手检测 原文:http://blog.csdn.net/wzmsltw/article/details/50849810 先写了人手的检测程序,下一步基于检测程 ...

  2. OpenCV学习笔记(十六)——CamShift研究 OpenCV学习笔记(十七)——运动分析和物体跟踪Video OpenCV学习笔记(十八)——图像的各种变换(cvtColor*+)imgproc

    OpenCV学习笔记(十六)--CamShift研究 CamShitf算法,即Continuously Apative Mean-Shift算法,基本思想就是对视频图像的多帧进行MeanShift运算 ...

  3. 分水岭算法java,OpenCV 学习笔记 04 深度估计与分割——GrabCut算法与分水岭算法...

    1 使用普通摄像头进行深度估计 1.1 深度估计原理 这里会用到几何学中的极几何(Epipolar Geometry),它属于立体视觉(stereo vision)几何学,立体视觉是计算机视觉的一个分 ...

  4. OpenCV学习笔记(十二)——图像分割与提取

    在图像处理的过程中,经常需要从图像中将前景对象作为目标图像分割或者提取出来.例如,在视频监控中,观测到的是固定背景下的视频内容,而我们对背景本身并无兴趣,感兴趣的是背景中出现的车辆.行人或者其他对象. ...

  5. OpenCV 学习笔记03 boundingRect、minAreaRect、minEnclosingCircle、boxPoints、int0、circle、rectangle函数的用法...

    函数中的代码是部分代码,详细代码在最后 1 cv2.boundingRect 作用:矩形边框(boundingRect),用于计算图像一系列点的外部矩形边界. cv2.boundingRect(arr ...

  6. python做直方图-python OpenCV学习笔记实现二维直方图

    本文介绍了python OpenCV学习笔记实现二维直方图,分享给大家,具体如下: 官方文档 – https://docs.opencv.org/3.4.0/dd/d0d/tutorial_py_2d ...

  7. OpenCV学习笔记大集锦

    转载自: OpenCV学习笔记大集锦 – 视觉机器人 http://www.cvrobot.net/collect-opencv-resource-learn-study-note-chinese/ ...

  8. OpenCV学习笔记(五十六)——InputArray和OutputArray的那些事core OpenCV学习笔记(五十七)——在同一窗口显示多幅图片 OpenCV学习笔记(五十八)——读《Mast

    OpenCV学习笔记(五十六)--InputArray和OutputArray的那些事core 看过OpenCV源代码的朋友,肯定都知道很多函数的接口都是InputArray或者OutputArray ...

  9. OpenCV学习笔记(五十一)——imge stitching图像拼接stitching OpenCV学习笔记(五十二)——号外:OpenCV 2.4.1 又出来了。。。。。 OpenCV学习笔记(五

    OpenCV学习笔记(五十一)--imge stitching图像拼接stitching stitching是OpenCV2.4.0一个新模块,功能是实现图像拼接,所有的相关函数都被封装在Stitch ...

最新文章

  1. 快速构建深度学习图像数据集,微软Bing和Google哪个更好用?
  2. zynq学习05 Zynq 7000 emio的gpio操作
  3. [译]ASP.NET Core 2.0 机密配置项
  4. 结构张量用于区分平坦、边缘、角点区域
  5. 硬盘安装Linux救援系统,硬盘安装linux系统
  6. 回调函数 相当于线程_阿里面试题:请简述下 Node 的线程模型
  7. P2024 [NOI2001]食物链[扩展域并查集]
  8. 程序员为什么应该旗帜鲜明地反对“最佳实践”?
  9. 多线程 Threading Multiprocessing(Python)
  10. Qt 5.9.6 下载及安装
  11. 串珠问题(今日头条笔试)
  12. tomcat服务器拒绝访问文件,tomcat拒绝访问特定文件
  13. android studio使用开源项目,gogo电子竞技-gogo电子竞技
  14. 开源配置管理中心apollo使用方法
  15. shell脚本使用两个横杠接收外部参数
  16. 用Python画哆啦A梦
  17. 服务器pytorch环境配置
  18. 中国北斗简单原理随笔
  19. ACL会议介绍 - Call for Main Conference Papers
  20. 项目:C++在线测评系统

热门文章

  1. ESP8266 Nodemcu 开发板 + Blinker 电脑远程开机支持小爱同学和手机APP
  2. self attention(自注意力机制)
  3. Android平台的标签云实现
  4. 漫谈程序员系列:任性,春节前辞职
  5. 聊聊Java的单元测试
  6. 【步进电机】简单介绍
  7. 【pwnable.kr】leg
  8. 罗永浩重返科技圈,却故人难寻
  9. instagram分享_Facebook,Twitter,Instagram,Google等使用的字体和颜色
  10. cocos2dx 更改帧频