OpenCV与图像处理学习九——连通区域分析算法(含代码)

OpenCV与图像处理学习九——连通区域分析算法(含代码)

  • 一、连通区域概要
  • 二、Two-Pass算法
  • 三、代码实现

一、连通区域概要

连通区域(Connected Component)一般是指图像中具有相同像素值且位置相邻的前景像素点组成的图像区域,连通区域分析是指将图像中的各个连通区域找出并标记。连通区域分析是一种在CV和图像分析处理的众多应用领域中较为常用和基本的方法。

例如: OCR识别中字符分割提取(车牌识别、文本识别、字幕识别等)、视觉跟踪中的运动前景
目标分割与提取(行人入侵检测、遗留物体检测、基于视觉的车辆检测与跟踪等)、医学图像处
理(感兴趣目标区域提取)等。

在需要将前景目标提取出来以便后续进行处理的应用场景中都能够用到连通区域分析
方法,通常连通区域分析处理的对象是一张二值化后的图像

在图像中,最小的单位是像素,每个像素周围有邻接像素,常见的邻接关系有2种: 4邻接与8邻接,如下图所示:
在这里插入图片描述
如果A与B连通, B与C连通,则A与C连通,在视觉上看来,彼此连通的点形成了一个区域,而不连通的点形成了不同的区域。这样的一个所有的点彼此连通点构成的集合,我们称为一个连通区域

我们来看一下下面这个二值化的图:
在这里插入图片描述
对于每一个前景像素,只要它的邻域中有像素也是前景,那么它们就属于一个连通区域,在这张图中,如果使用四邻域的规则,那么将可以分成三个连通区域,而使用八邻域的规则,则可以分成两个连通区域

二、Two-Pass算法

基于上述概念,我们再来学习连通区域分析算法中常用的Two-Pass算法 (两遍扫描法),正如其名,指的就是通过扫描两遍图像,将图像中存在的所有连通域找出并标记。

第一次扫描

  1. 从左上角开始遍历像素点,找到第一个像素为255(因为是二值图,只有0和255)的点,令该像素的label=1;
  2. 当该像素的左邻像素和上邻像素为无效值时,给该像素置一个新的label值, label ++,记录集合;
  3. 当该像素的左邻像素或者上邻像素有一个为有效值时,将有效值像素的label赋给该像素的label值;
  4. 当该像素的左邻像素和上邻像素都为有效值时,选取其中较小的label值赋给该像素的label值。

若一张二值图如下所示(蓝点为前景点):
在这里插入图片描述
则第一遍扫描之后记录的label如下所示:
在这里插入图片描述
通过领域像素得到label或成为领域像素得到label依据的像素点都将记录为一个集合,只有毫无联系的才会记录为不同的集合,如上图所示,前景点被分为了两个集合(橙色标记)。

第二次扫描

  1. 对每个点的label进行更新,更新为其对于其集合中最小的label
    在这里插入图片描述
    则就可以得到两个连通区域:
    在这里插入图片描述

三、代码实现

import cv2
import numpy as np# 4邻域的连通域和 8邻域的连通域
# [row, col]
NEIGHBOR_HOODS_4 = True
OFFSETS_4 = [[0, -1], [-1, 0], [0, 0], [1, 0], [0, 1]]NEIGHBOR_HOODS_8 = False
OFFSETS_8 = [[-1, -1], [0, -1], [1, -1],[-1,  0], [0,  0], [1,  0],[-1,  1], [0,  1], [1,  1]]
#第二遍扫描
def reorganize(binary_img: np.array):index_map = []points = []index = -1rows, cols = binary_img.shapefor row in range(rows):for col in range(cols):var = binary_img[row][col]if var < 0.5:continueif var in index_map:index = index_map.index(var)num = index + 1else:index = len(index_map)num = index + 1index_map.append(var)points.append([])binary_img[row][col] = numpoints[index].append([row, col])#print(binary_img)#print(points)return binary_img, points#四领域或八领域判断
def neighbor_value(binary_img: np.array, offsets, reverse=False):rows, cols = binary_img.shapelabel_idx = 0rows_ = [0, rows, 1] if reverse == False else [rows-1, -1, -1]cols_ = [0, cols, 1] if reverse == False else [cols-1, -1, -1]for row in range(rows_[0], rows_[1], rows_[2]):for col in range(cols_[0], cols_[1], cols_[2]):label = 256if binary_img[row][col] < 0.5:continuefor offset in offsets:neighbor_row = min(max(0, row+offset[0]), rows-1)neighbor_col = min(max(0, col+offset[1]), cols-1)neighbor_val = binary_img[neighbor_row, neighbor_col]if neighbor_val < 0.5:continuelabel = neighbor_val if neighbor_val < label else labelif label == 255:label_idx += 1label = label_idxbinary_img[row][col] = labelprint('第一遍扫描:',binary_img)print('开始第二遍...')return binary_img# binary_img: bg-0, object-255; int
#第一遍扫描
def Two_Pass(binary_img: np.array, neighbor_hoods):if neighbor_hoods == NEIGHBOR_HOODS_4:offsets = OFFSETS_4elif neighbor_hoods == NEIGHBOR_HOODS_8:offsets = OFFSETS_8else:raise ValueErrorbinary_img = neighbor_value(binary_img, offsets, False)return binary_imgif __name__ == "__main__":#创建四行七列的矩阵binary_img = np.zeros((4, 7), dtype=np.int16)#指定点设置为255index = [[0, 2], [0, 5],[1, 0], [1, 1], [1, 2], [1, 4], [1, 5], [1, 6],[2, 2], [2, 5],[3, 1], [3, 2], [3, 4],[3,5], [3, 6]]for i in index:binary_img[i[0], i[1]] = np.int16(255)print("原始二值图像")print(binary_img)#print("Two_Pass")#调用Two Pass算法,计算第一遍扫面的结果binary_img = Two_Pass(binary_img, NEIGHBOR_HOODS_4)#print(binary_img)#计算第一遍扫面的结果binary_img, points = reorganize(binary_img)print(binary_img)#print(points)

结果如下所示:

原始二值图像
[[  0   0 255   0   0 255   0][255 255 255   0 255 255 255][  0   0 255   0   0 255   0][  0 255 255   0 255 255 255]]
第一遍扫描: [[0 0 1 0 0 2 0][3 3 1 0 4 2 2][0 0 1 0 0 2 0][0 5 1 0 6 2 2]]
开始第二遍...
[[0 0 1 0 0 2 0][3 3 1 0 4 2 2][0 0 1 0 0 2 0][0 5 1 0 6 2 2]]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/491617.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

(180页PPT)|清华大学孙富春教授深度讲解: 人工智能技术与产业发展

来源&#xff1a;精智工厂[导读】本文是清华大学孙富春教授在机械工业出版社讲座交流PPT&#xff0c;孙教授从背景与历史、深度学习、脑认知、产业&#xff08;装备&#xff09;发展、发展趋势等五个方面详细解读了人工智能技术与产业发展。未来智能实验室是人工智能学家与科学…

(转)#ifndef的用法

原文链接&#xff1a;http://wenku.baidu.com/link?urlc4doqVo3U429RkwTN5eaJIfD2rEu-1bLKKQXuqO8drmL359PhUjVmzC7P94wBY90bqYjPBRiuujahij4AM_06OkiOThB3v91fXexqpIukG_ 定义 #ifndef x #define x ... #endif 这是宏定义的一种&#xff0c;它可以根据是否已经定义…

OpenCV与图像处理学习十——区域生长算法(含代码)

OpenCV与图像处理学习十——区域生长算法&#xff08;含代码&#xff09;一、区域生长算法概要二、区域生长算法原理三、代码应用一、区域生长算法概要 区域生长是一种串行区域分割的图像分割方法。区域生长是指从某个像素出发&#xff0c;按照一定的准则&#xff0c;逐步加入…

FutureWarning: Using a non-tuple sequence for multidimensional indexing is deprecated

使用scipy模块时出现警告&#xff1a;FutureWarning: Using a non-tuple sequence for multidimensional indexing is deprecated; use arr[tuple(seq)] instead of arr[seq]. In the future this will be interpreted as an array index, arr[np.array(seq)], which will resu…

一文看懂中国MEMS传感器产业链

来源&#xff1a;通信产业网物联网对促进我国经济发展、优化产业结构具有重大的战略意义。而在整个物联网生态中&#xff0c;MEMS传感器扮演着越来越重要的角色&#xff0c;在即将到来的智能物联网时代中将起到核心作用&#xff0c;为新科技产品提供更智能、更敏锐的感知能力。…

stream iterators源代码详解

所谓stream iterators&#xff0c;可以将迭代器绑定到一个stream&#xff08;数据流&#xff09;对象身上。绑定istream对象&#xff08;例如&#xff1a;std:cin)&#xff0c;称为 istream_iterator,拥有输入能力。乍听之下真神奇。所谓绑定一个istream object&#xff0c;其实…

OpenCV与图像处理学习十一——分水岭算法(含代码)

OpenCV与图像处理学习十一——分水岭算法&#xff08;含代码&#xff09;一、分水岭算法概要二、分水岭算法步骤三、代码应用一、分水岭算法概要 任意的灰度图像可以被看做是地质学表面&#xff0c;高亮度的地方是山峰&#xff0c;低亮度的地方是山谷。 给每个孤立的山谷&…

python清空文件夹

要清空一个文件夹&#xff0c;可以通过删除该文件夹再新建一个一样的文件夹来达到清空文件夹的效果 import os import shutilshutil.rmtree(dirpath) # 能删除该文件夹和文件夹下所有文件 os.mkdir(dirpath)

10件5G能实现但4G不能做的事情

来源&#xff1a;雷锋网 5G的一些最佳用途可能还没有被发现&#xff0c;但下面是我们已经知道的十个令人兴奋的用途。雷锋网按&#xff1b;2019年6月6日&#xff0c;工信部正式向中国电信、中国移动、中国联通、中国广电发放5G商用牌照&#xff0c;这表明中国正式进入了5G商用的…

【VS开发】CString 转为 char *方法大全

【VS开发】CString 转为 char *方法大全 标签&#xff08;空格分隔&#xff09;&#xff1a; 【VS开发】 方法1&#xff1a; CString strTemp; char szTemp[128];strTemp _T("abckdkfei"); memset( szTemp, 0, sizeof(szTemp) ); strcpy( szTemp, strTemp.GetBuffer…

OpenCV与图像处理学习十二——图像形状特征之HOG特征

OpenCV与图像处理学习十二——图像形状特征之HOG特征一、图像特征理解1.1 颜色特征1.2 纹理特征1.3 形状特征1.4 空间关系特征二、形状特征描述2.1 HOG特征2.1.1 基本概念2.1.2 HOG实现过程2.1.3 代码实现前面介绍了图像的基础知识、基本处理方法以及传统图像分割的应用&#x…

python删除文件

import osif os.path.exists(path):os.remove(path)

深度解读:5G正式发牌,国内通信市场冷暖预判

来源&#xff1a;ICT解读者2019年6月6日&#xff0c;工业和信息化部向中国电信、中国移动、中国联通和中国广电正式颁发5G牌照&#xff0c;批准四家企业经营“第五代数字蜂窝移动通信业务”。这标志着我国正式进入5G商用元年。一石激起千层浪&#xff0c;相较于此前各运营商官方…

OpenCV与图像处理学习十三——Harris角点检测(含代码)

OpenCV与图像处理学习十三——Harris角点检测&#xff08;含代码&#xff09;一、角点的概念二、Harris角点检测的实现过程三、Harris代码应用一、角点的概念 角点&#xff1a; 在现实世界中&#xff0c; 角点对应于物体的拐角&#xff0c; 道路的十字路口、 丁字路口等。 从…

wpf prism IRegionManager 和IRegionViewRegistry

引入了一个新的问题&#xff0c;IRegionViewRegistry和IRegionManager都具有RegisterViewWithRegion方法&#xff0c;二者有区别么&#xff1f; 答案是——没有。我们已经分析过&#xff0c;在UnityBootstrapper的中&#xff0c;已经默认建立了IRegionManager和RegionManager的…

The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

python表示条件之间的逻辑与除了用and还可以用&&#xff0c;把and换成&即可

ubuntu zip解压

您好&#xff0c;zip xx.zip压缩&#xff0c;unzip xx.zip 解压&#xff0c;tar zcvf xx.tar.gz压缩tar zxvf xx.tar.gz解压转载于:https://www.cnblogs.com/zxouxuewei/p/4973319.html

Go map如何排序

1. 将key 或 value 单独组成其类型的切片或数组&#xff0c;进行排序 package mainimport ("fmt""sort" )func main() {table : map[string]string{"hello": "hello","world": "world","a": "…

德勤发布《中国智能制造分析报告》

来源&#xff1a;CIO俱乐部亚洲正受到自动化、智能化大潮冲击。国际劳工组织调研发现&#xff0c;越南、柬埔寨、菲律宾和印度尼西亚的工人的失业风险最高&#xff0c;据估计这几个区域约50%的工人工作可能在未来20年被自动化取代。亚洲尤其是中国作为制造业的重要区域&#xf…

OpenCV与图像处理学习十四——SIFT特征(含代码)

OpenCV与图像处理学习十四——SIFT特征&#xff08;含代码&#xff09;一、SIFT算法二、SIFT实现过程三、代码实现一、SIFT算法 SIFT&#xff0c; 即尺度不变特征变换算法&#xff08;Scale-invariant feature transform&#xff0c;SIFT&#xff09; &#xff0c; 是用于图像…