【python】OpenCV—Connected Components

在这里插入图片描述

文章目录

  • 1、任务描述
  • 2、代码实现
  • 3、完整代码
  • 4、结果展示
  • 5、涉及到的库函数
  • 6、参考

1、任务描述

基于 python opencv 的连通分量标记和分析函数,分割车牌中的数字、号码、分隔符

  • cv2.connectedComponents
  • cv2.connectedComponentsWithStats
  • cv2.connectedComponentsWithAlgorithm
  • cv2.connectedComponentsWithStatsWithAlgorithm

2、代码实现

导入必要的包,加载输入图像,将其转换为灰度,并对其进行二值化处理

# 导入必要的包
import argparse
import cv2

# 解析构建的参数解析器
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", default="1.jpeg", help="path to input image")
ap.add_argument("-c", "--connectivity", type=int, default=4, help="connectivity for connected analysis")
args = vars(ap.parse_args())  # 将参数转为字典格式

# 加载输入图像,将其转换为灰度,并对其进行阈值处理
image = cv2.imread(args["image"])  # (366, 640, 3)
cv2.imshow("src", image)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv2.imwrite("gray.jpg", gray)

thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
cv2.imshow("threshold", thresh)
cv2.imwrite("threshold.jpg", thresh)

对阈值化后的图像应用连通分量分析

# 对阈值化后的图像应用连通分量分析
output = cv2.connectedComponentsWithStats(thresh, args["connectivity"], cv2.CV_32S)
(numLabels, labels, stats, centroids) = output

cv2.connectedComponentsWithStats 可以结合后面章节的介绍查看

输入图片的尺寸假如是 (366, 640, 3),看看 cv2.connectedComponentsWithStats 的返回情况

"""
[labels] (366, 640)

array([[1, 1, 1, ..., 1, 1, 1],
       [1, 1, 1, ..., 1, 1, 1],
       [1, 1, 1, ..., 1, 1, 1],
       ...,
       [1, 1, 1, ..., 1, 1, 1],
       [1, 1, 1, ..., 1, 1, 1],
       [1, 1, 1, ..., 1, 1, 1]], dtype=int32)

[state]
array([[    83,     83,    482,    163,  57925],
       [     0,      0,    640,    366, 155776],
       [    96,     96,    456,    138,   2817],
       [   113,    108,     75,    113,   5915],
       [   194,    119,     52,     90,   2746],
       [   270,    120,     62,     90,   2260],
       [   489,    124,     46,     85,   2370],
       [   344,    126,     29,     82,   1398],
       [   394,    126,     29,     82,   1397],
       [   445,    126,     29,     82,   1396],
       [   253,    149,     17,     18,    240]], dtype=int32)

[centroids]
array([[333.22577471, 163.75948209],
       [317.48520953, 191.81337305],
       [323.41924033, 174.62051828],
       [148.71885038, 163.47658495],
       [219.46686089, 164.00837582],
       [299.82566372, 161.7420354 ],
       [512.84767932, 165.38818565],
       [362.91773963, 161.85479256],
       [412.91481747, 161.956335  ],
       [463.91833811, 161.96919771],
       [261.3125    , 157.22083333]])
"""

注意这里是质心,不是连通区域矩形框的中心

对于 x 方向的质心,图像在质心左右两边像素和相等,y 同理,上下两边像素和相等

遍历每个连通分量,忽略 label = 0 背景,提取当前标签的连通分量统计信息和质心,可视化边界框和当前连通分量的质心

# 遍历每个连通分量
for i in range(0, numLabels):
    # 0表示的是背景连通分量,忽略
    if i == 0:
        text = "examining component {}/{} (background)".format(
            i + 1, numLabels)
    # otherwise, we are examining an actual connected component
    else:
        text = "examining component {}/{}".format(i + 1, numLabels)

    # 打印当前的状态信息
    print("[INFO] {}".format(text))

    # 提取当前标签的连通分量统计信息和质心
    x = stats[i, cv2.CC_STAT_LEFT]  # 左上角横坐标
    y = stats[i, cv2.CC_STAT_TOP]  # 左上角纵坐标
    w = stats[i, cv2.CC_STAT_WIDTH]  # 边界框的宽
    h = stats[i, cv2.CC_STAT_HEIGHT]  # 边界框的高
    area = stats[i, cv2.CC_STAT_AREA]  # 边界框的面积
    (cX, cY) = centroids[i]  # 边界框的质心

    # 可视化边界框和当前连通分量的质心
    # clone原始图,在图上画当前连通分量的边界框以及质心
    output = image.copy()
    cv2.rectangle(output, (x, y), (x + w, y + h), (0, 255, 0), 3)  # 绿色边界框
    cv2.circle(output, (int(cX), int(cY)), 4, (0, 0, 255), -1)  # 红色质心

    # 创建掩码
    componentMask = (labels == i).astype("uint8") * 255  # 绘制 mask,对应label 置为 255,其余为 0

    # 显示输出图像和掩码
    cv2.imshow("Output", output)
    cv2.imwrite(f"output-{str(i).zfill(3)}.jpg", output)
    cv2.imshow("Connected Component", componentMask)
    cv2.imwrite(f"componentMask-{str(i).zfill(3)}.jpg", componentMask)
    cv2.waitKey(0)

创建掩码的时候比较巧妙 componentMask = (labels == i).astype("uint8") * 255

3、完整代码

# 导入必要的包
import argparse
import cv2

# 解析构建的参数解析器
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", default="1.jpeg", help="path to input image")
ap.add_argument("-c", "--connectivity", type=int, default=4, help="connectivity for connected analysis")
args = vars(ap.parse_args())  # 将参数转为字典格式

# 加载输入图像,将其转换为灰度,并对其进行阈值处理
image = cv2.imread(args["image"])  # (366, 640, 3)
cv2.imshow("src", image)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv2.imwrite("gray.jpg", gray)

thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
cv2.imshow("threshold", thresh)
cv2.imwrite("threshold.jpg", thresh)

# 对阈值化后的图像应用连通分量分析
output = cv2.connectedComponentsWithStats(thresh, args["connectivity"], cv2.CV_32S)
(numLabels, labels, stats, centroids) = output

# 遍历每个连通分量
for i in range(0, numLabels):
    # 0表示的是背景连通分量,忽略
    if i == 0:
        text = "examining component {}/{} (background)".format(
            i + 1, numLabels)
    # otherwise, we are examining an actual connected component
    else:
        text = "examining component {}/{}".format(i + 1, numLabels)

    # 打印当前的状态信息
    print("[INFO] {}".format(text))

    # 提取当前标签的连通分量统计信息和质心
    x = stats[i, cv2.CC_STAT_LEFT]  # 左上角横坐标
    y = stats[i, cv2.CC_STAT_TOP]  # 左上角纵坐标
    w = stats[i, cv2.CC_STAT_WIDTH]  # 边界框的宽
    h = stats[i, cv2.CC_STAT_HEIGHT]  # 边界框的高
    area = stats[i, cv2.CC_STAT_AREA]  # 边界框的面积
    (cX, cY) = centroids[i]  # 边界框的质心

    # 可视化边界框和当前连通分量的质心
    # clone原始图,在图上画当前连通分量的边界框以及质心
    output = image.copy()
    cv2.rectangle(output, (x, y), (x + w, y + h), (0, 255, 0), 3)  # 绿色边界框
    cv2.circle(output, (int(cX), int(cY)), 4, (0, 0, 255), -1)  # 红色质心

    # 创建掩码
    componentMask = (labels == i).astype("uint8") * 255  # 绘制 mask,对应label 置为 255,其余为 0

    # 显示输出图像和掩码
    cv2.imshow("Output", output)
    cv2.imwrite(f"output-{str(i).zfill(3)}.jpg", output)
    cv2.imshow("Connected Component", componentMask)
    cv2.imwrite(f"componentMask-{str(i).zfill(3)}.jpg", componentMask)
    cv2.waitKey(0)

4、结果展示

输入图片

在这里插入图片描述
output

[INFO] examining component 1/11 (background)
[INFO] examining component 2/11
[INFO] examining component 3/11
[INFO] examining component 4/11
[INFO] examining component 5/11
[INFO] examining component 6/11
[INFO] examining component 7/11
[INFO] examining component 8/11
[INFO] examining component 9/11
[INFO] examining component 10/11
[INFO] examining component 11/11

灰度图

在这里插入图片描述

二值化后的结果

在这里插入图片描述

遍历每个连通分量

componentMask0
在这里插入图片描述

output0,车牌外矩形轮廓
在这里插入图片描述

componentMask1
在这里插入图片描述
output1,图像边界的大框

在这里插入图片描述

componentMask2
在这里插入图片描述
output2,车牌内矩形轮廓

在这里插入图片描述

componentMask3

在这里插入图片描述
output3,汉字豫

在这里插入图片描述

componentMask4

在这里插入图片描述

output4,字母 U

在这里插入图片描述

componentMask5

在这里插入图片描述

output5,字母 V

在这里插入图片描述

componentMask6

在这里插入图片描述
output6,数字 9

在这里插入图片描述

componentMask7

在这里插入图片描述

output7,数字 1

在这里插入图片描述

componentMask8

在这里插入图片描述

output8,数字 1

在这里插入图片描述

componentMask9

在这里插入图片描述

output9,数字 1

在这里插入图片描述

componentMask10

在这里插入图片描述

output10,分隔符

在这里插入图片描述

总结,配合车牌检测,和 OCR 就能形成一个简略的车牌识别系统 😊

5、涉及到的库函数

cv2.connectedComponentsWithStats 是 OpenCV 库中的一个函数,用于寻找图像中的连通区域,并计算每个连通区域的统计信息。这个函数在处理二值图像时非常有用,可以帮助我们了解图像中不同对象的数量和特征。

一、函数原型

retval, labels, stats, centroids = cv2.connectedComponentsWithStats(image, connectivity=8, ltype=CV_32S)

二、参数说明

  • image: 输入图像,应为二值图像(黑白图像),即图像中的每个像素点非黑即白。
  • connectivity: 像素的连通性。4 或 8,表示每个像素点与其上下左右(4连通)或上下左右加对角线方向(8连通)的像素点是否视为连通。默认值为 8。
  • ltype: 输出标签图像的类型,通常为 cv2.CV_32S。

三、返回值

  • retval: 连通区域的数量(包括背景,如果背景被视为一个连通区域的话)。
  • labels: 与输入图像同样大小的标签图像,其中每个连通区域被赋予一个唯一的标签值。
  • stats: 一个矩阵,包含了每个连通区域的统计信息。对于每个连通区域,矩阵中存储了以下信息:(x, y, width, height, area),其中 (x, y) 是连通区域的边界框的左上角坐标,width 和 height 是边界框的宽度和高度,area 是连通区域的面积。
  • centroids: 连通区域的质心坐标矩阵,每个连通区域有一个对应的 (cx, cy) 坐标。

四、示例

下面是一个简单的使用 cv2.connectedComponentsWithStats 的示例:

import cv2  
import numpy as np  
  
# 读取图像并转换为灰度图像  
image = cv2.imread('example.png', 0)  
  
# 二值化处理(例如,阈值分割)  
_, binary = cv2.threshold(image, 127, 255, cv2.THRESH_BINARY)  
  
# 查找连通区域及统计信息  
num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(binary)  
  
# 打印连通区域的数量  
print('Number of connected components:', num_labels)  
  
# 遍历每个连通区域,并打印其统计信息  
for i in range(1, num_labels):  # 注意:背景区域的标签为0,从1开始遍历  
    x, y, w, h, area = stats[i, 0:5]  
    print(f'Component {i}: (x, y) = ({x}, {y}), Width = {w}, Height = {h}, Area = {area}')

五、注意事项

  • 在处理二值图像时,确保图像已经正确地进行了二值化处理。
  • 连通区域的数量(返回值 retval)包括了背景区域,如果背景被视为一个连通区域的话。
  • 输出的标签图像 labels 中的每个像素值代表了对应像素点所属的连通区域的标签。

通过 cv2.connectedComponentsWithStats,我们可以方便地获取图像中连通区域的数量和统计信息,这对于图像分析和处理中的许多任务都是非常有用的。

6、参考

  • OpenCV 连通分量标记和分析
  • https://pyimagesearch.com/2021/02/22/opencv-connected-component-labeling-and-analysis/
  • https://docs.opencv.org/4.x/de/d01/samples_2cpp_2connected_components_8cpp-example.html

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【LangChain系列4】【Chain模块详解】

目录 前言一、LangChain1-1、介绍1-2、LangChain抽象出来的核心模块1-3、特点1-4、langchain解决的一些行业痛点1-5、安装 二、Chain模块2-1、介绍2-2、LLMChain2-3、Sequential Chain(顺序链)2-4、Router Chain 总结 前言 LangChain给自身的定位是&…

[pdf,epub]105页《分析模式》漫谈合集01

105页的《分析模式》漫谈合集第1集的pdf、epub文件,已上传到本账号的CSDN资源。 如果无法下载,也可以访问umlchina.com/url/ap.html 已排版成适合手机阅读,pdf的排版更好一些。 ★UMLChina为什么叒要翻译《分析模式》? ★[缝合故…

Python酷库之旅-第三方库Pandas(186)

目录 一、用法精讲 861、pandas.Index.names属性 861-1、语法 861-2、参数 861-3、功能 861-4、返回值 861-5、说明 861-6、用法 861-6-1、数据准备 861-6-2、代码示例 861-6-3、结果输出 862、pandas.Index.nbytes属性 862-1、语法 862-2、参数 862-3、功能 8…

rabbitmq高级特性(2)TTL、死信/延迟队列、事务与消息分发

目录 1.TTL 1.1.设置消息过期时间 1.2.设置队列过期时间 2.死信队列 2.1.介绍 2.2.演示 3.延迟队列 3.1.模拟实现延迟队列 3.2.延迟队列插件 4.事务与消息分发 4.1.事务 4.2.消息分发 1.TTL 所谓的ttl,就是过期时间。对于rabbitmq,可以设置…

el-table type=“selection“换页多选数据丢失的解决办法

element里有一个 reserve-selection属性 设置以后就可以保留之前选中的选项&#xff0c;但还要设置row-key 代码如下&#xff1a; <el-tableref"mytable":data"HostRows"borderv-loading"loading"element-loading-text"正在加载中...&q…

Gitee push 文件

1、背景 想将自己的plecs仿真放到git中管理&#xff0c;以防丢失&#xff0c;以防乱改之后丢失之前版本仿真。此操作说明默认用户已下载git。 2、操作步骤 2.1 开启Git Bash 在文件夹中右键&#xff0c;开启Git Bash。 2.2 克隆文件 在Git Bash中打git clone git地址&#…

序列中删除指定数字【四种解法】

文章目录 解法1&#xff1a;另辟空间法解法2&#xff1a;覆盖法解法3&#xff1a;覆盖法&#xff08;进阶版&#xff09;解法4&#xff1a;异或取巧法 题目&#xff1a;有一个整数序列&#xff08;可能存在重复的整数&#xff09;&#xff0c;编写程序删除序列中指定的某一个整…

百度文心一言接入流程-java版

百度文心一言接入流程-java版 一、准备工作二、API接口调用-java三、百度Prompt工程参考资料: 百度文心一言:https://yiyan.baidu.com/百度千帆大模型:https://qianfan.cloud.baidu.com/百度千帆大模型文档:https://cloud.baidu.com/doc/WENXINWORKSHOP/index.html千tokens…

【深度学习】实验 — 动手实现 GPT【三】:LLM架构、LayerNorm、GELU激活函数

【深度学习】实验 — 动手实现 GPT【三】&#xff1a;LLM架构、LayerNorm、GELU激活函数 模型定义编码一个大型语言模型&#xff08;LLM&#xff09;架构 使用层归一化对激活值进行归一化LayerNorm代码实现scale和shift 实现带有 GELU 激活的前馈网络测试 模型定义 编码一个大…

《YOLO 目标检测》—— YOLO v4 详细介绍

文章目录 一、整体网络结构1. YOLO v4 网络结构图2.对之前版本改进创新的概括 二、对改进创新部分的具体介绍1. 输入端创新2. Backbone主干网络创新CSPDarknet53Mish激活函数Dropblock正则化 3. 特征融合创新SPP模块PAN结构 4. Prediction输出层创新&#xff08;未写完&#xf…

LinkedList 源码分析

1. 迭代器Iterator 在 Java 中&#xff0c;Iterator&#xff08;迭代器&#xff09;是一个用于遍历集合元素的接口。它提供了一种统一的方式来访问集合中的元素&#xff0c;而不需要了解集合的内部实现细节。 一、主要方法 hasNext()&#xff1a;判断是否还有下一个元素可遍历…

怎么安装行星减速电机才是正确的

行星减速电机由于其高效、精密的传动能力&#xff0c;广泛应用于自动化设备、机器人、机床以及其他需要精准控制的领域。正确的安装行星减速电机对于确保设备的性能与延长使用寿命至关重要。 一、前期准备 在进行行星减速电机的安装之前&#xff0c;必须做好充分的前期准备工作…

springcloud通过MDC实现分布式链路追踪

在DDD领域驱动设计中&#xff0c;我们使用SpringCloud来去实现&#xff0c;但排查错误的时候&#xff0c;通常会想到Skywalking&#xff0c;但是引入一个新的服务&#xff0c;增加了系统消耗和管理学习成本&#xff0c;对于大型项目比较适合&#xff0c;但是小的项目显得太过臃…

SAP RFC 用户安全授权

一、SAP 通讯用户 对于RFC接口的用户&#xff0c;使用五种用户类型之一的“通讯”类型&#xff0c;这种类型的用户没有登陆SAPGUI的权限。 二、对调用的RFC授权 在通讯用户内部&#xff0c;权限对象&#xff1a;S_RFC中&#xff0c;限制进一步可以调用的RFC函数授权&#xff…

Spring IoC——依赖注入

1. 依赖注入的介绍 DI&#xff0c;也就是依赖注入&#xff0c;在容器中建立的 bean &#xff08;对象&#xff09;与 bean 之间是有依赖关系的&#xff0c;如果直接把对象存在 IoC 容器中&#xff0c;那么就都是一个独立的对象&#xff0c;通过建立他们的依赖关系&#xff0c;…

IDEA连接EXPRESS版本的SQL server数据库

我安装的版本是SQL2019-SSEI-Expr.exe 也就是EXPRESS版本的SQL Server安排非常简单和快速。 但是默认没有启动sa用户。 启动sa用户名密码登录 默认安装完以后没有启用。 使用Miscrosoft SQL Server Management Studio 使用Windows身份连接后。 在安全性》登录名中找到sa并修改…

​Java面试经典 150 题.P13. 罗马数字转整数(012)​

本题来自&#xff1a;力扣-面试经典 150 题 面试经典 150 题 - 学习计划 - 力扣&#xff08;LeetCode&#xff09;全球极客挚爱的技术成长平台https://leetcode.cn/studyplan/top-interview-150/ 题解&#xff1a; class Solution {public int romanToInt(String s) {int sum…

大数据-204 数据挖掘 机器学习理论 - 混淆矩阵 sklearn 决策树算法评价

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

Windows11下将某个程序添加到鼠标右键快捷菜单

经常看log&#xff0c;最喜欢用的txt查看和编辑工具是EditPlus&#xff0c;好像是个韩国软件&#xff0c;最大的优势是打开大文件&#xff0c;好几G的log文件也很轻松&#xff0c;速度快&#xff0c;然后还有各种高亮设置查找文件等&#xff0c;非常方便。但是不知道为什么&…

宏处理将多个excel文件的指定sheet页合并到一个excel文件中

背景了解&#xff1a;有个同事问我&#xff1a;现在他要处理一千多个文件&#xff0c;每个excel文件都有3个sheet页签&#xff0c;想把所有的excel文件的第二个sheet页签复制一份放到一个新的excel文件中。如果是手动去操作一个个文件的复制&#xff0c;也没什么不可&#xff0…