距离变换

输出像素的值为,输入图像中,与最近的零像素的距离,可显示物体靠质心的位置。

一般先对灰度图像取反,即转化为黑色背景。

void distanceTransform( InputArray src, OutputArray dst,int distanceType, int maskSize, int dstType=CV_32F);
//distanceType,输入DIST_C,DIST_L1,DIST_L2,分别表示计算四连通,八连通,和精准的欧氏距离
//markSize输入3/5.表示使用3x3/5x8的掩膜

分水岭算法

先通过距离变换求出物体质心后,将其想象成山顶,而其他地方为山谷,灌水后,山谷被填满,只剩下山顶,图像就被分割开来。

void watershed( InputArray image, InputOutputArray markers );
//输入8位三通道图像,输入cv_32SC1的Markers标记。
//输出给markers,0为不确定区域,-1为边界。

实战演练

处理流程

  1. 将白色背景转化为黑色
  2. sharp,使用拉普拉斯算子将图像对比度提高,突出边缘。
  3. 二值化
  4. 距离变换
  5. 归一化[0~1]之间
  6. 再次二值化
  7. 腐蚀
  8. 发现轮廓
  9. 绘制轮廓/轮廓编号
  10. 分水岭变换
  11. 着色输出
#include<opencv2/opencv.hpp>
#include<opencv2/core/mat.hpp>
#include<iostream>
#include<vector>
using namespace std;
using namespace cv;int main()
{Mat src0;Mat src, dst;src = imread("C:/Users/LBJ/Desktop/OpenCVTest/puke.png");if (!src.data){cout << "The iamge is empty" << endl;return -1;}imshow("input_img", src);src0 = src;//背景转化为黑色cvtColor(src, src, CV_BGR2GRAY);threshold(src, src, 251, 255, THRESH_TOZERO_INV);medianBlur(src, src, 5);//锐化提高边缘对比度Mat kernel = (Mat_<float>(3, 3) << 1, 1, 1,1, -8, 1,1, 1, 1);Mat laplas, sharp = src;filter2D(sharp, laplas, CV_32F, kernel, Point(-1, -1), 0);src.convertTo(sharp, CV_32F);sharp = sharp - laplas * 5;sharp.convertTo(sharp, CV_8U);threshold(sharp, sharp, 30, 255, THRESH_BINARY | THRESH_OTSU);//距离变换0Mat distan;distanceTransform(sharp, distan, CV_DIST_L2, CV_DIST_MASK_PRECISE);normalize(distan, distan, 0, 255, NORM_MINMAX);threshold(distan, distan, 0.4 * 255, 255, THRESH_BINARY);//腐蚀Mat marks = Mat::zeros(src.size(), CV_32SC1);Mat erod;Mat ker = Mat::ones(Size(3, 3), CV_8U);erode(distan, erod, ker, Point(-1, -1));//发现轮廓 绘制轮廓Mat dist_8u;erod.convertTo(dist_8u, CV_8UC1);vector<vector<Point>> contours;vector<Vec4i> hierachy;findContours(dist_8u, contours, hierachy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));for (int i = 0; i < contours.size(); i++){drawContours(marks, contours, i, Scalar::all(i + 1), -1, 8, hierachy, 0, Point(0, 0));}circle(marks, Point(5, 5), 3, Scalar(255, 255, 255), -1);//分水岭变换cvtColor(src0, src0, CV_BGR2GRAY);threshold(~src0, src0, 20, 255, THRESH_BINARY);cvtColor(src0, src0, CV_GRAY2BGR);watershed(src0, marks);Mat marker = Mat::zeros(marks.size(), CV_8UC1);marks.convertTo(marker, CV_8UC1);bitwise_not(marker, marker, Mat());dst = Mat::zeros(src0.size(), src0.type());RNG rng;vector<Vec3b> colors;for (size_t i = 0; i < contours.size(); i++){int r = rng.uniform(0, 255);int g = rng.uniform(0, 255);int b = rng.uniform(0, 255);colors.push_back(Vec3b(uchar(b), uchar(g), uchar(r)));}for (size_t row = 0; row < marks.rows; row++){for (size_t col = 0; col < marks.cols; col++){if (marks.at<int>(row,col)==-1){dst.at<Vec3b>(row, col) = Vec3b(255, 255, 255);}else if (marks.at<int>(row, col) >0 && marks.at<int>(row, col)<=static_cast<int>(contours.size())){dst.at<Vec3b>(row, col) = colors[marks.at<int>(row, col)-1];}else{continue;}}}imshow("output", dst);waitKey(0);return 0;
}

感觉分割的效果还是有待提高的,后续再优化

OpenCv笔记(五)--图像分割与分水岭算法相关推荐

  1. OpenCV中的图像处理 —— 霍夫线 / 圈变换 + 图像分割(分水岭算法) + 交互式前景提取(GrabCut算法)

    OpenCV中的图像处理 -- 霍夫线 / 圈变换 + 图像分割(分水岭算法) + 交互式前景提取(GrabCut算法)

  2. OpenCV学习(二十) :分水岭算法:watershed()

    OpenCV学习(二十) :分水岭算法:watershed() 参考博客: OpenCV-分水岭算法 图像处理--分水岭算法 OpenCV学习(7) 分水岭算法(1) Opencv分水岭算法--wat ...

  3. python图像分割算法_Opencv(二)—图像分割之分水岭算法!

    做图像处理时,我们可能会遇到一个问题:我们只需要图片的一部分区域,如何把图片中的某部分区域提取出来 或者 图像想要的区域用某种颜色(与其它区域颜色不一致)标记起来 ,以上描述的问题在像处理领域称为 图 ...

  4. OpenCV与图像处理学习十一——分水岭算法(含代码)

    OpenCV与图像处理学习十一--分水岭算法(含代码) 一.分水岭算法概要 二.分水岭算法步骤 三.代码应用 一.分水岭算法概要 任意的灰度图像可以被看做是地质学表面,高亮度的地方是山峰,低亮度的地方 ...

  5. OpenCV 【四】————Watershed Algorithm(图像分割)——分水岭算法的原理及实现

    分水岭算法实现(C++.opencv) 1.作用: 通常用于分割图像,主要实现以临近像素间的相似性作为重要的参考依据,从而将在空间位置上相近并且灰度值相近的像素点互相连接起来构成一个封闭的轮廓,封闭性 ...

  6. 【OpenCV】 - 图像分割之分水岭算法,watershed()函数的输出,对marker和image的改变

    一.背景 最近在学分水岭算法的opencv函数watershed()时,对函数执行完后image和marker的变化一无所知.懵懵懂懂. 于是便结合网上资料和自己现身说法,给大家分享一下[waters ...

  7. OpenCV系列之图像分割与Watershed算法 | 三十四

    目标 在本章中, 我们将学习使用分水岭算法实现基于标记的图像分割 我们将看到:cv.watershed() 理论 任何灰度图像都可以看作是一个地形表面,其中高强度表示山峰,低强度表示山谷.你开始用不同 ...

  8. 图像分割之分水岭算法

    使用C++.opencv进行分水岭分割图像 分水岭概念是以对图像进行三维可视化处理为基础的:其中两个是坐标,另一个是灰度级.基于"地形学"的这种解释,我们考虑三类点: a.属于局部 ...

  9. 使用OpenCV和C++实现的分水岭算法(Watershed)

    分水岭算法(watershed)是一种比较基本的数学形态学分割算法,其基本思想是将灰度图像转换为梯度图像,将梯度值看作高低起伏的山岭,将局部极小值及其邻域看作一个"集水盆".设想一 ...

最新文章

  1. Python设计模式-观察者模式
  2. python在abaqus中的应用代码下载_Python-(source-code)-in--Abaqus Python语言在Abaqus中的应用(源码) - 下载 - 搜珍网...
  3. CentOS 6.4 配置LAMP 环境 与安装 phpmyadmin
  4. 在那天的雪停息之前β
  5. java虚拟机采用UTF-16编码格式对字符进行编码
  6. 为什么0.1无法被二进制小数精确表示?
  7. 二陈丸配什么吃不上火_宝妈一个人带孩子是什么感觉?前三种场景,不知道是怎么熬过来的...
  8. 计算机安全知识讲座,计算机学院安全知识讲座:防火防电防诈骗 人身安全记心间...
  9. 在用ganglia时出现You don‘t have permission to access ganglia on this server
  10. 《我一开口,就能说服所有人》读书随记
  11. 存储ic载板_【行业亮点】看好载板供不应求趋势,深南/兴森/越亚积极布局
  12. WinEdt 的 LaTeX 生成的 pdf 无法中文正向搜索/中文复制后乱码解决
  13. 计算机配机方案和理由,配机方案
  14. 澳大利亚麦考瑞大学计算机系杨坚教授团队招收2022-2023年博士研究生
  15. 一张表格搞懂那些特殊的IP地址
  16. Windows 定时启动 关闭软件
  17. python vbs_python和vbs
  18. Ubuntu系统崩溃与修复
  19. 自动驾驶感知——环境感知的基本概念
  20. 单片机c语言define什么意思,单片机C语言中typedef和define的区别是什么?

热门文章

  1. 应用SerialPort实现串口扫码枪ST2200操作
  2. NP=P,一种解决方案
  3. C语言内功修炼之函数栈帧的创建与销毁(举例加图解)
  4. c语言 取余 % 和除法 / 的应用技巧 (在取位数方面的)
  5. 国内Android源码下载
  6. Android 俄罗斯方块
  7. 软考可以不考初级直接考中级吗?
  8. 点击按钮复制链接(实现点击按钮,复制文本框中的的内容)
  9. supervisor查询状态报错
  10. vue2[初级] vuex状态集中式管理