赞
踩
1.图像分割是图像处理最重要的处理手段之一
2.根据灰度、颜色、纹理和形状等特征,把图像分成若干个特定的、具有独特性质的区域,这些特征在同一区域内呈现出相似性,而在不同区域间呈现出明显的差异性,并提出感兴趣目标的技术和过程。 它是由图像处理到图像分析的关键步骤。从数学角度来看,图像分割是将数字图像划分成互不相交的区域的过程。图像分割的过程也是一个标记过程,即把属于同一区域的像素赋予相同的编号
3.图像分割的目标是将图像中像素根据一定的规则分为若干(N)个cluster(集群)集合
每个集合包含一类像素,根据算法分为监督学习和无监督学习方法,图像分割的
算法多数都是无监督学习方法—Kmeans
如果应用到单幅图像上则是主要为 图像窄化 骨架提取 粘连物体的分离
等
如果应用到原图跟模板图则是应用于 图像匹配
分水岭的概念
分水岭概念是以对图像进行三维可视化处理为基础的:其中两个是坐标,另一个是灰度级。基于“地形学”的这种解释,我们考虑三类点:
a点.属于 局部性最小值的点 ,也可能存在一个最小值面,该平面内的都是最小值点
b点.当一滴水放在某点的位置上的时候,水 一定会下落到一个单一的最小值点
c点.当水处在某个点的位置上时,水会 等概率地流向不止一个这样的最小值点
对一个特定的区域最小值:
满足条件(b)的点的集合称为这个最小值的“汇水盆地”或“分水岭”
满足条件©的点的集合组成地形表面的峰线,称做“分割线”或“分水线”
分水岭的分割方法
分水岭分割方法,是一种基于拓扑理论的数学形态学的分割方法,目前较著名且使用较多的有2种算法:(1) 自下而上的模拟泛洪的算法 (2) 自上而下的模拟降水的算法
泛洪算法:
我们把图像看作是测地学上的拓扑地貌,图像中 每一点像素的灰度值表示该点的海拔高度 ,模拟泛洪算法的基本思想是:假设在每个区域最小值的位置上打一个洞并且让水以均匀的上升速率从洞中涌出,从低到高淹没整个地形。当处在不同的汇聚盆地中的水将要聚合在一起时,修建的大坝将阻止聚合。水将达到在水线上只能见到各个水坝的顶部这样一个程度。这些大坝的边界对应于分水岭的分割线。所以,它们是由分水岭算法提取出来的(连续的)边界线
右一图片 显示了一个简单的灰度级图像,其中“山峰”的高度与输入图像的灰度级值成比例,为了阻止上升的水从这些结构的边缘溢出,我们想像将整幅地形图的周围用比最高山峰还高的大坝包围起来。最高山峰的值是由输入图像灰度级具有的最大值决定的
水淹没的第一个阶段,这里水用浅灰色表示,覆盖了对应于图中深色背景的区域
水分别在第一和第二汇水盆地中上升。由于水持续上升,最终水将从一个汇水盆地中溢出到另一个之中
上图中水从左边的盆地溢出到右边的盆地,并且两者之间有一个短“坝”(由单像素构成)阻止这一水位的水聚合在一起。随着水位不断上升,如右图所显示的那样。这幅图中在两个汇水盆地之间显示了一条更长的坝,另一条水坝在右上角。这条水坝阻止了盆地中的水和对应于背景的水的聚合
这个过程不断延续直到到达水位的最大值(对应于图像中灰度级的最大值)。水坝最后剩下的部分对应于分水线,这条线就是要得到的分割结果。
分水线在图中显示为叠加到原图上的一个像素宽的深色路径。注意一条重要的性质就是分水线组成一条连通的路径,由此给出了区域之间的连续的边界(知道了边界就能根据边界分割粘连的图像)
分水岭算法详解:
https://blog.csdn.net/Lemon_jay/article/details/89355937?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-6.edu_weight&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-6.edu_weight
封闭性是分水岭算法的一个重要特征
其他图像分割方法,如阈值,边缘检测等都不会考虑像素在空间关系上的相似性和封闭性这一概念,彼此像素间互相独立,没有统一性
OpenCV中的watershed函数实现的分水岭算法是基于“标记”的分割算法,用于解决传统的分水岭算法过度分割的问题
距离变换
距离变换常见算法有两种
1.不断膨胀/腐蚀得到
2.基于倒角距离
距离变化用于获取每个图像的中心区域 配合后面的二值化和腐蚀操作之后就可以使粘连的目标进行分离
分水岭
基于浸泡(泛洪)理论实现的分水岭算法
距离变换API cv::distanceTransform
distanceTransform
(
InputArray src,//输入图像
OutputArray dst,//输出8位或者32位的浮点数,单一通道,大小与输入图像一致
OutputArray labels,//离散维诺图输出 (相同距离的分为同一个labels)
int distanceType,//distanceType=DIST_L1/DIST_L2 (距离变换的类型 曼哈顿和欧几里得)
int maskSize, //maskSize=3*3,也支持5*5,推荐3*3
int labelType=DIST_LABEL_CCOMP
)
分水岭API cv::watershed
watershed
(
InputArray image,//输入图像
InputOutputArray markers//既做为输入也做为输出,其为具有一个个小山头的图像
)
处理流程
1.将白色背景变成黑色目的是为后面的变换做准备
2.使用ilter2D与拉普拉斯算子实现图像对比度提高, sharp
3.转为二值图像通过threshold
4.距离变换
5.对距离变换结果进行归一化到0~1之间
6.使用阈值,再次二值化, 得到标记(山头高低和让连在一起的山头分开)
7.腐蚀得到每个Peak(山峰)-erode(侵蚀)
8.发现轮廓- findContours
9.绘制轮廓- drawContours
10.分水岭变换watershed
11.对每个分割区域着色输出结果
基于距离变换与分水岭的图像分割
#include <opencv2/opencv.hpp> #include <opencv2/highgui/highgui_c.h> #include <iostream> #include <math.h> using namespace cv; using namespace std; Mat src, dst; int Osize = 0; void DTwatershed(int, void*); int main() { src = imread("D:/实验台/机器视觉/测试图片/图像分割2.jpg"); if (src.empty())//如果src这个数据库属性为空 { cout << "无法打开" << endl; return -1; } //imshow("原图", src); //namedWindow("去背景的原图", CV_WINDOW_AUTOSIZE); //createTrackbar("各值调节", "去背景的原图", &Osize, 1, DTwatershed); DTwatershed(0, 0); waitKey(0); return 0; } //去背景实验 /*void DTwatershed(int, void*) { Mat test; src.copyTo(test); imshow("test", test); //去背景 //将白色背景变成黑色,目的是为后面的变换做准备(要确保输入的图片背景不能失真) for (int row = 0; row < src.rows; row++) { for (int col = 0; col < src.cols; col++) { // if (src.at<Vec3b>(row, col)[0] >= 250 && src.at<Vec3b>(row, col)[1] >= 250 && src.at<Vec3b>(row, col)[2] >= 250) if (src.at<Vec3b>(row, col) == Vec3b(255, 255, 255)) { src.at<Vec3b>(row, col)[0] = 0; src.at<Vec3b>(row, col)[1] = 0; src.at<Vec3b>(row, col)[2] = 0; } } } imshow("去背景的原图", src); }*/ void DTwatershed(int, void*) { //去背景(为后期的距离变换做准备) //将白色背景变成黑色,目的是为后面的变换做准备(要确保输入的图片背景不能失真) for <
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。