Connected_Component Labelling(联通区域标记算法) C++实现
// Connected-Component Labelling.cpp : 定义控制台应用程序的入口点。
//如有是使用,请务必注明引用出处网站:http://www.cnblogs.com/AmatVictorialCuram/p/3524877.html,杜绝一切抄袭剽窃行为!//
// 11111111111.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <iomanip>
#include <vector>
#include <algorithm>
#include <stdlib.h>
#include <time.h>
#define M 10
#define N 10
using namespace std;
int minLabel(int a,int b)
{
return (a>b)?b:a;
}
int maxLabel(int a,int b)
{
return (a<b)?b:a;
}
int _tmain(int argc, _TCHAR* argv[])
{
int data[M][N];
//int data[M][N]=
//{
// 0,0,0,0,1,1,1,0,0,0,
// 0,0,0,1,1,1,1,1,0,0,
// 0,0,0,1,1,1,1,1,0,0,
// 100,0,0,0,1,1,1,0,0,0,
// 0,0,0,0,0,1,0,0,0,0,
// 0,0,0,0,0,0,0,0,0,0,
// 0,0,0,0,2,2,2,2,0,0,
// 0,0,0,0,2,2,2,2,0,0,
// 0,0,0,0,2,2,2,2,0,0,
// 0,0,0,0,0,0,0,0,0,0
//};
int dataLabel[M][N];//存储像素标记的矩阵,全部初始化为0.
int i=0,j=0;//用来遍历所有元素的循环变量
//int nIndex=0;//斑块数目索引
int nNeighbour=0;//Connected像素的个数初始化为0
int t=0;
int replace=0;//测试发生标记替换的次数
cout<<"输出原数组data[M][N]:"<<endl;
srand(time(NULL));
for(i=0;i<M;i++)
{
for(j=0;j<N;j++)
{
//srand(time(0));
data[i][j]=rand()%2;
cout<<setw(3)<<data[i][j];
dataLabel[i][j]=M*N;//标签数组的所有值均初始化为0
}
cout<<endl;
}
dataLabel[0][0]=1;//把左上角的第一个标签赋值为1
int indexcolor=1;
for(i=0;i<M;i++)
{
for(j=0;j<N;j++)
{
if(i==0)
{
if(j==0)
continue;
if(data[i][j]==data[i][j-1])
dataLabel[i][j]=dataLabel[i][j-1];
else
{
dataLabel[i][j]=++indexcolor;
}
continue;
}
if(j==0)
{
if(data[i][j]==data[i-1][j])
{
if(dataLabel[i-1][j]<dataLabel[i][j])
dataLabel[i][j]=dataLabel[i-1][j];
}
if(data[i][j]==data[i-1][j+1])
{
if(dataLabel[i-1][j+1]<dataLabel[i][j])
dataLabel[i][j]=dataLabel[i-1][j+1];
}
if(dataLabel[i][j]==M*N)
{
dataLabel[i][j]=++indexcolor;
}
continue;
}
//if(edgeCheckL(i,j) && data[i][j]==data[i][j-1])//左边的,
if(j>0 && data[i][j]==data[i][j-1])
{
if(dataLabel[i][j-1]<dataLabel[i][j])
dataLabel[i][j]=dataLabel[i][j-1];
}
//if(edgeCheckLU(i,j) && data[i][j]==data[i-1][j-1])//左上角的
if((i>0 && j>0)&& data[i][j]==data[i-1][j-1])
{
if(dataLabel[i-1][j-1]<dataLabel[i][j])
dataLabel[i][j]=dataLabel[i-1][j-1];
}
//if(edgeCheckU(i,j) && data[i][j]==data[i-1][j])//上面的
if(i>0 && data[i][j]==data[i-1][j])
{
if(dataLabel[i-1][j]<dataLabel[i][j])
dataLabel[i][j]=dataLabel[i-1][j];
}
//if(edgeCheckUR(i,j) && data[i][j]==data[i-1][j+1])//右上角的
if((i>0 && j<M-1) && data[i][j]==data[i-1][j+1])
{
if(dataLabel[i-1][j+1]<dataLabel[i][j])
dataLabel[i][j]=dataLabel[i-1][j+1];
}
if(dataLabel[i][j]==M*N)
dataLabel[i][j]=++indexcolor;
}
}
cout<<"输出第一次标记数组"<<endl<<endl;
for(i=0;i<M;i++)
{
for(j=0;j<N;j++)
{
cout<<setw(3)<<dataLabel[i][j];
}
cout<<endl;
}
cout<<"合并首次生成的标签数组。。。。"<<endl<<endl;
//合并:像素值相同,但是标签不同,就把标签值大的变为小的。
for(i=0;i<M;i++)//行
{
for(j=0;j<N;j++)//列
{
if(i==0)//第0行,只判左边的!
{
if(j==0)//第一个元素
{
j=1;//跳过第一个元素,直接从第二个元素:data[0][1]判断
//判断并执行合并:
if(data[i][j-1]==data[i][j] && dataLabel[i][j-1]!=dataLabel[i][j])//像素值相同 && 标签不同:合并!
{
//把所有的大标签替换为当前两个标签中的一个较小的值
//执行一次遍历
//cout<<"第"<<i<<"行"<<"第"<<j<<"列:"<<"第"<<++replace<<"次替换"<<endl;
for(int m=0;m<M;m++)
{
for(int n=0;n<N;n++)
{//把大的标签替换为小的标签
if(dataLabel[m][n]==maxLabel(dataLabel[i][j],dataLabel[i][j-1]))
{
dataLabel[m][n]=minLabel(dataLabel[i][j],dataLabel[i][j-1]);
}
}
}
}
}
}
else//非0行
{
if(j==0)//第0列,但不是第一行的:只判断上、右上两个方向
{
if(data[i-1][j]==data[i][j] && dataLabel[i-1][j]!=dataLabel[i][j])//像素值相同 && 标签不同:合并!
{
//把所有的大标签替换为当前两个标签中的一个较小的值
//执行一次遍历
//cout<<"第"<<i<<"行"<<"第"<<j<<"列:"<<"第"<<++replace<<"次替换"<<endl;
for(int m=0;m<M;m++)
{
for(int n=0;n<N;n++)
{//把大的标签替换为小的标签
if(dataLabel[m][n]==maxLabel(dataLabel[i][j],dataLabel[i-1][j]))
{
dataLabel[m][n]=minLabel(dataLabel[i][j],dataLabel[i-1][j]);
}
}
}
}
if(data[i-1][j+1]==data[i][j] && dataLabel[i-1][j=1]!=dataLabel[i][j])//像素值相同 && 标签不同:合并!
{
//把所有的大标签替换为当前两个标签中的一个较小的值
//执行一次遍历
//cout<<"第"<<i<<"行"<<"第"<<j<<"列:"<<"第"<<++replace<<"次替换"<<endl;
for(int m=0;m<M;m++)
{
for(int n=0;n<N;n++)
{//把大的标签替换为小的标签
if(dataLabel[m][n]==maxLabel(dataLabel[i][j],dataLabel[i-1][j+1]))
{
dataLabel[m][n]=minLabel(dataLabel[i][j],dataLabel[i-1][j+1]);
}
}
}
}
}
else if(j==M-1)//非0行且最后一列的:判断左、左上、上三个方向
{
if(data[i][j-1]==data[i][j] && dataLabel[i][j-1]!=dataLabel[i][j])//像素值相同 && 标签不同:合并!
{
//把所有的大标签替换为当前两个标签中的一个较小的值
//执行一次遍历
//cout<<"第"<<i<<"行"<<"第"<<j<<"列:"<<"第"<<++replace<<"次替换"<<endl;
for(int m=0;m<M;m++)
{
for(int n=0;n<N;n++)
{//把大的标签替换为小的标签
if(dataLabel[m][n]==maxLabel(dataLabel[i][j],dataLabel[i][j-1]))
{
dataLabel[m][n]=minLabel(dataLabel[i][j],dataLabel[i][j-1]);
}
}
}
}
if(data[i-1][j-1]==data[i][j] && dataLabel[i-1][j-1]!=dataLabel[i][j])//像素值相同 && 标签不同:合并!
{
//把所有的大标签替换为当前两个标签中的一个较小的值
//执行一次遍历
//cout<<"第"<<i<<"行"<<"第"<<j<<"列:"<<"第"<<++replace<<"次替换"<<endl;
for(int m=0;m<M;m++)
{
for(int n=0;n<N;n++)
{//把大的标签替换为小的标签
if(dataLabel[m][n]==maxLabel(dataLabel[i][j],dataLabel[i-1][-1]))
{
dataLabel[m][n]=minLabel(dataLabel[i][j],dataLabel[i-1][j-1]);
}
}
}
}
if(data[i-1][j]==data[i][j] && dataLabel[i-1][j]!=dataLabel[i][j])//像素值相同 && 标签不同:合并!
{
//把所有的大标签替换为当前两个标签中的一个较小的值
//执行一次遍历
//cout<<"第"<<i<<"行"<<"第"<<j<<"列:"<<"第"<<++replace<<"次替换"<<endl;
for(int m=0;m<M;m++)
{
for(int n=0;n<N;n++)
{//把大的标签替换为小的标签
if(dataLabel[m][n]==maxLabel(dataLabel[i][j],dataLabel[i-1][j]))
{
dataLabel[m][n]=minLabel(dataLabel[i][j],dataLabel[i-1][j]);
}
}
}
}
}
else//非0行且(既不是第一列,也不是最后一列的):判断左、左上、上、右上四个方向
{
if(data[i][j-1]==data[i][j] && dataLabel[i][j-1]!=dataLabel[i][j])//像素值相同 && 标签不同:合并!
{
//把所有的大标签替换为当前两个标签中的一个较小的值
//执行一次遍历
//cout<<"第"<<i<<"行"<<"第"<<j<<"列:"<<"第"<<++replace<<"次替换"<<endl;
for(int m=0;m<M;m++)
{
for(int n=0;n<N;n++)
{//把大的标签替换为小的标签
if(dataLabel[m][n]==maxLabel(dataLabel[i][j],dataLabel[i][j-1]))
{
dataLabel[m][n]=minLabel(dataLabel[i][j],dataLabel[i][j-1]);
}
}
}
}
if(data[i-1][j-1]==data[i][j] && dataLabel[i-1][j-1]!=dataLabel[i][j])//像素值相同 && 标签不同:合并!
{
//把所有的大标签替换为当前两个标签中的一个较小的值
//执行一次遍历
//cout<<"第"<<i<<"行"<<"第"<<j<<"列:"<<"第"<<++replace<<"次替换"<<endl;
for(int m=0;m<M;m++)
{
for(int n=0;n<N;n++)
{//把大的标签替换为小的标签
if(dataLabel[m][n]==maxLabel(dataLabel[i][j],dataLabel[i-1][-1]))
{
dataLabel[m][n]=minLabel(dataLabel[i][j],dataLabel[i-1][j-1]);
}
}
}
}
if(data[i-1][j]==data[i][j] && dataLabel[i-1][j]!=dataLabel[i][j])//像素值相同 && 标签不同:合并!
{
//把所有的大标签替换为当前两个标签中的一个较小的值
//执行一次遍历
//cout<<"第"<<i<<"行"<<"第"<<j<<"列:"<<"第"<<++replace<<"次替换"<<endl;
for(int m=0;m<M;m++)
{
for(int n=0;n<N;n++)
{//把大的标签替换为小的标签
if(dataLabel[m][n]==maxLabel(dataLabel[i][j],dataLabel[i-1][j]))
{
dataLabel[m][n]=minLabel(dataLabel[i][j],dataLabel[i-1][j]);
}
}
}
}
if(data[i-1][j+1]==data[i][j] && dataLabel[i-1][j+1]!=dataLabel[i][j])//像素值相同 && 标签不同:合并!
{
//把所有的大标签替换为当前两个标签中的一个较小的值
//执行一次遍历
//cout<<"第"<<i<<"行"<<"第"<<j<<"列:"<<"第"<<++replace<<"次替换"<<endl;
for(int m=0;m<M;m++)
{
for(int n=0;n<N;n++)
{//把大的标签替换为小的标签
if(dataLabel[m][n]==maxLabel(dataLabel[i][j],dataLabel[i-1][j+1]))
{
dataLabel[m][n]=minLabel(dataLabel[i][j],dataLabel[i-1][j+1]);
}
}
}
}
}
}
}
}
t=1;
cout<<"输出合并后的标签数组dataLabel:"<<endl;
for(i=0;i<M;i++)
{
for(j=0;j<N;j++)
{
if(dataLabel[i][j]>t)
{
t++;
}
cout<<setw(3)<<dataLabel[i][j];
}
cout<<endl;
}
cout<<endl<<"t="<<t<<endl;
return 0;
}
Connected_Component Labelling(联通区域标记算法) C++实现的更多相关文章
- OpenCV:二值图像连通区域分析与标记算法实现
http://blog.csdn.net/cooelf/article/details/26581539?utm_source=tuicool&utm_medium=referral Open ...
- JVM GC-----3、垃圾标记算法(二)
在上一篇文章中,介绍了在GC机制中,GC是以什么标准判定对象可以被标记的,以及最有效最常用的可达性分析法.今天介绍另外一种非常常用的标记算法,它的应用面也相当广泛.这就是:引用计数法 Referenc ...
- Java虚拟机(三)垃圾标记算法与Java对象的生命周期
前言 这一节我们来简单的介绍垃圾收集器,并学习垃圾标记的算法:引用计数算法和根搜索算法,为了更好的理解根搜索算法,会在文章的最后介绍Java对象在虚拟机中的生命周期. 1.垃圾收集器概述 垃圾收集器( ...
- 百度地图API实现多区域标记
最近遇到一个业务就是需要需要在地图上标记多个区域.一般餐饮业做外卖的,配送范围一般是多区域的,那么在地图上标记配送范围的时候就需要能标记多个区域.长话短说,最初的实现原型的截图如下:
- 区域检测算法-MSERs
区域检测算法-MSERs:最大稳定极值区域 参考书籍——<图像局部不变性特征与描述>王永明.王贵锦著 MSER最大极值稳定区域的提取步骤:1.像素点排序 2.极值区域生成 3.稳定 ...
- hdu2767 Proving Equivalences,有向图强联通,Kosaraju算法
点击打开链接 有向图强联通,Kosaraju算法 缩点后分别入度和出度为0的点的个数 answer = max(a, b); scc_cnt = 1; answer = 0 #include<c ...
- JVM垃圾收集算法之标记算法
前言 总所周知,jvm的垃圾收集算法一般包括标记.清除.整理三个阶段,最近在看了有关于垃圾收集的标记算法,记录一下自己的理解. 垃圾收集中标记算法有两种:一种是引用计数法,一种是根搜索算法. 引用记数 ...
- JVM(八),垃圾回收标记算法
八.垃圾回收标记算法 1.对象被判定成垃圾的标准 没有被其他对象引用 2.判断对象是否为垃圾的算法 (1)引用计数法 优点and缺点 (2)可达性分析算法
- POJ 2186-Popular Cows (图论-强联通分量Korasaju算法)
题目链接:http://poj.org/problem?id=2186 题目大意:有n头牛和m对关系, 每一对关系有两个数(a, b)代表a牛认为b牛是“受欢迎”的,且这种关系具有传递性, 如果a牛认 ...
随机推荐
- 一款基于jQuery的支持鼠标拖拽滑动焦点图
记得之前我们分享过一款jQuery全屏广告图片焦点图,图片切换效果还不错.今天我们要分享另外一款jQuery焦点图插件,它的特点是支持鼠标拖拽滑动,所以在移动设备上使用更加方便,你只要用手指滑动屏幕即 ...
- 把你的旧笔记本变成 Chromebook
导读 Linux 之年就在眼前.根据报道,Google 在 2016 年第一季度卖出了比苹果卖出的 Macbook 更多的 Chromebook.并且,Chromebook 即将变得更加激动人心.在 ...
- vim的列编辑操作
转载:http://www.cnblogs.com/xiaowant/articles/1992923.html 删除列 1.光标定位到要操作的地方. 2.CTRL+v 进入“可视 块”模式,选取这一 ...
- LeetCode44 Wildcard Matching
题目: Implement wildcard pattern matching with support for '?' and '*'. '?' Matches any single charact ...
- Pandas系列教程——写在前面
之前搜pandas资料,发现互联网上并没有成体系的pandas教程,于是乎突然有个爱迪页儿,打算自己把官网的文档加上自己用pandas的理解,写成一个系列的教程, 巩固自己,方便他人 接下来就干这件事 ...
- EMS电子面单接口对接使用-免费版
快递鸟电子面单接口,可一次对接15家快递公司, 无需和每一家快递公司做对接.支持快递有四通一达.顺丰.EMS.宅急送.德邦.优速等15家快递公司,对顺丰有电子面单服务需求的可以选择顺丰自有的电子面单或 ...
- 1.6.1 什么是 Indexing
这部分描述了建立索引的过程:添加内容到solr索引中,如果有需要,修改内容或者删除它.通过添加内容到索引里边,我们使其内容可以搜索. solr索引能够接收不同来源的数据,xml文件,逗号分隔值的(CV ...
- ListView的addAll方法
add是将传入的参数作为当前List中的一个Item存储,即使你传入一个List也只会另当前的List增加1个元素addAll是传入一个List,将此List中的所有元素加入到当前List中,也就是当 ...
- Android(java)学习笔记265:Android线程形态之 HandlerThread
1. HandlerThread Android HandlerThread 完全解析 Handler与HandlerThread区别,HandlerThread应用(对比AsyncTask) 备注 ...
- 沈逸老师PHP魔鬼特训笔记(6)--巫术与骨架
PHP最牛逼的特性之一除了懒人函数,还有一些魔法函数. 首先我们来认识下__tostring,通过一个巫术方法,我们吧实例转化过后的类,直接当字符串输出.结合我们前面所做的功能,我们在类里面加上这个函 ...