当前位置: 首页 > article >正文

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

目录

一、摄像头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.kler.cn/news/334391.html

相关文章:

  • 心觉:成事的基石,需要在“放弃”和“永不放弃”之间找到平衡
  • 冒泡排序,插入排序,快速排序,选择排序
  • 海外合规|新加坡推出智慧国2.0计划 设新网络安全与保障机构
  • 浅析Golang的Context
  • 《软件工程概论》作业一:新冠疫情下软件产品设计
  • JAVA运用中springBoot获取前端ajax提交参数方式汇总
  • Python | 使用Seaborn绘制KDE核密度估计曲线
  • Flutter笔记--通知
  • 【Unity】双摄像机叠加渲染
  • 使用 Vertex AI Gemini 模型和 Elasticsearch Playground 快速创建 RAG 应用程序
  • 12.1 Linux_进程间通信_管道
  • 开发指南066-平台紧凑版
  • 学生多元智能测评
  • TCP 流量控制 - 滑动窗口和拥塞控制算法解析
  • 大学生就业服务:Spring Boot技术实践
  • 项目管理-信息系统治理
  • rk3568 LTE(EC20 Android14)
  • 一篇文章搞懂Android 刷卡器对接:RS232 DB9串口通讯,通讯设置,刷卡器API介绍;代码示例;MDB协议;
  • 掌握嵌套子查询:复杂 SQL 中 * 列的准确表列关系
  • C/C++/EasyX——入门图形编程(3)