【OpenCV实现图像:OpenCV进行OCR字符分割】

文章目录

    • 概要
    • 基本概念
    • 读入图像
    • 图像二值化
    • 小结

概要

在处理OCR(Optical Character Recognition,光学字符识别)时,利用传统的图像处理方法进行字符切分仍然是一种有效的途径。即便当前计算机视觉领域主导的是卷积神经网络,但对于一些相对简单的实际应用场景,传统方法仍然表现出良好的效果。

在OCR任务中,字符切分是一个关键的步骤,它能够将整个文本图像分割成单个字符,为后续的处理任务提供基础。传统图像处理方法可以通过一系列技术来实现字符的准确切分。这些技术可能包括但不限于:

边缘检测: 使用算子(如Sobel、Canny)检测图像中字符的边缘,从而确定字符的边界。

连通区域分析: 通过标记和分析图像中的连通区域,可以识别字符的位置和形状。

投影法: 水平和垂直投影可以帮助检测字符之间的间隔,从而进行字符切分。

轮廓分析: 提取字符的轮廓信息,进而判断字符的位置和形状。

形态学操作: 使用腐蚀、膨胀等形态学操作来调整字符的形状,以便更好地进行切分。

虽然卷积神经网络在图像处理任务中表现出色,但在一些简单的场景中,传统方法的实用性仍然很大。例如,在文档扫描、数字识别等任务中,通过合理运用传统图像处理技术,可以快速、准确地完成字符切分,为后续的OCR处理奠定基础。这种混合使用传统方法和深度学习技术的方式,可以充分发挥各自的优势,实现更全面、高效的图像处理任务。

基本概念

OCR(Optical Character Recognition):全称光学字符识别,是一项技术,通过使用光学和图像处理技术,将图像中的文字转换为可编辑的文本。

Segmentation:在图像处理领域,分割是指将整个图像分解为多个子部分的过程,以便进行进一步的处理。

OCR Segmentation:是指在光学字符识别过程中,将包含文本的图像分解成多个小部分的操作。这旨在有效地识别图像中的文字,并将其从背景中分离出来,以便后续的OCR处理。通过分割,系统可以更准确地定位和识别每个字符,提高整体识别准确性。

读入图像

读入图像:

一旦获得了包含文本的数字图像,或者通过扫描仪将某些文档转换为数字图像进行存储,就可以迈入下一步,即预处理。在这个阶段,可以使用以下代码来读入图像,以便进行后续的处理。

import cv2

# 读入图像
myImage = cv2.imread('12.png')

# 显示图像
cv2.imshow('Text Image', myImage)
cv2.waitKey(0)

在这里插入图片描述

图像二值化

在开始分割文本图像之前,需要经过一系列预处理步骤,其中之一是图像的二值化。这个过程包括以下步骤:

灰度化: 首先,将输入图像转换为灰度图像。这一步的目的是简化图像,使系统能够更轻松地识别图像中的不同形状,同时去除颜色信息,从而减少处理的复杂性。这通常通过将图像中的每个像素的彩色信息转化为相应的灰度值来实现。

import cv2

# 读入图像
myImage = cv2.imread('12.png')

# 灰度化
grayImage = cv2.cvtColor(myImage, cv2.COLOR_BGR2GRAY)

# 二值化
_, binaryImage = cv2.threshold(grayImage, 128, 255, cv2.THRESH_BINARY)

# 显示图像
cv2.imshow('Binary Image', grayImage)
cv2.waitKey(0)

在这里插入图片描述

二值化: 一旦图像变为灰度图,接下来的关键步骤是将其二值化。这意味着将图像中的像素值转换为两个可能的值之一,通常是0和255。这样的二值图像使得文字与背景更为明显,为后续的字符切分和识别提供了更好的基础。

这个可以根据自己的修改,转换颜色。

_, binaryImage = cv2.threshold(grayImage, 128, 255, cv2.THRESH_BINARY)
import cv2
# 读入图像
myImage = cv2.imread('12.png')
# 灰度化
grayImage = cv2.cvtColor(myImage, cv2.COLOR_BGR2GRAY)
# 二值化
_, binaryImage = cv2.threshold(grayImage, 128, 255, cv2.THRESH_BINARY)
# 显示图像
cv2.imshow('Binary Image', binaryImage)
cv2.waitKey(0)

在这里插入图片描述

import cv2

# 读入图像
myImage = cv2.imread('12.png')

# 灰度化
grayImage = cv2.cvtColor(myImage, cv2.COLOR_BGR2GRAY)

# 二值化
ret, thresh = cv2.threshold(grayImage, 0, 255, cv2.THRESH_OTSU | cv2.THRESH_BINARY_INV)
# 形态学操作
horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (18, 18))
dilation = cv2.dilate(thresh, horizontal_kernel, iterations=1)

# 显示图像
cv2.imshow('Dilated Image', thresh)
cv2.waitKey(0)

在这里插入图片描述

接着可以选择并使用多种算法从上述二值图像中提取信息,例如直方图均衡、傅立叶变换、形态学等。
形态学操作

import cv2

# 读入图像
myImage = cv2.imread('12.png')

# 灰度化
grayImage = cv2.cvtColor(myImage, cv2.COLOR_BGR2GRAY)

# 二值化
ret, thresh = cv2.threshold(grayImage, 0, 255, cv2.THRESH_OTSU | cv2.THRESH_BINARY_INV)
# 形态学操作
horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (18, 18))
dilation = cv2.dilate(thresh, horizontal_kernel, iterations=1)

# 显示图像
cv2.imshow('Dilated Image', dilation)
cv2.waitKey(0)

在这里插入图片描述

查找轮廓
接着需要找到轮廓线,这样才能将图像与背景逐行分离。
为了清楚,换红色线条标注,可以修改这段代码更换颜色

    rect = cv2.rectangle(myImage, (x, y), (x + w, y + h), (0, 0, 255), 1)  # 红色矩形
import cv2

# 读入图像
myImage = cv2.imread('12.png')

# 灰度化
grayImage = cv2.cvtColor(myImage, cv2.COLOR_BGR2GRAY)

# 二值化
ret, thresh = cv2.threshold(grayImage, 0, 255, cv2.THRESH_OTSU | cv2.THRESH_BINARY_INV)

# 形态学操作
horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (18, 18))
dilation = cv2.dilate(thresh, horizontal_kernel, iterations=1)

# 查找轮廓
horizontal_contours, hierarchy = cv2.findContours(dilation, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

# 在原始图像上绘制红色矩形
for cnt in horizontal_contours:
    x, y, w, h = cv2.boundingRect(cnt)
    rect = cv2.rectangle(myImage, (x, y), (x + w, y + h), (0, 0, 255), 1)  # 红色矩形

# 显示图像
cv2.imshow('Image with Red Rectangles', myImage)
cv2.waitKey(0)

在这里插入图片描述
单词和字符分割

接着我们通过以下步骤对裁剪出的轮廓子图进行单词分割:

1-预处理(灰度、阈值)

2-形态学算法

3-找到边界并绘制它们

4-进入单个字符分割

进而我们将对输出图像中的每个单词再次重复相同的步骤进行单个字符的分割:

1-预处理(灰度、阈值)

2-形态学算法

3-找到边界并绘制它们

4-停止

最终我们得到的结果如下。
代码:

import cv2

# 读入图像
myImage = cv2.imread('12.png')

# 灰度化
grayImage = cv2.cvtColor(myImage, cv2.COLOR_BGR2GRAY)

# 二值化
ret, thresh = cv2.threshold(grayImage, 0, 255, cv2.THRESH_OTSU | cv2.THRESH_BINARY_INV)

# 形态学操作
horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (18, 18))
dilation = cv2.dilate(thresh, horizontal_kernel, iterations=1)

# 查找轮廓
horizontal_contours, hierarchy = cv2.findContours(dilation, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

# 在原始图像上绘制红色矩形和进行字符分割
for cnt in horizontal_contours:
    x, y, w, h = cv2.boundingRect(cnt)

    # 绘制红色矩形
    rect = cv2.rectangle(myImage, (x, y), (x + w, y + h), (0, 0, 255), 1)

    # 在水平轮廓区域内进行字符分割
    roi = thresh[y:y + h, x:x + w]

    # 进行字符分割的额外步骤,例如形态学操作、查找字符轮廓等
    char_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
    char_dilation = cv2.dilate(roi, char_kernel, iterations=1)
    char_contours, _ = cv2.findContours(char_dilation, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    # 在原始图像上绘制字符的边界
    for char_cnt in char_contours:
        char_x, char_y, char_w, char_h = cv2.boundingRect(char_cnt)
        char_rect = cv2.rectangle(myImage, (x + char_x, y + char_y), (x + char_x + char_w, y + char_y + char_h),
                                  (0, 255, 0), 1)

# 显示图像
cv2.imshow('Image with Red Rectangles and Character Boundaries', myImage)
cv2.waitKey(0)

`
在这里插入图片描述

小结

在传统图像处理中,如何利用常见的形态学方法进行字符轮廓查找,从而实现字符的切分。通过提供相应的代码实现,展示了在一些字符分布简单、字符间隔较大的场景下,该方法能够取得一定的效果。然而,由于采用传统方案,该方法的泛化性较为有限。在面对更复杂的场景时,可以考虑借助神经网络等先进技术,以实现更加鲁棒和适用于多种情况的字符切分算法。

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

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

相关文章

【软考篇】中级软件设计师 第四部分(三)

中级软件设计师 第四部分(三) 三十四. 结构化开发方法34.1 内聚34.2 耦合 三十五. 测试基础知识三十六. 面向对象36.1 UML图36.2 设计模式36.3 数据流图 读前须知: 【软考篇】中级软件设计师 学前须知 上一章节: 【软考篇】中级软…

【入门篇】1.7 Redis 之 codis 入门介绍

文章目录 1. 简介2. Codis的安装与配置下载编译源码安装1. 安装 Go 运行环境2. 设置编译环境3. 下载 Codis 源代码4. 编译 Codis 源代码 Docker 部署 3. Codis的架构Codis的架构图和组件Codis的工作流程 4. Codis的核心特性自动数据分片数据迁移高可用性全面支持Redis命令分布式…

Client not connected, current status:STARTING

上面的问题出现在springboot整合nacos的时候出现的 首先说明一点,我出现这个问题是使用了nacos集群,nacos版本为2.2.3,且使用了nginx做了负载均衡,如果您和我一样,那么可以接着往下看。 1️⃣:当nacos版本为…

windows与wsl互传文件

1.把windows上的文件传到wsl中,\\wsl.localhost\Ubuntu-22.04\mnt\wsl 将你要传的文件放到wsl这个路径下,Ubuntu-22.04是我的子系统,换成自己对应的 2.把wsl中的文件传到windows中 将wsl中的文件放到 /mnt/c 或 /mnt/d 中,这两…

汇川伺服【选型目录】

sv680旗舰: 编码器位数:26bit 电机额定转速:3000r【3k】圈脉冲: sv670标准: 编码器位数:23bit【台达B3:23bit,台达A2:bit】 电机额定转速:3000r【3k】圈脉冲&#xff1…

【AI视野·今日Sound 声学论文速览 第三十五期】Fri, 27 Oct 2023

AI视野今日CS.Sound 声学论文速览 Fri, 27 Oct 2023 Totally 8 papers 👉上期速览✈更多精彩请移步主页 Daily Sound Papers Controllable Generation of Artificial Speaker Embeddings through Discovery of Principal Directions Authors Florian Lux, Pascal T…

chatGPT API中参数temperature的含义是什么

在 ChatGPT API 中,temperature 参数用于控制回答的确定性和创造性。temperature 的值范围通常是从 0 到 1。这个参数影响模型生成回答时的随机性: 低温度值(如 0 或接近 0):会导致模型生成更确定、更一致、更少出乎意…

微服务实战系列之Sentinel

前言 微服务架构(Microservice Architecture)是一种架构概念,旨在通过将功能分解到各个离散的服务中以实现对解决方案的解耦。 近年来,微服务已赫然崛起于IT界,越来越多的程序员不得不向之靠拢。也正因为各行各业都愿为…

ZOC8 for Mac:最佳终端仿真器,助力您的工作效率飞升!

在现代的工作环境中,终端仿真器扮演着不可或缺的角色。无论是开发人员、系统管理员还是网络工程师,都需要一个功能强大、易于使用的终端仿真器来处理各种任务。而ZOC8 for Mac正是为这些专业人士而打造的最佳选择。 作为一款全功能的终端仿真软件&#…

Apache SCXML2 RCE漏洞

文章目录 前言源码利用上传恶意xml文件构造payload搭建Apache服务器 远程RCE 前言 在做 [HDCTF 2023]BabyJxVx 遇到的知识点,但是没公网的服务器只能作罢,写下这篇文章记录 源码利用 public String Flag(RequestParam(required true) String filenam…

微信如何设置自动保存图片和视频

8-6 在日常的工作中,如果你需要经常或者每天都要对同事们发来的大量图片和视频进行保存的,这种工作需要花费很多时间,如果你想节省这些手工时间的话,也许本文适合你,首先要明白的是,微信本身是没有任何相关…

备战旺季,赛盈分销解析2023年美国人爱买的年终爆款!

今年10月份美国人增加了自己在线上渠道的支出,Adobe Analytics的调查报告显示,美国消费者当月的线上支出达到了768亿美元,同比增长5.9%。 数据还表明,1-10月份美国人的线上购物相比去年增长了4.3%,整体消费达到7590亿…

二十、泛型(9)

本章概要 对缺乏潜在类型机制的补偿 反射将一个方法应用于序列 Java 8 中的辅助潜在类型 使用 Suppliers 类的通用方法 总结:类型转换真的如此之糟吗? 对缺乏潜在类型机制的补偿 尽管 Java 不直接支持潜在类型机制,但是这并不意味着泛型代…

笔记53:torch.nn.rnn() 函数详解

参数解释: (1)input_size():即输入信息 Xt 的每个序列的独热编码向量的长度,即 len(vocab) (2)hidden_size():即隐变量 h 的维度(维度是多少,就代表用几个数…

北京君正客户应用案例:掌静脉3D人脸猫眼视屏智能锁

凯迪仕在今年4月发布了智能锁旗舰新品K70 Pro Max掌静脉3D人脸猫眼视屏智能锁,随即这款新品也成了行业热议的焦点。凯迪仕每次新品都力求突破精益求精,不仅追求科技感、高级感与品质感,而且赋予科技温度,带来人文化的关怀。K70 Pr…

FPGA——IP核 基础操作

FPGA——IP核 基础操作 IP核例化模块时钟IP核RAM IP核 IP核例化模块 找到模版 加入代码中 时钟IP核 配置模式功能 配置输入时钟 输出配置 RAM IP核

物联网AI MicroPython学习之语法 I2C总线

学物联网,来万物简单IoT物联网!! I2C 介绍 模块功能: I2C Master设备驱动 接口说明 I2C - 构建硬件I2C对象 函数原型:I2C(id, scl, sda, freq)参数说明: 参数类型必选参数?说明idintYI2C外设&#xff…

关于新能源汽车的英语翻译

近年来,随着全球对环保和可持续发展的重视,新能源汽车已经成为汽车产业的重要发展方向。各国政府和企业都在加大投入,推动新能源汽车的技术研发和产业化发展,进而促进了新能源汽车翻译的需求不断提升 。那么,关于新能源…

免费的快速手机文件解压APP,快冲

各位小伙伴们大家好,今天我要介绍一款手机上必备的神奇工具!你有没有经常遇到需要解压文件情况呢?还在为不知道用哪个软件而烦恼吗?别担心,我给你带来了解决方案 ,就是这一款免费的解压精灵。 解压精灵是一…

-pthread和-lpthread

我试图在我的Ubuntu机器上设置GTest环境.但在使GTest获取库时,我收到以下错误... ../obj/gtest.a(gtest-all.o): In function testing::internal::ThreadLocal<std::vector<testing::internal::TraceInfo, std::allocator<testing::internal::TraceInfo> > >…