two Pass方法连通域检测
原理:
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方法连通域检测的更多相关文章
- OpenCV: 图像连通域检测的递归算法
序言:清除链接边缘,可以使用数组进行递归运算; 连通域检测的递归算法是定义级别的检测算法,且是无优化和无语义失误的. 同样可用于寻找连通域 void ClearEdge(CvMat* MM,CvPoi ...
- 图像连通域检测的2路算法Code
本文算法描述参考链接:http://blog.csdn.net/icvpr/article/details/10259577 两遍扫描法: (1)第一次扫描: 访问当前像素B(x,y),如果B(x,y ...
- 使用dlib自带的面向梯度直方图(HOG)和线性分类器方法来检测人脸
之前使用opencv里面CascadeClassifier(级联分类器)来识别人脸, 下面使用dlib库来实现人脸识别. dlib是一个开源的库,它包含了很多内容有机器学习,图像处理,数值算法等等. ...
- 一种用单片机AD采样方式来检测交流市电电压的方法
下面介绍一种用单片机AD采样的方式检测市电电压的方法 要检测交流市电的电压,通常有两种方法 一.通过频繁的采样后再求平均值来获得实际电压值 二.通过采样交流市电的峰值,再通过算法得出实际电压值 这里 ...
- Android手机安全软件的恶意程序检测靠谱吗--LBE安全大师、腾讯手机管家、360手机卫士恶意软件检测方法研究
转载请注明出处,谢谢. Android系统开放,各大论坛活跃,应用程序分发渠道广泛,这也就为恶意软件的传播提供了良好的环境.好在手机上安装了安全软件,是否能有效的检测出恶意软件呢?下边针对LBE安全大 ...
- Spring Assert主张 (参议院检测工具的方法-主张)
Web 收到申请表格提交的数据后都需要对其进行合法性检查,假设表单数据是不合法的,该请求将被拒绝.分类似的,当我们写的类方法,该方法还经常需要组合成参 法国检查.假设参议院不符合要求,方法通过抛出异常 ...
- android 检测是否插入U盘方法之一
本方法是检测文件/proc/partitions. import java.io.*; File Usbfile = new File("/proc/partitions");if ...
- Android root检测方法小结
转载目的,之前主要应用这里的原理解决了,手机被某个APP检测为root过的手机的问题,记录后续可能参考. 出于安全原因,我们的应用程序不建议在已经root的设备上运行,所以需要检测是否设备已经root ...
- VC++ 内存泄露与检测的一种方法
本文介绍,当VC++或者MFC程序,出现内存泄露时,如何快速定位的方法,这种方法有一定的局限性,在注意事项中会给出的. MFC程序 当MFC程序出现内存泄露时,退出程序时的VS调试输出 ...
随机推荐
- detach() 与remove()
detach() 与remove()区别,在于remove()掉后,就没有啦,添加的事件也没有啦,后者还有啊,可以保留的哦,虽然 $("div").click(function() ...
- windows64 系统下安装Nodejs
1.nodejs安装: 版本号: node-v8.9.3-x64 检测安装成功:(这个版本已经集成了npm) 2.npm作为一个NodeJS的模块管理,先配置npm的全局模块的存放路径以及cache的 ...
- vue2.0 项目build后资源文件报错404的解决方案
当vue项目build后,我们会看到css.js报错404的问题: 那我们就去找错误原因吧. 首先,查看build后的dist文件目录 可以看出,js.css在index.html的同级目录下: 然后 ...
- 骗子网站,X毛都没有,骗我九十九
前言 这几天在A市和B市奔波着,眼瞅着自己就要毕业了,必须得出来找份工作了. 和小伙伴在A市兜兜转转了几天,要不就是不合适没下文,要不就是给了offer,工资是在太低.心很累,然后就下B市了,看看B市 ...
- 使用腾讯云无服务器云函数(SCF)分析天气数据
欢迎大家前往云+社区,获取更多腾讯海量技术实践干货哦~ 作者:李想 无服务器云函数(SCF)是腾讯云提供的Serverless执行环境,也是国内首款FaaS(Function as a Service ...
- findhex
FindPattern(hD3D, 0x128000, (PBYTE)"\xC7\x06\x00\x00\x00\x00\x89\x86\x00\x00\x00\x00\x89\x86&qu ...
- PE文件详解(四)
本文转自小甲鱼的PE文件详解系列原文传送门 到此为止,小甲鱼和大家已经学了许多关于 DOS header 和 PE header 的知识.接下来就该轮到SectionTable (区块表,也成节表). ...
- 用call和ret实现子程序
ret和call是另外两种转移指令,它们与jmp的主要区别是,它们还包含入栈和出栈的操作.具体的原理如下: ret操作相当于:pop ip(直接将栈顶元素赋值给ip寄存器) call s的操作相当于: ...
- 3、ABPZero系列教程之拼多多卖家工具 项目修改及优化
本篇内容杂而简单,不需要多租户.不需要多语言.使用MPA(多页面).页面加载速度提升…… 刚登录系统会看到如下界面,这不是最终想要的效果,以下就一一来修改. 不需要多租户 AbpZeroTemplat ...
- 在树莓派上编译安装golang环境
请看我在掘金的文章