8方向连通域统计——two-pass算法(用于图像斑块数统计)

    • 问题描述
    • 连通域标记问题
    • Two-Pass算法
      • First Pass
      • Second Pass
    • Python实现
  • 例子

问题描述

现有一幅单通道灰度图像,图中像素共有0,1两种取值(取值代表类别代号,与算法无关)。现欲统计:每种取值的像素在图中构成的“斑块”的数目。斑块类似连通域的概念,这里我们定义像素数大于4的连通域才被算作一个斑块。

这个问题可以借助连通域标记算法解决。

连通域标记问题

连通域标记(Connected Component Labelling)问题, 主要有Two-Pass和Seed-Filling两种算法。本文介绍Two-Pass算法。

逐像素遍历图像,根据周围邻居像素的标签来给当前像素打标签。然后进行二次遍历,将同在一个斑块内的几种标签标记为一样(一个斑块内的几种标签,即等效标签,存储在并查集中)。

Two-Pass算法

只需要遍历两遍就可以完成标记。

First Pass

遍历每一个像素,如果像素p的值不为0,则考察它左上方的4个邻居的值。

  • 如果邻居的值均为0,则给他打上标签(自增的,label_counter)。
  • 如果邻居中存在不为0的值,取其中的最小值赋给p。随后利用并查集,把邻居的各种取值都建立联系(认定为同一个连通域)。

比如在下图中,像素p(红色块)的值不为0,考察其邻居的值,把2赋给p,同时把2和3标记为等价(在Union-Find set中,2和3有公共的根节点)。

Second Pass

遍历每一个非0的像素,利用建好的并查集的find方法,把每一个像素的取值设为对应根节点的值。

Python实现

import numpy as npclass UnionFind:def __init__(self, n):"""长度为n的并查集"""self.uf = [-1] * (n + 1)  # 列表0位置空出self.sets_count = n  # 判断并查集里共有几个集合, 初始化默认互相独立def find(self, p):"""查找p的根结点(祖先)"""r = p  # 初始pwhile self.uf[p] > 0:p = self.uf[p]while r != p:  # 路径压缩, 把搜索下来的结点祖先全指向根结点self.uf[r], r = p, self.uf[r]return pdef union(self, p, q):"""连通p,q 让q指向p"""proot = self.find(p)qroot = self.find(q)if proot == qroot:returnelif self.uf[proot] > self.uf[qroot]:  # 负数比较, 左边规模更小self.uf[qroot] += self.uf[proot]self.uf[proot] = qrootelse:self.uf[proot] += self.uf[qroot]self.uf[qroot] = prootself.sets_count -= 1                   # 连通后集合总数减一def is_connected(self, p, q):"""判断pq是否已经连通"""return self.find(p) == self.find(q)  # 即判断两个结点是否是属于同一个祖先def im_binary(data: np.ndarray, target_value: int):return np.where(data == target_value, 1, 0)def im_padding(data: np.ndarray):return np.pad(data, ((1, 1), (1, 1)), 'constant')def first_pass(data, uf_set):offsets = [[-1, -1], [0, -1], [-1, 1], [-1,  0]]label_counter = 2for y in range(1, data.shape[0]-1):for x in range(1, data.shape[1]-1):if data[y, x] == 0:continueneighbor = []for offset in offsets:if data[y + offset[0], x + offset[1]] != 0:neighbor.append(data[y + offset[0], x + offset[1]])neighbor = np.unique(neighbor)if len(neighbor) == 0:data[y, x] = label_counterlabel_counter += 1elif len(neighbor) == 1:data[y, x] = neighbor[0]else:# 邻居内有多重label, 这种情况要把最小值赋给data[y, x], 同时建立值之间的联系.data[y, x] = neighbor[0]for n in neighbor:uf_set.union(int(neighbor[0]), int(n))def second_pass(data, uf_set):for y in range(data.shape[0]):for x in range(data.shape[1]):if data[y, x] != 0:data[y, x] = uf_set.find(int(data[y, x]))
  • im_binary() 方法把一个图像中等于target_value的值置为1,其余的置为0,实现二值化。
  • im_padding() 把图片周围补一圈0,这样才能用下面的算法。

例子

输入是一个植被指数(NDVI)单通道图像。希望把NDVI值大于0.1的部分设为1,小于的部分设为0,再计算1构成的连通域(图斑)的数量,并实现可视化。

def count_patch(data, get_img=False):# 统计某一种类别的图斑数. 返回各个图斑的像素数,和结果图.ufSet = UnionFind(1000000)first_pass(data, ufSet)second_pass(data, ufSet)count_dic = {}for y in range(1, data.shape[0] - 1):for x in range(1, data.shape[1] - 1):if data[y, x] in count_dic:count_dic[data[y, x]] += 1else:count_dic[data[y, x]] = 1count_dic.pop(0)if get_img:return list(count_dic.values()), dataelse:return list(count_dic.values())

结果图如下(同一连通域被标记成一种颜色):

8方向连通域统计——two-pass算法(用于图像斑块数统计)相关推荐

  1. C++Poisso statistics泊松统计的实现算法(附完整源码)

    C++Poisso statistics泊松统计的实现算法 C++Poisso statistics泊松统计的实现算法完整源码(定义,实现,main函数测试) C++Poisso statistics ...

  2. 自然语言处理(NLP)-统计句法分析(CKY算法用于PCFG下的句法分析)

    1.先解释何为CFG及PCFG: 一个栗子: 2.CKY算法(或称CYK算法) "在计算机科学领域,CYK算法(也称为Cocke–Younger–Kasami算法)是一种用来对 上下文无关文 ...

  3. PaSS:用于 PacBio 测序的测序模拟器

    PaSS:用于 PacBio 测序的测序模拟器 张文敏, 1 本佳, 1魏朝春1 , 2 作者信息 文章注释 版权和许可信息 免责声明 本文已被PMC 中的其他文章引用. 相关数据 补充材料 数据可用 ...

  4. SIFT算法总结:用于图像搜索

    原始文章链接:http://bubblexc.com/y2011/163/ 原文链接:http://blog.csdn.net/cserchen/article/details/5606859 关于三 ...

  5. 蚁群算法用于航路规划的matlab简单实现

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一.蚁群算法 二.背景 三.算法原理 四.算法步骤 五.程序实现 主函数 以下为用到的定义的函数 1.伪随机规则 2. ...

  6. 大数据算法课程笔记1:寻找中值算法之随机选取,中值的中值,One Pass算法

    大数据算法的课程笔记,包括四种中值搜索算法.包括最简单的先搜索后检索,平均算法复杂度为O(N)的简单随机选取算法,确定性的中值的中值算法,大概率返回中值的one pass算法. 1. 最简单的方法:先 ...

  7. Matlab实现连通域标记算法求图像连通域

    Matlab实现连通域标记算法求图像连通域 连通域 连通域标记算法 连通域 连通区域(Connected Component)一般是指图像中具有相同像素值且位置相邻的前景像素点组成的图像区域(Regi ...

  8. C++计算实时输入数据的统计信息实现算法(附完整源码)

    C++计算实时输入数据的统计信息实现算法 C++计算实时输入数据的统计信息实现算法完整源码(定义,实现,main函数测试) C++计算实时输入数据的统计信息实现算法完整源码(定义,实现,main函数测 ...

  9. 开源目标检测算法用于交通标志检测全方位评估

    (欢迎关注"我爱计算机视觉"公众号,一个有价值有深度的公众号~) 交通标志检测在自动驾驶.汽车主动安全中应用非常重要,通用的目标检测算法可以通过微调网络的方式直接用于交通标志检测. ...

最新文章

  1. Windows 环境 Tomcat 的 HTTPS 单向认证和双向认证的配置
  2. c语言中if—else的配对问题
  3. sigmoid函数(Logistic函数)
  4. 欲瘦其包,必先探清其底细
  5. c++类的静态成员特性
  6. SAP Fiori Launchpad的后台配置路径
  7. 八皇后问题python_python八皇后问题的解决方法
  8. 计算机辅助电话调查系统,基于XML题型定制的计算机辅助电话调查系统问卷设计与实现...
  9. 图片上传,CheckBox等用户控件的应用代码
  10. python运算符及优先级顺序
  11. 她经济正在替代男性,成为体育产业的新支柱?
  12. 按键精灵助手之按钮响应事件
  13. Excel画函数图像
  14. 叶问【转自知数堂微信公众号】
  15. 一些格言,希望自己铭记在心
  16. nginx详细文档 – 安装配置,深入源码,模块编写,编译器参数,系统函数
  17. win10微软图标点击无反应_win10系统任务栏开始菜单等系统图标点击无反应的解决方法...
  18. flutter显示图标_flutter 引入第三方 Icon 图标(以阿里图标库为例)
  19. Android 中在Android studio2.3中 NASA 的World Wind地图应用
  20. 汽车UDS诊断之通过标识符写入数据服务(0x2E)深度剖析

热门文章

  1. TCP流量控制与拥塞控制(重要)
  2. 选择排序法:思路清晰
  3. Cell Biolabs——细胞研究丨细胞信号通路和蛋白质生物学
  4. 以太坊人来人往:已有7位创始成员离开
  5. .NET中的托管资源与非托管资源
  6. FZU 2239 Daxia Yayamao's problem 斜率优化
  7. python如何输入三引号_python三引号如何输入
  8. 使用css实现二级导航栏
  9. 百度-欢聚集团Joyy面经:22届 - Java开发实习生
  10. 背景位置——混合单位