【python】OpenCV—Connected Components

news2024/11/6 16:24:23

在这里插入图片描述

文章目录

  • 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

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

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

相关文章

ENSP (虚拟路由冗余协议)VRRP配置

VRRP(Virtual Router Redundancy Protocol,虚拟路由冗余协议)是一种用于提高网络可用性和可靠性的协议。它通过在多个路由器之间共享一个虚拟IP地址,确保即使一台路由器发生故障,网络依然能够正常运行,防止…

【JS学习】08. web API-事件进阶

Web APIs - 第3天 进一步学习 事件进阶,实现更多交互的网页特效,结合事件流的特征优化事件执行的效率 掌握阻止事件冒泡的方法理解事件委托的实现原理 事件流 事件流是对事件执行过程的描述,了解事件的执行过程有助于加深对事件的理解&…

Hadoop完全分布式环境搭建步骤

【图书介绍】《Spark SQL大数据分析快速上手》-CSDN博客 大数据与数据分析_夏天又到了的博客-CSDN博客 本文介绍Hadoop完全分布式环境搭建方法,这个Hadoop环境用于安装配置Spark。假设读者已经安装好Visual Box 7.0.6虚拟环境与一个CentOS 7虚拟机(如果…

H7-TOOL的CAN/CANFD助手增加帧发送成功标识支持, 继续加强完善功能细节

2.27版本固件正式携带此功能,包括之前做的负载率检测和错误信息展示也将集成到这个版本固件中。 对于接收,我们可以直接看到效果,而发送不行,所以打算在发送的地方展示下发送成功标识。CAN发送不像串口,需要等待应答后…

ssm+jsp653基于Javaweb的网上花店系统的设计与实现

博主介绍:专注于Java(springboot ssm 等开发框架) vue .net php phython node.js uniapp 微信小程序 等诸多技术领域和毕业项目实战、企业信息化系统建设,从业十五余年开发设计教学工作 ☆☆☆ 精彩专栏推荐订阅☆☆☆☆☆不…

操作系统如何执行,他究竟是个什么

硬件中断 所谓硬件中断,其实也是一个执行信号的过程,具体流程如下。 具体要执行什么方法,只需要拿着对应的信号访问中断向量表就就行比如 N就是像cpu发的中断信号。 时钟中断 但是这里面有一个叫做时钟源的东西,其实也是一个外…

音视频入门基础:FLV专题(24)——FFmpeg源码中,获取FLV文件视频信息的实现

一、引言 通过FFmpeg命令可以获取到FLV文件的视频压缩编码格式、色彩格式(像素格式)、分辨率、码率、帧率信息: 而由《音视频入门基础:FLV专题(9)——Script Tag简介》和《音视频入门基础:FLV专…

JMM内存模型(面试回答)

1.什么是JMM JMM就是Java内存模型(java memory model)。因为在不同的硬件生产商和不同的操作系统下,内存的访问有一定的差异,所以会造成相同的代码运行在不同的系统上会出现各种问题。所以Java内存模型(JMM)屏蔽掉各种硬件和操作系统的内存访问差异&…

【stablediffusion又出王炸】IC-Light,可以操控图像生成时的光照,光照难题终于被解决了!

IC-Light代表Impose Constant Light,是一个控制图像照明的项目。可以操控图像生成时的光照,对内容主体重新打光生成符合新背景环境光照的图片。这下商品图合成这种需要最大程度保持原有主体 ID 需求的最大的问题解决了。 Controlnet, Layerdiffusion, IC-light… …

创建线程时传递参数给线程

在C中,可以使用 std::thread 来创建和管理线程,同时可以通过几种方式将参数传递给线程函数。这些方法包括使用值传递、引用传递和指针传递。下面将对这些方法进行详细讲解并给出相应的代码示例。 1. 值传递参数 当你创建线程并希望传递参数时&#xff…

react使用Fullcalendar 实战用法

使用步骤请参考:react使用Fullcalendar 卡片式的日历: 需求图: 卡片式的日历,其实我是推荐 antd的,我两个都写了一下都能实现。 antd 的代码: antd的我直接用的官网示例:antd 日历示例 i…

使用 RabbitMQ 有什么好处?

大家好,我是锋哥。今天分享关于【使用 RabbitMQ 有什么好处?】面试题。希望对大家有帮助; 使用 RabbitMQ 有什么好处? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 RabbitMQ 是一种流行的开源消息代理,广…

基于MATLAB的农业病虫害识别研究

matlab有处理语音信号的函数wavread,不过已经过时了,现在处理语音信号的函数名称是audioread选取4.wav进行处理(只有4的通道数为1) 利用hamming窗设计滤波器 Ham.m function [N,h,H,w] Ham(fp,fs,fc)wp 2*pi*fp/fc;ws 2*pi*…

极简实现酷炫动效:Flutter隐式动画指南第三篇自定义Flutter隐式动画

目录 前言 一、TweenAnimationBuilder 二、使用TweenAnimationBuilder实现的一些动画效果 1.调整透明度的动画 2.稍微复杂点的组合动画 3.数字跳动的动画效果 前言 上两节博客分别介绍了Flutter中的隐式动画的基础知识以及使用隐式动画实现的一些动画效果。当系统提供的隐…

怎么能监控电脑屏幕?四个真心好用的电脑屏幕监控小妙招,一分钟看完!

怎么能监控电脑屏幕?这或许是许多家长、企业管理者和IT安全人员心中的疑问。 有人说:用魔法水晶球! 当然,这个方法些许梦幻,现实中我们还是要依靠科技手段来实现电脑屏幕的监控。 接下来,我将为大家介绍四…

中仕公考:25年浙江省公务员考试今日开始报名

2025年浙江省公务员考试于今日开始报名,准备参加考试的各位考生不要错过报名时间! 报名时间:2024年11月6日9时—11月11日17时。 资格初审时间:2024年11月6日9时—11月13日17时。 准考证下载时间:2024年12月3日9时—12月8日17时…

【IEEE出版】第六届国际科技创新学术交流大会暨信息技术与计算机应用学术会议(ITCA 2024,12月06-08)

第六届国际科技创新学术交流大会暨信息技术与计算机应用学术会议(ITCA 2024) 2024 6th International Conference on Information Technology and Computer Application 会议官网:itca2024.iaecst.org 会议时间:2024年12月06-08日 截稿时…

SpringMVC总结 我的学习笔记

SpringMVC总结 我的学习笔记 一、SpringMVC简介1.MVC2.SpringMVC概述3. SpringMVC中的核心组件4.SpringMVC核心架构流程 二、SpringMVC框架实例具体实现使用注解实现 四、数据处理及跳转1.结果跳转方式2.处理器方法的参数与返回值处理提交数据数据显示到前端 五、RestFul风格1.…

基于SpringBoot的免税商品优选购物商城的设计与实现

一、项目背景 从古至今,通过书本获取知识信息的方式完全被互联网络信息化,但是免税商品优选购物商城,对于购物商城工作来说,仍然是一项非常重要的工作。尤其是免税商品优选购物商城,传统人工记录模式已不符合当前社会…

【Python】计算机视觉应用:OpenCV库图像处理入门

计算机视觉应用:OpenCV库图像处理入门 在当今的数字化时代,计算机视觉(Computer Vision)已经渗透到各行各业,比如自动驾驶、智能监控、医疗影像分析等。而 Python 的 OpenCV 库(Open Source Computer Visi…