OpenCV学习(8) 分水岭算法(2)
现在我们看看OpenCV中如何使用分水岭算法。
首先我们打开一副图像:
// 打开另一幅图像
cv::Mat image= cv::imread("../tower.jpg");
if (!image.data)
{
cout<<"不能打开图像!"<<endl;
return 0;
}
接下来,我们要创建mark图像。mark图像格式是有符号整数,其中没有被mark的部分用0表示,其它不同区域的mark标记,我们用非零值表示,通常为1-255,但也可以为其它值,比如大于255的值,不同mark区域甚至可以用同样的值,这个值大小对最后分割可能没有影响(也可能影响),最好不同mark区域还是用不同的值表示,这样能够确保结果正确,之所以用有符号整数,是因为opencv在分水岭算法内部,要用-1,-2等来标记注水区域,最终在mark图像中生成的分水岭线就是用-1表示。
我们通常会创建uchar格式的灰度图,指定mark区域,然后转化为有符号整数的图像格式。
首先对整个背景区域我们创建一个mark域,是下图中白色框框住的部分,其灰度值为255,第二个选择mark域为塔,就是黑色框框住的一块区域,其灰度值为64,最后就是树mark域,蓝色框的部分,其灰度值为128。在分水岭算法时候,会分别对这个3个区域来进行注水操作,如果两个注水盆地被一个mark域覆盖,则它们之间不会有分水岭线产生。
对于mark图像,opencv分水岭算法在初始化时候,会把最外圈的值置为-1,作为整个图像的边界,所以我们第一个mark区域,选择倒数第2外圈,因为设置到最外圈,最后还是会被冲掉。
// 标示背景图像
cv::Mat imageMask(image.size(),CV_8U,cv::Scalar(0));
cv::rectangle(imageMask,cv::Point(1,1),cv::Point(image.cols-2,image.rows-2),cv::Scalar(255),1);
// 表示塔
cv::rectangle(imageMask,cv::Point(image.cols/2-10,image.rows/2-10),
cv::Point(image.cols/2+10,image.rows/2+10),cv::Scalar(64),10);
//树
cv::rectangle(imageMask,cv::Point(64,284),
cv::Point(68,300),cv::Scalar(128),5);
mark图像:
注意:mark图像是32bit的有符号整数,所以在使用分水岭算法前,我们先对mark图像做一个转化。算法执行完后,再转化为0-255的灰度图。
imageMask.convertTo(imageMask,CV_32S);
// 设置marker和处理图像
cv::watershed(image,imageMask);
cv::Mat mark1;
imageMask.convertTo(mark1,CV_8U);
cv::namedWindow("marker");
cv::imshow("marker",mark1);
此时imageMask图像从无符号整数转化为uchar后,如下图所示,第一个mask区域注水,将会使得整个图像为白色,之后分别在第二个,第三个区域的盆地注水,会产生相应的注水图,注水的区域的值即为mark的值,128和64, 分水岭线则为0,注:在转化前分水岭线的值为-1,转化后成为0。
我们使用一个转化函数把分水岭线转化为黑色,其它的部分都白黑色,转化函数的公式为:
imageMask(x,y) = saturate_cast<uchar>(255*imageMask(x,y)+255)
imageMask.convertTo(imageMask,CV_8U,255, 255);
最后显示分水岭线,得到下图:(注:在转化前,分水岭线的值为-1)
源码:工程FirstOpenCV7
下载:稍后提供
OpenCV学习(8) 分水岭算法(2)的更多相关文章
- OpenCV学习(9) 分水岭算法(3)
本教程我学习一下opencv中分水岭算法的具体实现方式. 原始图像和Mark图像,它们的大小都是32*32,分水岭算法的结果是得到两个连通域的轮廓图. 原始图像:(原始图像必须是3通道图像) Mark ...
- OpenCV学习(7) 分水岭算法(1)
分水岭算法主要用于图像分段,通常是把一副彩色图像灰度化,然后再求梯度图,最后在梯度图的基础上进行分水岭算法,求得分段图像的边缘线. 下面左边的灰度图,可以描述为右边的地 ...
- OpenCV学习(16) 细化算法(4)
本章我们学习Rosenfeld细化算法,参考资料:http://yunpan.cn/QGRjHbkLBzCrn 在开始学习算法之前,我们先看下连通分量,以及4连通性,8连通性的概念: http://w ...
- OpenCV学习(15) 细化算法(3)
本章我们学习一下Hilditch算法的基本原理,从网上找资料的时候,竟然发现两个有很大差别的算法描述,而且都叫Hilditch算法.不知道那一个才是正宗的,两个算法实现的效果接近,第一种算 ...
- OpenCV学习(21) Grabcut算法详解
grab cut算法是graph cut算法的改进.在理解grab cut算之前,应该学习一下graph cut算法的概念及实现方式. 我搜集了一些graph cut资料:http://yunpan. ...
- OpenCV学习(18) 细化算法(6)
本章我们在学习一下基于索引表的细化算法. 假设要处理的图像为二值图,前景值为1,背景值为0. 索引表细化算法使用下面的8邻域表示法: 一个像素的8邻域,我们可以用8位二进制表示,比如下面的8邻域,表示 ...
- OpenCV 1 图像分割--分水岭算法代码
// watershed_test20140801.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" // // ch9_watershed ...
- OpenCV学习(19) 细化算法(7)
最后再来看一种通过形态学腐蚀和开操作得到骨架的方法.http://felix.abecassis.me/2011/09/opencv-morphological-skeleton/ 代码非常简单: v ...
- OpenCV学习(17) 细化算法(5)
本章我们看下Pavlidis细化算法,参考资料http://www.imageprocessingplace.com/downloads_V3/root_downloads/tutorials/con ...
随机推荐
- C++快速文件输入输出
转载请注明: 仰望高端玩家的小清新 http://www.cnblogs.com/luruiyuan/ C语言可以获得接近汇编的性能,而输入输出常常是最为耗时的过程,因此可以使用 C 语言中的 fre ...
- Vijos1448 校门外的树 [树状数组]
题目传送门 校门外的树 描述 校门外有很多树,有苹果树,香蕉树,有会扔石头的,有可以吃掉补充体力的……如今学校决定在某个时刻在某一段种上一种树,保证任一时刻不会出现两段相同种类的树,现有两个操作:K= ...
- 自定义寄存器出现error C142: 'SFR': invalid base address
今天打算自定义一个.H文件来写写代码.自定义寄存器的时候发现出现这样的问题7816.H(5): error C142: 'SFR': invalid base address. 下面是我自定义的寄存器 ...
- /.nav-tabs :是普通标签页 .nav-pills:胶囊式标签页 action ;默认的激活项,给<li>加默认显示的是哪个标签页内容 .nav是标签页的一个基类,给ul加 .nav-stacked: 垂直排列BootStrap
<meta name="viewport" content="with=device-width, initial-scale=1, user-scalabe=no ...
- 备份Kylin的Metadata
元数据是Kylin中最重要的数据之一,备份元数据时运维工作中一个至关重要的环节.只有这样,在由于误操作导致整个Kylin服务或某个Cube异常时,才能将Kylin快速从备份中恢复出来. Kylin组织 ...
- SpringBoot学习(三)
一.单个 controller 范围的异常处理 package com.xxx.secondboot.web; import org.springframework.web.bind.annotati ...
- 深入理解javascript作用域系列第二篇
前面的话 大多数时候,我们对作用域产生混乱的主要原因是分不清楚应该按照函数位置的嵌套顺序,还是按照函数的调用顺序进行变量查找.再加上this机制的干扰,使得变量查找极易出错.这实际上是由两种作用域工作 ...
- java 安全 技术
韩梦飞沙 韩亚飞 313134555@qq.com yue31313 han_meng_fei_sha 加密对应的类 是 Cipher ,意思 是加密的意思.这个类 在 javax.cryp ...
- luogu P1011 车站
题目描述 火车从始发站(称为第1站)开出,在始发站上车的人数为a,然后到达第2站,在第2站有人上.下车,但上.下车的人数相同,因此在第2站开出时(即在到达第3站之前)车上的人数保持为a人.从第3站起( ...
- [AtCoder-ARC073F]Many Moves
题目大意: 有一排n个格子和2枚硬币. 现在有q次任务,每一次要你把其中一枚硬币移到x的位置上,移动1格的代价是1. 两枚硬币不能同时移动,任务必须按次序完成. 现在告诉你两枚硬币初始状态所在的位置a ...