图像分割是图像处理最重要的处理手段之一
图像分割的目标是将图像中像素根据一定的规则分为若干个cluster集合每个集合包括一类像素
根据算法分为监督学习和无监督学习,图像分割的算法多数都是无监督学习-KMenas
距离变换常见算法有两种
- 不断膨胀/ 腐蚀得到
- 基于倒角距离
分水岭变换常见的算法
基于浸泡理论实现,假设颜色数据为一个个山头,在山底不停加水,直到各大山头之间形成了明显的分水线
API:
watershed ( // 分水岭变换
InputArray image,
InputOutputArray markers
)
distanceTransform ( // 距离变换
InputArray src, // 输入的图像,一般为二值图像
OutputArray dst, // 输出8位或者32位的浮点数,单一通道,大小与输入图像一致
OutputArray labels, // 输出 2D 的标签(离散Voronoi(维诺)图),类型为 CV_32SC1
,相同距离的算做同一个 label ,算出总共由多少个 labels
int distanceType, // 所用的求解距离的类型
CV_DIST_L1 distance = |x1-x2| + |y1-y2|
CV_DIST_L2 distance = sqrt((x1-x2)^2 + (y1-y2)^2) 欧几里得距离
CV_DIST_C distance = max(|x1-x2|, |y1-y2|)
int maskSize, // 最新的支持5x5,推荐3x3
int labelType=DIST_LABEL_CCOMP // Type of the label array to build, see cv::DistanceTransformLabelTypes
)
步骤:
- 将白色背景变成黑色-目的是为后面的变换做准备
- 使用filter2D与拉普拉斯算子实现图像对比度提高,sharp锐化
- 转灰度转为二值图像通过threshold
- 距离变换
- 对距离变换结果进行归一化到0-1之间
- 使用阈值再次二值化得到标记
- 腐蚀得到每个peak-erode
- 发现轮廓-findContours
- 绘制轮廓-drawcontours
- 分水岭变换watershed
- 对每个分割区域着色输出结果
代码:
#include <opencv2/opencv.hpp>
#include<iostream>
#include<math.h>
#include <string>
#include<fstream>
using namespace cv;
using namespace std;
int main() {
Mat src;
src =