原理:

Two-Pass方法检测连通域的原理可参见这篇博客:http://blog.csdn.net/lichengyu/article/details/13986521

参考下面动图,一目了然。

代码:

代码中标记图的数据类型要注意,如果first pass中标记数多于255,就不要用uchar类型,我直接设置为int类型。

 #include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <map>
#include <cassert>
#include <iostream> using namespace std; const int max_size = ;
int parent[max_size] = { }; // 找到label x的根节点
int Find(int x, int parent[])
{
assert(x < max_size);
int i = x;
while ( != parent[i])
i = parent[i];
return i;
} // 将label x 和 label y合并到同一个连通域
void Union(int x, int y, int parent[])
{
assert(x < max_size && y < max_size);
int i = x;
int j = y;
while ( != parent[i])
i = parent[i];
while ( != parent[j])
j = parent[j];
if (i != j)
parent[i] = j;
} cv::Mat twoPassConnectComponent(cv::Mat &binaryImg)
{
int imgW = binaryImg.cols;
int imgH = binaryImg.rows;
int channel = binaryImg.channels();
int type = binaryImg.type();
// first pass
int label = ; cv::Mat dst = cv::Mat::zeros(cv::Size(imgW, imgH), CV_32SC1);
for (int y = ; y < imgH; y++)
{
for (int x = ; x < imgW; x++)
{
if (binaryImg.at<uchar>(y, x) != )
{
int left = (x - < ) ? : dst.at<int>(y, x - );
int up = (y - < ) ? : dst.at<int>(y - , x); if (left != || up != )
{
if (left != && up != )
{
dst.at<int>(y, x) = min(left, up);
if (left <= up)
Union(up, left, parent);
else if (up<left)
Union(left, up, parent);
}
else
dst.at<int>(y, x) = max(left, up);
}
else
{
dst.at<int>(y, x) = ++label;
}
}
}
} //second pass
for (int y = ; y < imgH; y++)
{
for (int x = ; x < imgW; x++)
{
if (binaryImg.at<uchar>(y, x) != )
dst.at<int>(y, x) = Find(dst.at<int>(y, x), parent);
}
} return dst;
} cv::Scalar getRandomColor()
{
uchar r = * (rand() / (1.0 + RAND_MAX));
uchar g = * (rand() / (1.0 + RAND_MAX));
uchar b = * (rand() / (1.0 + RAND_MAX));
return cv::Scalar(b, g, r);
} cv::Mat showColorLabel(cv::Mat label)
{
int imgW = label.cols;
int imgH = label.rows;
std::map<int, cv::Scalar> colors; cv::Mat colorLabel = cv::Mat::zeros(imgH, imgW, CV_8UC3);
int *pLabel = (int*)label.data;
uchar *pColorLabel = colorLabel.data;
for (int i = ; i < imgH; i++)
{
for (int j = ; j < imgW; j++)
{
int idx = (i*imgW + j) * ;
int pixelValue = pLabel[i*imgW + j];
if (pixelValue > )
{
if (colors.count(pixelValue) <= )
{
colors[pixelValue] = getRandomColor();
}
cv::Scalar color = colors[pixelValue];
pColorLabel[idx + ] = color[];
pColorLabel[idx + ] = color[];
pColorLabel[idx + ] = color[];
}
}
} return colorLabel;
} int main()
{
// 加载图像
string imageName = "data/source_images/logo.png";
cv::Mat image = cv::imread(imageName, );
if (!image.data)
{
cout << "No image data" << endl;
getchar();
return -;
}
//转为灰度图
cv::cvtColor(image, image, CV_RGB2GRAY);
//阈值化,情景为255,背景为0
cv::Mat threshImg;
cv::threshold(image, threshImg, , , cv::THRESH_BINARY);
cv::bitwise_not(threshImg, threshImg); //连通域检测 two Pass方法标记图像
cv::Mat labelImg = twoPassConnectComponent(threshImg); //不同连通区域用不同颜色表示
cv::Mat colorLabelImg=showColorLabel(labelImg); //显示
cv::imshow("thresh", threshImg);
cv::imshow("label", labelImg*);
cv::imshow("colorLabel", colorLabelImg);
cv::waitKey();
}

结果:

使用OpenCV的logo为素材图,如下:

(1)转为灰度图然后阈值化

(2)寻找连通域

(3)不同连通区域不同颜色显示

   

   

封装后的代码见我的码云code:https://gitee.com/rxdj/twoPassMethod.git

two Pass方法连通域检测的更多相关文章

  1. OpenCV: 图像连通域检测的递归算法

    序言:清除链接边缘,可以使用数组进行递归运算; 连通域检测的递归算法是定义级别的检测算法,且是无优化和无语义失误的. 同样可用于寻找连通域 void ClearEdge(CvMat* MM,CvPoi ...

  2. 图像连通域检测的2路算法Code

    本文算法描述参考链接:http://blog.csdn.net/icvpr/article/details/10259577 两遍扫描法: (1)第一次扫描: 访问当前像素B(x,y),如果B(x,y ...

  3. 使用dlib自带的面向梯度直方图(HOG)和线性分类器方法来检测人脸

    之前使用opencv里面CascadeClassifier(级联分类器)来识别人脸, 下面使用dlib库来实现人脸识别. dlib是一个开源的库,它包含了很多内容有机器学习,图像处理,数值算法等等. ...

  4. 一种用单片机AD采样方式来检测交流市电电压的方法

    下面介绍一种用单片机AD采样的方式检测市电电压的方法  要检测交流市电的电压,通常有两种方法 一.通过频繁的采样后再求平均值来获得实际电压值 二.通过采样交流市电的峰值,再通过算法得出实际电压值 这里 ...

  5. Android手机安全软件的恶意程序检测靠谱吗--LBE安全大师、腾讯手机管家、360手机卫士恶意软件检测方法研究

    转载请注明出处,谢谢. Android系统开放,各大论坛活跃,应用程序分发渠道广泛,这也就为恶意软件的传播提供了良好的环境.好在手机上安装了安全软件,是否能有效的检测出恶意软件呢?下边针对LBE安全大 ...

  6. Spring Assert主张 (参议院检测工具的方法-主张)

    Web 收到申请表格提交的数据后都需要对其进行合法性检查,假设表单数据是不合法的,该请求将被拒绝.分类似的,当我们写的类方法,该方法还经常需要组合成参 法国检查.假设参议院不符合要求,方法通过抛出异常 ...

  7. android 检测是否插入U盘方法之一

    本方法是检测文件/proc/partitions. import java.io.*; File Usbfile = new File("/proc/partitions");if ...

  8. Android root检测方法小结

    转载目的,之前主要应用这里的原理解决了,手机被某个APP检测为root过的手机的问题,记录后续可能参考. 出于安全原因,我们的应用程序不建议在已经root的设备上运行,所以需要检测是否设备已经root ...

  9. VC++ 内存泄露与检测的一种方法

        本文介绍,当VC++或者MFC程序,出现内存泄露时,如何快速定位的方法,这种方法有一定的局限性,在注意事项中会给出的. MFC程序     当MFC程序出现内存泄露时,退出程序时的VS调试输出 ...

随机推荐

  1. JAVA NIO学习四:Path&Paths&Files 学习

    今天我们将学习NIO 的最后一章,前面大部分涉及IO 和 NIO 的知识都已经讲过了,那么本章将要讲解的是关于Path 以及Paths 和 Files 相关的知识点,以对前面知识点的补充,好了言归正传 ...

  2. Robot Framework学习笔记(三)------常用关键字介绍

    下面关键字全部由 Builtin 库提供,Builtin 为 Robot Framework 标准类库.Builtin库提供常用的关键字 1.log log 关键字就是编程语言里的"prin ...

  3. mac SecureCRT设置

    参考: http://www.2cto.com/os/201407/320292.html SecureCRT 设置 1)每次登陆都要输入密码: Global Option -> General ...

  4. PXE+kickstart网络安装CentOS7.4系统及过程中各种报错

    环境:关闭防火墙.selinux 注意:虚拟机进行网络安装的话,7.3以后的系统是需要2G以上的内存 [root@kickstart ~]# cat /etc/redhat-release CentO ...

  5. ubuntu16.04+eigen3安装

    Eigen库安装指南(两种方式)1.apt-get方式(假设默认安装到/usr/local/include里,若实际中默认安装到了/usr/include的话,可以对应替换下面命令的相应部分);运行命 ...

  6. [Spark内核] 第29课:Master HA彻底解密

    本课主题 Master HA 解析 Master HA 解析源码分享 [引言部份:你希望读者看完这篇博客后有那些启发.学到什么样的知识点] 更新中...... Master HA 解析 生产环境下一般 ...

  7. Android Studio 查看手机CPU信息

    在Android开发中,我们想要获取手机是什么CPU架构,可以通过下面方式: 1.进入adb 终端 adb shell 2.进入proc目录 cd /proc/ 3.查看cpu信息 cat cpuin ...

  8. 用 Identity Server 4 (JWKS 端点和 RS256 算法) 来保护 Python web api

    目前正在使用asp.net core 2.0 (主要是web api)做一个项目, 其中一部分功能需要使用js客户端调用python的pandas, 所以需要建立一个python 的 rest api ...

  9. Redis的key过期处理策略

    Redis中有三种处理策略:定时删除.惰性删除和定期删除. 定时删除:在设置键的过期时间的时候创建一个定时器,当过期时间到的时候立马执行删除操作.不过这种处理方式是即时的,不管这个时间内有多少过期键, ...

  10. console.log的返回值undefined

    console.log(fun());  function fun(){ console.log(1); } //////输出结果为: 1 undefined console.log(fun());  ...