《深度学习》OpenCV 摄像头OCR 过程及案例解析

news2024/10/6 7:46:33

目录

一、摄像头OCR

1、含义

2、一般操作步骤

1)安装OpenCV库

2)设置摄像头

3)图像采集

4)图像预处理

5)文本识别

6)文本处理

7)结果显示

二、案例实现

1、定义展示图像函数

2、定义自动缩放图片大小函数

3、定义轮廓点的排序函数

4、定义透视变换函数

5、打开相应摄像头

6、建立整体循环结构

7、执行上述代码


一、摄像头OCR

1、含义

        OpenCV摄像头OCR是一个使用OpenCV库OCR技术实现的工具,它可以通过摄像头实时读取图像,然后利用OCR光学字符识别)技术将图像中的文本内容提取出来。这个工具可以应用于各种场景,例如扫描身份证、识别车牌号、读取条形码等。使用OpenCV摄像头OCR,可以方便地在实时图像中进行文本识别和处理。

2、一般操作步骤

        1)安装OpenCV库

                首先需要安装OpenCV库,这是一个开源的计算机视觉库,提供了许多图像处理和分析的功能。

        2)设置摄像头

                将摄像头与计算机连接,并通过OpenCV库进行初始化和设置,以确保能够实时获取摄像头图像

        3)图像采集

                通过调用OpenCV库提供的函数,从摄像头中获取图像帧,并将其存储为图像对象。

        4)图像预处理

                对采集到的图像进行预处理,以提高后续的OCR识别效果。可能的预处理包括图像灰度化、二值化、降噪等。

        5)文本识别

                使用OCR技术对预处理后的图像进行文本识别。这可以使用OCR引擎,如Tesseract进行,也可以使用第三方OCR服务。

        6)文本处理

                对识别出的文本进行必要的后处理,例如去除空格、提取特定格式的信息等。

        7)结果显示

                将识别和处理后的文本结果显示在图像或图形用户界面上,以便用户查看和使用。

二、案例实现

1、定义展示图像函数

import numpy as np
import cv2

def cv_show(name,img):
    cv2.imshow(name,img)
    # cv2.waitKey(60)

2、定义自动缩放图片大小函数

# 调整图像高宽,保持图像宽高比不变
def resize(image,width=None,height=None ,inter=cv2.INTER_AREA):  # 输入参数为图像、可选宽度、可选高度、插值方式默认为cv2.INTER_AREA,即面积插值
    dim = None   # 存储计算后的目标尺寸w、h
    (h,w) = image.shape[:2]  # 返回输入图像高宽
    if width is None and height is None:   # 判断是否指定了宽和高大小,如果没有指定则返回原图
        return image
    if width is None:   # 判断如果没有指定宽度大小,则表示指定了高度大小,那么运行内部代码
        r = height/float(h)   # 指定高度与原图高度的比值
        dim = (int(w*r),height)   # 宽度乘以比值得到新的宽度,此处得到新的宽高
    else:  # 此处表示为width不是None,即指定了宽度,与上述方法一致,计算比值
        r = width/float(w)
        dim = (width,int(h*r))
    resized = cv2.resize(image,dim,interpolation=inter)     # 指定图像大小为上述的dim,inter默认为cV2.INTER_AREA,即面积插值,适用于缩放图像。
    return resized

3、定义轮廓点的排序函数

def order_points(pts):   # 对输入的四个点按照左上、右上、右下、左下进行排序
    rect = np.zeros((4,2),dtype='float32')   # 创建一个4*2的数组,用来存储排序之后的坐标位置
    # 按顺序找到对应坐标0123分别是左上、右上、右下、左下
    s = pts.sum(axis=1)   # 对pts矩阵的每个点的x y相加
    rect[0] = pts[np.argmin(s)]    # np.argmin(s)表示数组s中最小值的索引,表示左上的点的坐标
    rect[2] = pts[np.argmax(s)]    # 返回最大值索引,即右下角的点坐标
    diff = np.diff(pts,axis=1)   # 对pts矩阵的每一行的点求差值
    rect[1] = pts[np.argmin(diff)]   # 差值最小的点为右上角点
    rect[3] = pts[np.argmax(diff)]   # 差值最大表示左下角点
    return rect   # 返回排序好的四个点的坐标

4、定义透视变换函数

# 将透视扭曲的矩形变换成一个规则的矩阵
def four_point_transform(image,pts):
    # 获取输入坐标点
    rect = order_points(pts)  # 为上述排序的四个点
    (tl,tr,br,bl) = rect   # 分别返回给四个值,分别表示为左上、右上、右下、左下
    # 计算输入的w和h值
    widthA = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1]-bl[1]) ** 2))   # 计算四边形底边的宽度
    widthB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1]-tl[1]) ** 2))   # 计算顶边的宽度
    maxWidth = max(int(widthA), int(widthB))   # 返回最大宽度
    heightA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2))   # 计算左上角到右下角的对角线长度
    heightB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2))   # 计算右上角到左下角的高的长度
    maxHeight = max(int(heightA),int(heightB))   # 返回最长的高度
    # 变换后对应坐标位置
    dst = np.array([[0,0],   # 定义四个点,表示变换后的矩阵的角点
                    [maxWidth-1,0],
                    [maxWidth-1,maxHeight-1],
                    [0,maxHeight-1]],dtype='float32')

    M = cv2.getPerspectiveTransform(rect,dst)  # 根据原始点和变换后的点计算透视变换矩阵M
    warped = cv2.warpPerspective(image,M,(maxWidth,maxHeight))  # 对原始图像,针推变换矩阵和输出图像大小进行透视变换,返回变换后的图片
    # 返回变换后的结果
    return warped

5、打开相应摄像头

import cv2
cap = cv2.VideoCapture(0)   # 确保摄像头是可以启动的状态
if not cap.isOpened():   # 打开失败
    print("Cannot open camera")
    exit()

6、建立整体循环结构

while True:
    flag = 0  # 用于标识 当前是否检测到文档
    ret,image = cap.read()  # 从摄像头读取每一帧图像,如果正确读取帧,ret为True,image为读取到的帧图像
    orig = image.copy()   # 对每一帧做副本
    if not ret:   # 读取失败,则退出循环
        print("不能读取摄像头")
        break

    cv_show("image",image)   # 展示读取到的帧画面

    gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)  # 图像处理,转换为灰度图
    gray = cv2.GaussianBlur(gray,(5,5), 0)  # 高斯滤波减少图像中的噪点
    edged = cv2.Canny(gray,75,200)  # 使用canny边缘检测算法检测图像边缘
    cv_show('1',edged)

    # 对进行处理过的图像做副本,然后进行轮廓检测,cv2.RETR_EXTERNAL表示只检测最外层轮廓,cv2.CHAIN_APPROX_SIMPLE表示只保存轮廓端点坐标,返回轮廓点的集合列表
    cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[1]
    # 对轮廓点进行排序,排序方式为轮廓面积的大小,以降序排列
    cnts = sorted(cnts,key=cv2.contourArea,reverse=True)[:3]
    image_contours = cv2.drawContours(image, cnts, -1, (0, 255, 0),2)  # 在原图上绘制轮廓,-1表示绘制所有轮廓
    cv_show( "image_contours", image_contours)
    k = cv2.waitKey(60)
    if k == 27:   # esc键的asc码为27,点击esc终止循环
        break

    for c in cnts:   # 遍历每一幅轮廓的描述信息
        # 计算轮廓近似
        peri = cv2.arcLength(c,True)   # 其计算轮蹦的周长,True表示封闭图像
        # c表示输入的点集
        # epsilon表示从原始轮到近似轮的最大距离,它是一个准确度参数

        approx = cv2.approxPolyDP(c,0.05 * peri, True)   # 轮廓近似,对待逼近的轮廓c进行多边形逼近,逼近的精度为0.05*peri,即周长的5%
        area = cv2.contourArea(approx)   # 计算逼近的多边形轮廓面积
        # 4个点的时候就拿出来
        if area > 20000 and len(approx) == 4:   # 筛选轮廓面积大于20000,近似多边形四个顶点,认为检测到了文档
            screenCnt = approx   # 将筛选出来的近似多边形赋值给screenCnt
            flag = 1  # 将上述设置的旗帜设置为1
            print(peri, area)   # 打印识别出来的轮廓周长和轮廓面积
            print('检测到文档')
            break

    if flag == 1:  # 如果检测到文档
        # 展示结果
        # print("STEP 2:获取轮骤")
        image_contours = cv2.drawContours(image,[screenCnt],0,(0,255,0),2)  # 将上述筛选出来的轮廓绘制到原图
        cv_show("image",image_contours)
        # 对检测到的文档区域进行透视变换,矫正文档形状
        warped = four_point_transform(orig,screenCnt.reshape(4,2))
        cv_show("warped",warped)
        # 将矫正完的图像转换成灰度图,然后进行二值化处理,来提取文档内容
        warped = cv2.cvtColor(warped,cv2.COLOR_BGR2GRAY)
        ref = cv2.threshold(warped,220,255,cv2.THRESH_BINARY)[1]
        # ref = cv2.threshold(warped,0, 255, CV2.THRESH BINARY | CV2.THRESH OTSU)[1]
        cv_show("ref",ref)

cap.release()  # 释放捕获器,释放摄像头资源
cv2.destroyAllWindows()   # 关闭所有OpenCV创建的窗口

7、执行上述代码

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

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

相关文章

CANoe_TestModule截图功能TestReportAddWindowCapture

前言 TestReportAddWindowCapture方法作为CAPL脚本中的一个重要功能,其能够将指定窗口的屏幕截图添加到测试报告中,对于记录和验证界面状态具有重要意义。本文将全面解析TestReportAddWindowCapture方法的使用方法、参数解释、示例应用以及注意事项&…

从介质失效看互联网时代的信息过载

来读一篇文章:90年代的硬盘已大规模变砖,没啥好担心的,好事。 结合我两年前的粗浅认知 互联网时代无信息,按照 “动” 的观念看,当信息越来越多,信息密度越来越大时,信息的寿命就会越来越短&am…

智谱AI开源CogView3及升级版,文生图技术新突破!

Ai 智能办公利器 - Ai-321.com 智谱AI近日震撼宣布,向公众开放其最新研发的CogView3及进阶版CogView-3Plus-3B,这两款模型无疑为文本转图像技术领域带来了革命性的突破。 人工智能 - Ai工具集 - 全球热门人工智能软件ai工具集合网站 CogView3作为首款运…

PMP--三模--解题--161-170

文章目录 10.沟通管理--沟通管理计划--沟通管理计划是项目管理计划的组成部分,描述将如何规划、结构化、执行与监督项目沟通,以提高沟通的有效性。该计划包括如下信息:干系人的沟通需求。--凡信息,找沟通。161、 [单选] 一家公司的…

【X线源】微焦点X射线源的基本原理

【X线源】微焦点X射线源的基本原理 1.背景2.原理 1.背景 1895年11月8日,德国物理学家威廉伦琴在研究阴极射线时偶然发现了X射线。当时,他注意到阴极射线管附近的荧光屏发出了光,即使它被纸板遮挡住。经过进一步实验,他意识到这种…

开源模型应用落地-模型微调-模型研制-模型训练(二)

一、前言 模型训练是深度学习领域中的关键环节。随着技术的发展,预训练模型的出现极大地改变了模型构建的格局。这些预训练模型在大规模数据集上进行了初步的学习,蕴含了丰富的通用知识。然而,不同的实际应用场景有着各自独特的需求。例如在医疗影像诊断领域,预训练模型可能…

Linux和指令初识

前言 Linux是我们在服务器中常用的操作系统,我们有必要对这个操作系统有足够的认识,并且能够使相关的指令操作。今天我们就来简单的认识一下这个操作的前世今生,并且介绍一些基础的指令操作 Linux的前世今生 要说Linux,还得从U…

GitLab flow工作流及其使用

问题背景 Git flow和Github flow及其问题 使用GitLab flow 目录 什么是GitLab工作流 功能分支 生产分支 使用GitLab flow环境分支 使用GitLab flow发布分支 使用GitLab flow合并/拉取请求 使用GitLab flow进行问题跟踪 链接和关闭合并请求中的问题 用rebase压缩提交…

ElasticSearch备考 -- Multi field

一、题目 Create the index hamlet_2 with one primary shard and no replicas Copy the mapping of hamlet_1 into hamlet_2, but also define a multi-field for speaker. The name of such multi-field is tokens and its data type is the (default) analysed string Reind…

【工程测试技术】第6章 信号处理初步,频谱分析,相关系数

目录 6.1 数字信号处理的基本步骤 6.2 离散信号及其频谱分析 6.2.1 概述 6.2.2 时域采样、混叠和采样定理 6.2.3 量化和量化误差 6.2.4 截断、泄漏和窗函数 6.2.5 频域采样、时域周期延拓和栅栏效应 6.2.6 频率分辨率、整周期截断 6.3 相关分析及其应用 6.3.1 两…

Emissive CEO Fabien Barati谈《消失的法老》背后的故事:XR大空间体验的创新与未来

在最近的一次播客访谈中,虚拟现实之声(Voices of VR)的主持人Kent Bye与Emissive公司的联合创始人兼CEO Fabien Barati进行了深入交流。Emissive是全球顶级的VR大空间体验制作商之一,以其沉浸式探险项目如《永恒的巴黎圣母院》和《胡夫地平线》而闻名。以下是这次访谈的核心…

VSCode debug模式无法跳转进入内置模块

在使用VSCode调试python代码的时候, 需要查看第三方库的代码,进行调试。 但是VSCode默认是不进入的, 因此需要更改Debug配置: 在launch.json 里加入如下的代码: "justMyCode": false 这样就能进入第三方库…

计算有向无环图中两节点间简单路径的数量

计算有向无环图中两节点间简单路径的数量 主要步骤:伪代码:C代码实现:解释:在给定一个有向无环图(DAG)以及两个节点s和t时,我们需要计算从节点s到节点t之间的简单路径的数量。为了实现这一目标,我们可以使用动态规划的思想,在拓扑排序的基础上解决问题。 主要步骤: 拓…

【Linux第五课-进程概念下】环境变量、程序地址空间

目录 环境变量main参数 --- 命令行参数环境变量环境变量特性 --- 命令行操作main函数的参数获取环境变量environ获取环境变量getenv()获取环境变量unset移除本地变量或环境变量set显示本地变量 代码获取和设置环境变量 本地变量 程序地址空间什么是进程地址空间为什么有地址空间…

预算有限也能玩转 AI:香橙派、树莓派与 Jetson 的选择攻略

随着 AI 技术的迅猛发展,越来越多的边缘计算设备可以处理从轻量级任务到复杂的 AI 模型。在本文中,我们将对比几款主流的边缘 AI 设备,包括 NVIDIA Jetson 系列、香橙派 和 树莓派 5,并探讨 Hailo 加速器 在边缘 AI 领域的潜力。我…

【学习笔记】手写一个简单的 Spring MVC

目录 一、什么是Spring MVC ? Spring 和 Spring MVC 的区别? Spring MVC 的运行流程? 二、实现步骤 1. DispatcherServlet 1. 创建一个中央分发器 拦截所有请求 测试 2. 接管 IOC 容器 1. 创建配置文件 2. 修改 web.xml 配置文件 …

vSAN03:vSAN故障处理、节点维护、删除节点、关闭/重启/删除vSAN集群

目录 vSAN故障处理单节点维护从vSAN集群中永久删除节点关闭vSAN集群重启vSAN集群删除vSAN集群 vSAN故障处理 级别状态处理可能原因活动正常无无缺失vSAN 检测到临时组件故障,且其中的组件可以恢复并还原其工作状态,则该组件将处于“缺失”状态。&#x…

分析JS Crash(进程崩溃)

一、JS Crash异常检测能力 1、JS Crash日志规格 以下是进程崩溃日志信息中对应字段解释。 Build info:XXX-XXXX X.X.X.XX(XXXXXXXX) <- 版本信息 Module name:com.example.myapplication <- 模块名 Version:1.0.0 <- 版本号 Pid:579 <- 进程号 Uid:0 <- 用户ID…

【Qt】Qt学习笔记(一):Qt界面初识

Qt 是一个跨平台应用程序和 UI 开发框架。使用 Qt 您只需一次性开发应用程序&#xff0c;无须重新编写源代码&#xff0c;便可跨不同桌面和嵌入式操作系统部署这些应用程序。Qt Creator是跨平台的Qt集成开发环境。 创建项目 Qt的一些界面&#xff0c;初学时一般选择Qt Widgets …

VirtualBox虚拟机连接宿主机并能够上网(小白向)

现存问题 windows系统主要使用vmare和virtualbox两种虚拟机&#xff0c;virtualbox相对于vmare更加轻便&#xff0c;但少有博客能够详细说明使用virtualbox的教程。踩了网上的坑后&#xff0c;决定写一篇文章介绍virtualbox虚拟机上网的流程。 需求 1. virtualbox虚拟机与宿主机…