基于距离变换与分水岭的图像分割 (一)
作者:互联网
什么是图像分割
image segmentation 直观含义就是将图像从背景中分离开
图像分割是图像处理最重要的处理手段之一
图像分割的目标是将图像中的像素根据一定的规则分为若干个cluster几何,每个集合包含一类像素
根据算法分为监督学习方法和无监督学习方法,图像分割的算法多数都是无监督的学习方法(K-Means)
距离变换分水岭介绍
距离变换常见算法有两种
一种是不断膨胀/腐蚀得到
另一种是倒角距离
将图像灰度值看作山峰,按照高度进行区域划分就是分水岭算法
常见的分水岭算法是基于浸泡理论实现的
API
距离变换API
cv::distanceTransform(InputArray src,OutputArray dst,OutputArray labels,int distanceType,int maskSize,int labelType=DIST_LABEL_CCOMP)
distancdType=DIST_L1/DIST_L2
maskSize=3x3最新的可以5x5,推荐3,3
labels离散维诺图输出
dst输出8位或者32位浮点数,大小与输入图像一致
分水岭API
cv::watershed(InputArray image,InputOutputArray markers)
markers就是标线
处理流程
1.将白色背景变为黑色,为后续变换做准备
2.使用filter2D与拉普拉斯算子实现图像对比度提高,sharp
3.转为二值图像通过threshold
4.距离变换
5.对距离变换得到的结果进行归一化,[0,1]之间
6.使用阈值,再次二值化,得到标记
7.腐蚀得到每个Peak-erode
8.发现轮廓-findContours
9.绘制轮廓-drawContours
10.分水岭变换watershed
11.对每个分割区域进行着色输出结果
Demo
#include"pch.h" #include<iostream> #include<opencv2/opencv.hpp> #include<math.h> using namespace std; using namespace cv; int main(int argc, char** argv) { Mat src,gray; src = imread("water.jpg"); imshow("input img", src); //cvtColor(src, gray, COLOR_BGR2GRAY); //反转背景 for(int row=0;row<src.rows;++row) for (int col = 0; col < src.cols; ++col) { 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("black background", src); //锐化 Mat imgLaplance; Mat sharp = src; src.convertTo(sharp, CV_32F); Mat kernel = (Mat_<float>(3, 3) << 1, 1, 1, 1, -8, 1, 1, 1, 1); filter2D(src, imgLaplance, CV_32F, kernel, Point(-1, -1), 0, BORDER_DEFAULT); Mat resultImg = sharp - imgLaplance; resultImg.convertTo(resultImg, CV_8UC3); imgLaplance.convertTo(imgLaplance, CV_8UC3); imshow("sharp", resultImg); //二值距离变换 Mat binaryImg; cvtColor(resultImg, resultImg, COLOR_BGR2GRAY); threshold(resultImg, binaryImg, 40, 255, THRESH_BINARY | THRESH_OTSU); imshow("binary", binaryImg); //距离变换 Mat dstImg; distanceTransform(binaryImg, dstImg, DIST_L1, 3, 5); normalize(dstImg, dstImg, 0, 1, NORM_MINMAX); imshow("dist img", dstImg); threshold(dstImg, dstImg, 0.4, 1, THRESH_BINARY); imshow("threshold", dstImg); //二值腐蚀 Mat Kernel1 = Mat::ones(13, 13, CV_8UC1); erode(dstImg, dstImg, Kernel1, Point(-1, -1)); imshow("erode", dstImg); waitKey(); return 0; }
标签:src,分割,Mat,int,变换,图像,分水岭,row 来源: https://www.cnblogs.com/wangtianning1223/p/13443261.html