若该文为原创文章,未经允许不得转载 上一篇:《OpenCV开发笔记(五十八):红胖子8分钟带你深入了解图像的矩(图文并茂+浅显易懂+程序源码)》 红胖子,来也! 分水岭分割方法,是一种基于拓扑理论的数学形态学的分割方法,其基本思想是把图像看作是测地学上的拓扑地貌,图像中每一点像素的灰度值表示该点的海拔高度,每一个局部极小值及其影响区域称为集水盆,而集水盆的边界则形成分水岭。简单来说就是根据图像相邻的像素差值,分成不同区域,将各区域染成不同颜色,其适合使用者已经可以标记已知对象或背景中的一部分。 分水岭比较经典的计算方法是L. Vincent提出的。在该算法中,分水岭计算分两个步骤,一个是排序过程,一个是淹没过程。首先对每个像素的灰度级进行从低到高排序,然后在从低到高实现淹没过程中,对每一个局部极小值在h阶高度的影响域采用先进先出(FIFO)结构进行判断及标注。 均值滤波:《OpenCV开发笔记(十五):算法基础之线性滤波-均值滤波》 对应版本号v1.53.0
上一篇:《OpenCV开发笔记(五十八):红胖子8分钟带你深入了解图像的矩(图文并茂+浅显易懂+程序源码)》
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/106258388
各位读者,知识无穷而人力有穷,要么改需求,要么找专业人士,要么自己研究
红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中…(点击传送门)OpenCV开发专栏(点击传送门)
下一篇:持续补充中…
前言
做识别,有时候需求要识别物体,物体在背景上比较杂,但是其边缘与背景图相差大,这个时候可以使用分水岭算法突出两边的颜色对比度,从而更好的分割。
Demo
分水岭算法
概述
&emp;分水岭的概念和形成可以通过模拟浸入过程来说明。在每一个局部极小值表面,刺穿一个小孔,然后把整个模型慢慢浸入水中,随着浸入的加深,每一个局部极小值的影响域慢慢向外扩展,在两个集水盆汇合处构筑大坝,即形成分水岭。
分水岭的计算过程是一个迭代标注过程。原理
分水岭变换得到的是输入图像的集水盆图像,集水盆之间的边界点,即为分水岭。显然,分水岭表示的是输入图像极大值点。因此,为得到图像的边缘信息,通常把梯度图像作为输入图像,即
g(x,y)=grad(f(x,y))={[f(x,y)-f(x-1,y)]2[f(x,y)-f(x,y-1)]2}0.5
式中,f(x,y)表示原始图像,grad{.}表示梯度运算。
分水岭算法对微弱边缘具有良好的响应,图像中的噪声、物体表面细微的灰度变化,都会产生过度分割的现象。但同时,分水岭算法对微弱边缘具有良好的响应,是得到封闭连续边缘的保证的。分水岭函数原型
void watershed(InputArray image, InputOutputArray markers )
Demo涉及到的相关知识
canny边缘检测:《OpenCV开发笔记(三十七):红胖子8分钟带你深入了解边缘检测和Canny算子边缘检测(图文并茂+浅显易懂+程序源码)》
查找与绘制轮廓:《OpenCV开发笔记(四十九):红胖子8分钟带你深入了解轮廓识别(图文并茂+浅显易懂+程序源码)》
Demo源码
void OpenCVManager::testWatersheed() { QString fileName1 = "E:/qtProject/openCVDemo/openCVDemo/modules/openCVManager/images/5.jpg"; int width = 400; int height = 300; cv::Mat srcMat = cv::imread(fileName1.toStdString()); cv::resize(srcMat, srcMat, cv::Size(width, height)); cv::String windowName = _windowTitle.toStdString(); cvui::init(windowName); cv::Mat windowMat = cv::Mat(cv::Size(srcMat.cols * 2, srcMat.rows * 3), srcMat.type()); int threshold1 = 200; int threshold2 = 100; while(true) { windowMat = cv::Scalar(0, 0, 0); cv::Mat mat; cv::Mat tempMat; // 原图先copy到左边 mat = windowMat(cv::Range(srcMat.rows * 0, srcMat.rows * 1), cv::Range(srcMat.cols * 0, srcMat.cols * 1)); cv::addWeighted(mat, 0.0f, srcMat, 1.0f, 0.0f, mat); { // 灰度图 cv::Mat grayMat; cv::cvtColor(srcMat, grayMat, cv::COLOR_BGR2GRAY); // copy mat = windowMat(cv::Range(srcMat.rows * 0, srcMat.rows * 1), cv::Range(srcMat.cols * 1, srcMat.cols * 2)); cv::Mat grayMat2; cv::cvtColor(grayMat, grayMat2, cv::COLOR_GRAY2BGR); cv::addWeighted(mat, 0.0f, grayMat2, 1.0f, 0.0f, mat); // 均值滤波 cv::blur(grayMat, tempMat, cv::Size(3, 3)); cvui::printf(windowMat, width * 1 + 20, height * 1 + 20, "threshold1"); cvui::trackbar(windowMat, width * 1 + 20, height * 1 + 40, 200, &threshold1, 0, 255); cvui::printf(windowMat, width * 1 + 20, height * 1 + 100, "threshold2"); cvui::trackbar(windowMat, width * 1 + 20, height * 1 + 120, 200, &threshold2, 0, 255); // canny边缘检测 cv::Canny(tempMat, tempMat, threshold1, threshold2); // copy mat = windowMat(cv::Range(srcMat.rows * 1, srcMat.rows * 2), cv::Range(srcMat.cols * 0, srcMat.cols * 1)); cv::cvtColor(tempMat, grayMat2, cv::COLOR_GRAY2BGR); cv::addWeighted(mat, 0.0f, grayMat2, 1.0f, 0.0f, mat); // 查找轮廓 std::vector<std::vector<cv::Point>> contours; std::vector<cv::Vec4i> hierarchy; cv::findContours(tempMat, contours, hierarchy, cv::RETR_CCOMP, cv::CHAIN_APPROX_SIMPLE); // 绘制轮廓 cv::Mat maskers = cv::Mat::zeros(grayMat.size(), CV_32SC1); maskers = cv::Scalar::all(0); cv::Mat tMat = srcMat.clone(); tMat = cv::Scalar(0, 0, 0); for(int index = 0; index < contours.size(); index++) { cv::drawContours(maskers, contours, index, cv::Scalar::all(index+1)); cv::drawContours(tMat, contours, index, cv::Scalar(0, 0, 255)); } // copy mat = windowMat(cv::Range(srcMat.rows * 2, srcMat.rows * 3), cv::Range(srcMat.cols * 0, srcMat.cols * 1)); cv::addWeighted(mat, 0.0f, tMat, 1.0f, 0.0f, mat); // 分水岭 cv::watershed(srcMat, maskers); cv::Mat watershedImage(maskers.size(), CV_8UC3) ; for(int i = 0 ; i < maskers.rows ; i++ ) { for(int j = 0 ; j < maskers.cols; j++) { int index = maskers.at<int>(i, j); if(index == -1) { watershedImage.at<cv::Vec3b>(i, j) = cv::Vec3b(255, 255, 255); }else if( index <= 0 || index > contours.size() ) { watershedImage.at<cv::Vec3b>(i, j) = cv::Vec3b(0, 0, 0); }else { watershedImage.at<cv::Vec3b>(i, j) = cv::Vec3b((index - 5 > 0 ? 0 : index % 5) * 50, (index - 5 > 0 ? index - 5 : 0) % 5 * 50, (index - 10 > 0 ? index - 10 : 0) % 5 * 50); } // 混合灰皮图和 分水岭效果 图 并显 示最终的窗 口 } } // copy mat = windowMat(cv::Range(srcMat.rows * 2, srcMat.rows * 3), cv::Range(srcMat.cols * 1, srcMat.cols * 2)); cv::addWeighted(mat, 0.0f, watershedImage, 1.0f, 0.0f, mat); } // 更新 cvui::update(); // 显示 cv::imshow(windowName, windowMat); // esc键退出 if(cv::waitKey(25) == 27) { break; } } }
工程模板:对应版本号v1.53.0
下一篇:持续补充中…
原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/106258388
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算