分水岭分割方法原理 (3种)
- 基于浸泡理论的分水岭分割方法 (距离)
- 基于连通图的方法
- 基于距离变换的方法 图像形态学操作:
- 腐蚀与膨胀
- 开闭操作 分水岭算法运用
- 分割粘连对象,实现形态学操作与对象计数
- 图像分割

#include <opencv2/opencv.hpp>
#include <iostream> using namespace cv;
using namespace std; int main(int argc, char** argv) {
Mat src = imread("D:/images/coins_001.jpg");
if (src.empty()) {
printf("could not load image...\n");
return -;
}
namedWindow("input image", CV_WINDOW_AUTOSIZE);
imshow("input image", src); Mat gray, binary, shifted;
pyrMeanShiftFiltering(src, shifted, , );
//imshow("shifted", shifted); //灰度
cvtColor(shifted, gray, COLOR_BGR2GRAY);
threshold(gray, binary, , , THRESH_BINARY | THRESH_OTSU);
//imshow("binary", binary); // 距离变换
Mat dist;
distanceTransform(binary, dist, DistanceTypes::DIST_L2, , CV_32F);
normalize(dist, dist, , , NORM_MINMAX);
//imshow("distance result", dist); // 二值化
threshold(dist, dist, 0.4, , THRESH_BINARY);
//imshow("distance binary", dist); // markers
Mat dist_m;
dist.convertTo(dist_m, CV_8U);
vector<vector<Point>> contours;
findContours(dist_m, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point(, )); // create markers
Mat markers = Mat::zeros(src.size(), CV_32SC1);
for (size_t t = ; t < contours.size(); t++) {
drawContours(markers, contours, static_cast<int>(t), Scalar::all(static_cast<int>(t) + ), -);
}
circle(markers, Point(, ), , Scalar(), -);
//imshow("markers", markers*10000); // 形态学操作 - 彩色图像,目的是去掉干扰,让结果更好
Mat k = getStructuringElement(MORPH_RECT, Size(, ), Point(-, -));
morphologyEx(src, src, MORPH_ERODE, k); // 完成分水岭变换
watershed(src, markers);
Mat mark = Mat::zeros(markers.size(), CV_8UC1);
markers.convertTo(mark, CV_8UC1);
bitwise_not(mark, mark, Mat());
//imshow("watershed result", mark); // generate random color
vector<Vec3b> colors;
for (size_t i = ; i < contours.size(); i++) {
int r = theRNG().uniform(, );
int g = theRNG().uniform(, );
int b = theRNG().uniform(, );
colors.push_back(Vec3b((uchar)b, (uchar)g, (uchar)r));
} // 颜色填充与最终显示
Mat dst = Mat::zeros(markers.size(), CV_8UC3);
int index = ;
for (int row = ; row < markers.rows; row++) {
for (int col = ; col < markers.cols; col++) {
index = markers.at<int>(row, col);
if (index > && index <= contours.size()) {
dst.at<Vec3b>(row, col) = colors[index - ];
}
else {
dst.at<Vec3b>(row, col) = Vec3b(, , );
}
}
} imshow("Final Result", dst);
printf("number of objects : %d\n", contours.size()); waitKey();
return ;
}

#include <opencv2/opencv.hpp>
#include <iostream> using namespace cv;
using namespace std; Mat watershedCluster(Mat &image, int &numSegments);
void createDisplaySegments(Mat &segments, int numSegments, Mat &image);
int main(int argc, char** argv) {
Mat src = imread("D:/images/cvtest.png");
if (src.empty()) {
printf("could not load image...\n");
return -;
}
namedWindow("input image", CV_WINDOW_AUTOSIZE);
imshow("input image", src); int numSegments;
Mat markers = watershedCluster(src, numSegments);
createDisplaySegments(markers, numSegments, src);
waitKey();
return ;
} Mat watershedCluster(Mat &image, int &numComp) {
// 二值化
Mat gray, binary;
cvtColor(image, gray, COLOR_BGR2GRAY);
//阈值
threshold(gray, binary, , , THRESH_BINARY | THRESH_OTSU);
// 形态学与距离变换
Mat k = getStructuringElement(MORPH_RECT, Size(, ), Point(-, -));
morphologyEx(binary, binary, MORPH_OPEN, k, Point(-, -));
Mat dist;
distanceTransform(binary, dist, DistanceTypes::DIST_L2, , CV_32F);
normalize(dist, dist, 0.0, 1.0, NORM_MINMAX); // 开始生成标记
threshold(dist, dist, 0.1, 1.0, THRESH_BINARY);
normalize(dist, dist, , , NORM_MINMAX);
dist.convertTo(dist, CV_8UC1); // 标记开始
vector<vector<Point>> contours;
vector<Vec4i> hireachy;
findContours(dist, contours, hireachy, RETR_CCOMP, CHAIN_APPROX_SIMPLE);
if (contours.empty()) {
return Mat();
} Mat markers(dist.size(), CV_32S);
markers = Scalar::all();
for (int i = ; i < contours.size(); i++) {
drawContours(markers, contours, i, Scalar(i + ), -, , hireachy, INT_MAX);
}
//填充
circle(markers, Point(, ), , Scalar(), -); // 分水岭变换
watershed(image, markers);
numComp = contours.size();
return markers;
} void createDisplaySegments(Mat &markers, int numSegments, Mat &image) {
// generate random color
vector<Vec3b> colors;
for (size_t i = ; i < numSegments; i++) {
int r = theRNG().uniform(, );
int g = theRNG().uniform(, );
int b = theRNG().uniform(, );
colors.push_back(Vec3b((uchar)b, (uchar)g, (uchar)r));
} // 颜色填充与最终显示
Mat dst = Mat::zeros(markers.size(), CV_8UC3);
int index = ;
for (int row = ; row < markers.rows; row++) {
for (int col = ; col < markers.cols; col++) {
index = markers.at<int>(row, col);
if (index > && index <= numSegments) {
dst.at<Vec3b>(row, col) = colors[index - ];
}
else {
dst.at<Vec3b>(row, col) = Vec3b(, , );
}
}
}
imshow("分水岭图像分割-演示", dst);
return;
}

opencv::分水岭图像分割的更多相关文章

  1. Opencv分水岭算法——watershed自动图像分割用法

    分水岭算法是一种图像区域分割法,在分割的过程中,它会把跟临近像素间的相似性作为重要的参考依据,从而将在空间位置上相近并且灰度值相近的像素点互相连接起来构成一个封闭的轮廓,封闭性是分水岭算法的一个重要特 ...

  2. OpenCV 1 图像分割--分水岭算法代码

    // watershed_test20140801.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" // // ch9_watershed ...

  3. opencv分水岭算法对图像进行切割

    先看效果 说明 使用分水岭算法对图像进行切割,设置一个标记图像能达到比較好的效果,还能防止过度切割. 1.这里首先对阈值化的二值图像进行腐蚀,去掉小的白色区域,得到图像的前景区域.并对前景区域用255 ...

  4. OpenCV 之 图像分割 (一)

    1  基于阈值 1.1  基本原理 灰度阈值化,是最简单也是速度最快的一种图像分割方法,广泛应用在硬件图像处理领域 (例如,基于 FPGA 的实时图像处理). 假设输入图像为 f,输出图像为 g,则经 ...

  5. Opencv 分水岭分割图片

    #include <iostream>#include <opencv2/opencv.hpp> using namespace std;using namespace cv; ...

  6. opencv::KMeans图像分割

    #include <opencv2/opencv.hpp> #include <iostream> using namespace cv; using namespace st ...

  7. opencv 金字塔图像分割

    我所知的opencv中分割函数:watershed(只是看看效果,不能返回每类pixel类属),cvsegmentImage,cvPyrSegmentation(返回pixel类属) 金字塔分割原理篇 ...

  8. OpenCV——分水岭算法

    分水岭算法,是一种基于拓扑理论的数学形态学的分割方法,其基本思想是把图像看作是测地学上的拓扑地貌,图像中每一点像素的灰度值表示该点的海拔高度,每一个局部极小值及其影响区域称为集水盆,而集水盆的边界则形 ...

  9. opencv kmeans 图像分割

    利用kmeans算法,将彩色图像的像素点作为样本,rgb值作为样本的属性, 对图像所有的像素点进行分类,从而实现对图像中目标的分割. c++代码(openCV 2.4.11) Scalar color ...

随机推荐

  1. XCode证书问题

    1. 确认下证书是不是开发证书,如果是发布证书就会出现这样的提示. 2. 证书失效了,去开发者中心重新生成一个. 3. 包标识符不与描述文件包含的包标识符不一致,按照它的提示换一下就好了,最好不要点 ...

  2. [b0026] python 归纳 (十一)_线程_threading.Thread

    总结: 默认父线程跑完,子线程并不会马上退出,不像 thread.start_threadXXXX 父线程跑完了,并没有退出,一直在那里 线程启动速度很快,不占多少开销,不到1毫 秒 代码: # -* ...

  3. Python—下载安装与使用

    安装依赖包 首先安装gcc编译器,编译时需要使用gcc.gcc有些系统版本已经默认安装,通过  gcc --version  查看,没安装的先安装 [root@localhost ~]# yum -y ...

  4. Linxu:磁盘分区

    了解磁盘分区 磁盘的物理组成: 圆形的磁盘盘(主要记录数据的部分): 机械手臂,与在机械手臂上的磁盘读取头(可擦写磁盘盘上的数据): 主轴马达,可以转动磁盘盘,让机械手臂的读取头在磁盘盘上读写数据. ...

  5. 【转】Redis相关

      1. 什么是redis? Redis 是一个使用 C 语言写成的,开源的基于内存的高性能key-value数据库. Redis的值可以是由string(字符串).hash(哈希).list(列表) ...

  6. [C1] Andrew Ng - AI For Everyone

    About this Course AI is not only for engineers. If you want your organization to become better at us ...

  7. (day56)八、删除框、批量创建、分页器组件

    目录 一.ajax结合sweetalert实现删除按钮的动态效果 二.bulk_create批量插入数据 三.自定义分页器 (一)手动推导 (二)自定义分页器 (1)模板 (2)用法 一.ajax结合 ...

  8. Dijkstra算法堆优化详解

    DIJ算法的堆优化 DIJ算法的时间复杂度是\(O(n^2)\)的,在一些题目中,这个复杂度显然不满足要求.所以我们需要继续探讨DIJ算法的优化方式. 堆优化的原理 堆优化,顾名思义,就是用堆进行优化 ...

  9. slideDown()、slideUp()反复执行的问题

    <ul class="main"> <li><a href="#">菜单一</a> <ul> < ...

  10. A1047 Student List for Course (25 分)

    一.技术总结 首先题目要看清湖,提出的条件很关键,比如for循环的终止条件,特别注意. 还有这个题目主要考虑到vector的使用,还有注意一定要加上using namespace std; 输出格式, ...