OpenCV单词轮廓检测

news2025/3/1 9:46:47

OpenCV单词轮廓检测

    • 0. 前言
    • 1. 策略分析
    • 2. 检测字符轮廓
    • 3. 检测单词轮廓
    • 相关链接

0. 前言

在根据文档图像执行单词转录时,通常第一步是识别图像中单词的位置。我们可以使用两种不同的方法识别图像中的单词:

  • 使用 CRAFTEAST 等深度学习技术
  • 使用基于 OpenCV 的技术

在本节中,我们将学习如何在不利用深度学习的情况下识别机器打印的单词。由于打印单词的背景和前景之间的对比度很高,因此不需要像 YOLO 之类的模型来识别单个单词的位置,在这种情况下,使用 OpenCV 可以在计算资源非常有限的情况下获得解决方案,唯一的缺点是准确率可能并非 100%,准确率取决于扫描图像的质量,如果扫描图像非常清晰,则准确率可以接近 100%

1. 策略分析

利用 OpenCV 识别图像中的单词策略如下所示:

  1. 将图像转换为灰度图像
  2. 放大图像中的内容,膨胀操作可以将黑色像素扩散到相邻区域,因此将同一单词的字符连接起来,有助于确保同一个单词的字符之间的连接;需要注意的是,不能过度膨胀,以至于将属于不同相邻单词的字符也连接起来
  3. 连接字符后,利用 cv2.findContours 在每个单词周围绘制一个边界框

2. 检测字符轮廓

(1) 加载图像,并查看图像样本:

import cv2, numpy as np
img = cv2.imread('1.png')
img1 = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
import matplotlib.pyplot as plt,cv2
plt.imshow(img1)
plt.show()

示例图像
(2) 将输入图像转换为灰度图像:

img_gray = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)

(3) 随机裁剪原始图像:

crop = img_gray[250:300,50:200]
plt.imshow(crop,cmap='gray')
plt.show()

裁切图像
(5) 二值化输入灰度图像:

_img_gray = np.uint8(img_gray < 200)*255

将小于 200 的像素的值置为 0,而像素强度大于 200 的值置为 255

(6) 查找图像中的字符轮廓:

contours,hierarchy = cv2.findContours(_img_gray,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)

使用 cv2.findContours 函数可以通过将一组连续的像素创建为对象的单个区域来查找轮廓。

(7) 将阈值图像转换为三通道图像,以便在字符周围绘制彩色边界框:

thresh1 = np.stack([_img_gray]*3,axis=2)

(8) 创建空白图像,以便将 thresh1 中的相关内容复制到新图像中:

thresh2 = np.zeros((thresh1.shape[0],thresh1.shape[1]))

(9) 获取轮廓并在轮廓所在的位置绘制一个矩形边界框,同时,将 thresh1 图像中与矩形边界框对应的内容复制到 thresh2 中:

for cnt in contours:
    if cv2.contourArea(cnt)>0:
        [x,y,w,h] = cv2.boundingRect(cnt)
        if ((h>5) & (h<100)):
            thresh2[y:(y+h),x:(x+w)] = thresh1[y:(y+h),x:(x+w),0].copy()
            cv2.rectangle(thresh1,(x,y),(x+w,y+h),(255,0,0),2)

在以上代码中,只获取面积大于 5 像素的轮廓,并且只获取边界框高度在 5100 像素之间的那些轮廓,这样可以排除可能是噪声的较小边界框,并排除可能包含整个图像的大边界框。

(10) 绘制结果图像:

fig = plt.figure()
fig.set_size_inches(20,20)
plt.imshow(img1)
plt.show()

字符轮廓

我们已经可以在字符周围绘制边界框,但是如果想在单词周围绘制框,则需要将单词中的像素组合成一个连续的单元。接下来,我们利用膨胀技术在单词周围绘制边界框。

3. 检测单词轮廓

(1) 检查图像 thresh2

fig = plt.figure()
fig.set_size_inches(20,20)
plt.imshow(thresh2)
plt.show()

轮廓检测
接下来,需要将不同字符的像素连接成一个集合,使一个连续的像素集合构成一个单词。使用膨胀函数 cv2.dilate,将白色像素扩散周围的像素中,扩散程度由核大小决定。如果核大小为 5,则白色区域的所有边界向外移动 5 个像素。

(2) 使用尺寸为 1x2 的核执行膨胀操作:

dilated = cv2.dilate(thresh2, np.ones((1,2),np.uint8), iterations=1)

将核大小指定为 1x2 (np.ones((1,2),np.uint8)),以便相邻字符会出现交集,cv2.findContours 可以包含彼此接近的字符。但是,如果核大小过大,膨胀后的单词可能会有一些交集,导致一个边界框中包含多个单词。

(3) 获取膨胀图像的轮廓:

contours,hierarchy = cv2.findContours(np.uint8(dilated),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)

(5) 在原始图像上绘制膨胀后的图像轮廓:

for cnt in contours:
    if cv2.contourArea(cnt)>5:
        [x,y,w,h] = cv2.boundingRect(cnt)
        if ((h>5) & (h<100)):
            cv2.rectangle(img1,(x,y),(x+w,y+h),(255,0,0),2)

(6) 绘制带有轮廓的原始图像:

fig = plt.figure()
fig.set_size_inches(20,20)
plt.imshow(img1)
plt.show()

检测结果
从上图中可以看出,我们获取了每个单词对应的边界框。本节的关键在于如何确定一组像素是否形成一个连通的单元,如果一组像素没有形成一个单元,使用膨胀进行处理,膨胀会扩散黑色像素,而侵蚀 (erode) 函数会扩散白色像素。

相关链接

OpenCV简介与图像处理基础
OpenCV图像运算
手写文本识别
YOLO 目标检测

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

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

相关文章

【算法-力扣】72. 编辑距离(动态规划)

目录 一、题目描述 二、解题思路 三、参考答案 一、题目描述 编辑距离 给你两个单词 word1 和 word2&#xff0c; 请返回将 word1 转换成 word2 所使用的最少操作数 。 你可以对一个单词进行如下三种操作&#xff1a; 插入一个字符 删除一个字符 替换一个字符 示例 1&#…

win11电脑桌面倒计时提醒怎么设置?

在日常工作中&#xff0c;我们经常需要处理大量的工作任务&#xff0c;而且很多任务都有时间限制。如果将这些任务记录在桌面上&#xff0c;并设置倒计时提醒&#xff0c;无疑会大大提高我们的工作效率。想象一下&#xff0c;在繁忙的工作间隙&#xff0c;你只需一瞥桌面&#…

618火爆来袭,退换货花费多咋办?

姐妹们&#xff0c;一年一度的618就要来了&#xff0c;你准备好了吗&#xff0c;虽然咱们的钱包鼓鼓的&#xff0c;但是咱们的购物袋也要鼓鼓的呀&#xff0c;我们就是要多买&#xff0c;多买&#xff0c;多买&#xff0c;这样才能更显示出自己更爱自己了。 言归正传&#xff…

2024.6.14 刷题总结

2024.6.14 **每日一题** 2786.访问数组中的位置使分数最大&#xff0c;看到这题就想到动态规划的思路&#xff0c;遍历数组&#xff0c;每次选择移动该元素时能获得到的最大值&#xff0c;分别考虑最后一个的元素为奇数/偶数的最大值&#xff0c;用长度为2的数组来储存这两个值…

JUnit 5学习笔记

JUnit 5 学习笔记 1.JUnit5的改变2.JUnit5常用注解及测试2.1 DisplayName/Disabled/BeforeEach/AfterEach/BeforeAll/AfterAll2.2 Timeout2.3 RepeatedTest 3.断言3.1 简单断言3.2 数组断言3.3 组合断言3.4 异常断言3.5 超时断言3.6 快速失败 4.前置条件5.嵌套测试6.参数化测试…

微信群发机器人.使用指南.

0.简介 1.介绍 微信群发机器人是用来群发微信消息的工具,通过控制电脑的键盘和鼠标操作微信app来实现群发.支持的消息类型有:文字,图片,视频,文件,小程序,位置等. 群发机器人也可以将微信联系人中的信息保存到电脑csv表格中,以供分析. 因其是通过模拟用户操作鼠标键盘来实现群…

Java课程设计:基于swing的贪吃蛇小游戏

文章目录 一、项目介绍二、核心代码三、项目展示四、源码获取 一、项目介绍 贪吃蛇是一款经典的休闲益智游戏,自问世以来便深受广大用户的喜爱。这个游戏的基本玩法是控制一条不断增长的蛇,目标是吃掉屏幕上出现的食物,同时避免撞到边缘或自身。随着游戏的进行,蛇的身体会越长…

智慧工厂人员定位系统的影响与前景展望

随着科技的不断发展&#xff0c;智能制造正在迅速崛起&#xff0c;而智慧工厂人员定位系统作为其中的重要组成部分&#xff0c;正在改变传统制造业的面貌。这一系统通过利用物联网、室内定位等技术手段&#xff0c;能够实时准确地追踪和监控工厂内人员的位置。那么&#xff0c;…

Hexapod C-887使用手册 -- 3

3--产品描述 本章中 型号概要 产品视图 交换范围 可选的附件 可命令元素 固件的重要组件 ID芯片探测 轴A和B的操作参数 Hexapod的运动 通过EtherCAT接口发送命令 通信接口 PC软件的概要 3.1 型号概要 C-887 hexapod控制器可以获取以下版本&#xff1a; 型号 描述…

【软件安装9】OpenCV多版本安装Ubuntu18.04

文章目录 一、查看已安装的Opencv版本二、安装新版本三、多版本OpenCV切换 OpenCV 官网 在此 一、查看已安装的Opencv版本 查看已安装opencv的版本 pkg-config opencv --modversion官网下载对应的版本&#xff0c;并解压 opencv3.4.3 二、安装新版本 进入前置准备里下载…

Linux驱动开发笔记(八)输入子系统

文章目录 前言一、输入子系统1. 子系统的引入2. 组成部分3. 事件处理流程4. 相关数据结构 二、程序编写1. 相关API函数1.1 input_allocate_device ( )1.2 input_free_device ( )1.3 input_register_device ( )1.4 input_unregister_device ( )1.5 input_event ( )1.6 input_rep…

ModbusRTU协议之3.5T

RTU 模式每个字节 ( 11 位 ) 的格式为 : 1 起始位&#xff0c; 8 数据位&#xff0c; 1 校验位&#xff08;也可以无校验&#xff09;&#xff0c; 1 停止位&#xff0c; 校验位使用偶校验、奇校验、无校验都可以&#xff0c;但 使用无校验时必须配置 2 个停止位。 所以无…

阿里云的视频超分辨率服务将视频从25M视频增强至469M,画质提升了不少

效果还是不错的&#xff1a; tom&#xff1a; 阿里云文档&#xff1a; 视频超分辨率SuperResolveVideo的语法及示例_视觉智能开放平台(VIAPI)-阿里云帮助中心 请求参数&#xff1a; 还比较简单&#xff0c;就三个参数&#xff0c;其中一个还是固定的&#xff0c;我本次的BitRat…

【SQLAlChemy】表之间的关系,外键如何使用?

表之间的关系 数据库表之间的关系分为三种&#xff1a; 一对一关系&#xff08;One-to-One&#xff09;&#xff1a;在这种关系中&#xff0c;表A的每一行都与表B的一行关联&#xff0c;反之亦然。例如&#xff0c;每个人都有一个唯一的社保号&#xff0c;每个社保号也只属于…

深度学习(六)——神经网络的基本骨架:nn.Module的使用

一、torch.nn简介 官网地址&#xff1a; torch.nn — PyTorch 2.0 documentation 1. torch.nn中的函数简介 Containers&#xff1a;神经网络的骨架 Convolution Layers&#xff1a;卷积层 Pooling layers&#xff1a;池化层 Padding Layers&#xff1a;Padding Non-linear …

android 播放视频

播放视频文件 新建一个activity_main.xml文件&#xff0c;文件中放置了3个按钮&#xff0c;分别用于控制视频的播放、暂停和重新播放。另外在按钮的下面又放置了一个VideoView&#xff0c;稍后的视频就将在这里显示。 <LinearLayout xmlns:android"http://schemas.an…

Android Studio新增功能:Device Streaming

今天将Android Studio升级到2023.3.1 Patch2。发现新增了Device Streaming功能。支持远程使用Google的物理设备调试程序。这样可以方便地在真实设备上测试自己的APP。这对于手头没有Google设备的开发者而言&#xff0c;确实方便很多。该功能目前处于测试阶段&#xff0c;在2025…

【机器学习300问】117、序列模型中的符号表示方法?以命名实体识别(NER)任务为例。

在序列模型中&#xff0c;特别是在命名实体识别(NER)任务中&#xff0c;我们通常会用一系列符号来表示输入序列、目标标签以及模型的结构和操作。本文列出一些常见的符号表示方法&#xff0c;结合NER任务进行解释。 一、什么是命名实体识别任务&#xff1f; &#xff08;1&am…

06 SpringBoot 配置文件详解-application.yaml

Spring Boot 提供了大量的自动配置&#xff0c;极大地简化了spring 应用的开发过程&#xff0c;当用户创建了一个 Spring Boot 项目后&#xff0c;即使不进行任何配置&#xff0c;该项目也能顺利的运行起来。当然&#xff0c;用户也可以根据自身的需要使用配置文件修改 Spring …

L50--- 104. 二叉树的最大深度(深搜)---Java版

1.题目描述 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 2.思路 这个二叉树的结构如下&#xff1a; 根节点 1 左子节点 2 右子节点 3 左子节点 4 计算过程 从根节点 1 开始计算&#xff1a; 计算左子树的最大深度&#xff1a; 根节点 2&#xf…