首页 > 其他分享 >机器学习:opencv--摄像头OCR

机器学习:opencv--摄像头OCR

时间:2024-09-30 22:18:25浏览次数:7  
标签:轮廓 -- image cv2 opencv np OCR pts 摄像头

目录

前言

一、三个函数

1.显示图像

2.点排序

3.透视变换

二、代码实例

1.打开摄像头

2.图像预处理

3.检测特定轮廓

4.对轮廓进行处理

5.释放资源


前言

        摄像头OCR指的是利用摄像头捕捉图像中的文字信息,并通过光学字符识别(OCR)技术将其转换为可编辑的文本。

 

一、三个函数

1.显示图像

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

 

2.点排序

接收传入的坐标(为轮廓的四个顶点),

  1. 对每一行进行求和,
    1. 最小值是该轮廓的左上角,
    2. 最大值是右下角,
  2. 对每一行进行求差,
    1. 最小的是右上角,
    2. 最大的是右下角,
  3. 按照左上,右上,右下,左下的顺序填入rect矩阵
def order_points(pts):
    # 共4个坐标点
    rect = np.zeros((4, 2), dtype="float32")  # 用来存储排序之后的坐标位置
    # 按顺序找到对应坐标 0 1 2 3 分别是左上,右上,右下,左下
    s = pts.sum(axis=1)  # 对pts矩阵的每一行进行求和操作。 (x+y)
    rect[0] = pts[np.argmin(s)]
    rect[2] = pts[np.argmax(s)]
    diff = np.diff(pts, axis=1)  # 对pts矩阵的每一行进行求差操作。(y-x)
    rect[1] = pts[np.argmin(diff)]
    rect[3] = pts[np.argmax(diff)]
    return rect

 

3.透视变换

  1. 获取排序之后的点坐标
  2. 计算该轮廓的宽和高的较大值,当做变换之后的图像宽高
  3. 通过cv2.getPerspectiveTransform方法计算透视变换矩阵
  4. 再通过cv2.warpPerspective方法获取透视变换之后的图像
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)
    # 应用透视变换
    warped = cv2.warpPerspective(image, M, (maxWidth, maxHeight))  # 返回变换后结果
    return warped

 

二、代码实例

1.打开摄像头

  • 参数为0 则用电脑自带摄像头
  • 参数为1 则用外接摄像头
  • 若摄像头未被打开则输出Cannot open camera
cap = cv2.VideoCapture(0)  # 确保摄像头是可以启动的状态  电脑自带摄像头用0 外接的用1
if not cap.isOpened():
    print("Cannot open camera")
    exit()

 

2.图像预处理

  1. 打开摄像头之后,读取每一帧的画面并显示
  2. 转换成灰度图,进行高斯滤波处理,
  3. 然后使用Canny算子进行边缘检测并显示,
  4. 再对边缘检测之后的图像进行轮廓检测,
  5. 只取轮廓大小前十的轮廓将其画出来,并显示
while True:
    flag = 0  # 标识符 当前是否检测到文档
    ret, image = cap.read()
    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)
    cv_show('1', edged)

    cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[1]

    cnts = sorted(cnts, key=cv2.contourArea, reverse=True)[:10]
    image_contours = cv2.drawContours(image, cnts, -1, (0, 255, 0), 2)
    cv_show('image_contours', image_contours)

输出:

 

3.检测特定轮廓

  1. 遍历上述获取的轮廓 
  2. 对轮廓进行近似处理,并获取其特征点集
  3. 判断轮廓面积大于20000 并且特征点集只有4个
    for c in cnts:
        peri = cv2.arcLength(c, True)  # 计算轮廓的周长
        # True表示是否选择封闭轮廓
        approx = cv2.approxPolyDP(c, 0.05 * peri, True)  # 返回轮廓点集
        area = cv2.contourArea(approx)

        if area > 20000 and len(approx) == 4:
            screenCnt = approx
            flag = 1
            print(peri, area)
            print('检测到文档')
            break

 

4.对轮廓进行处理

  1. 如果在画面中获取到了符合条件的轮廓
  2. 就在原图上画出该轮廓
  3. 并将该轮廓图像进行透视变换并显示
  4. 最后对其进行二值化处理并显示
    if flag == 1:
        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, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
        cv2.imshow('ref', ref)
        cv2.waitKey(0)
输出:

 

5.释放资源

  • 最后循环结束之后记得释放资源
cap.release()  # 释放捕获器
cv2.destroyAllWindows()  # 关闭图像窗口

标签:轮廓,--,image,cv2,opencv,np,OCR,pts,摄像头
From: https://blog.csdn.net/weixin_65047977/article/details/142664186

相关文章

  • 小白学安全:搭建靶场
    DVWA漏洞靶场DVWA是一个故意设计成充满漏洞的PHP应用程序,用于渗透测试目的。它包含了多种常见的Web应用程序安全漏洞,如SQL注入、跨站脚本(XSS)、跨站请求伪造(CSRF)等,让学习者可以在一个安全可控的环境中实践识别和利用这些漏洞的方法,从而更好地理解和防御实际中的网络安全威胁。DVWA......
  • 今日总结
    Java方法是语句的集合,用于执行特定功能或解决某类问题。一、方法的基本概念定义:Java方法是封装代码块的结构,用于执行特定任务。它们允许将代码组织成逻辑单元,可重复使用并易于维护。优点:使程序更加简短而清晰。有利于程序的维护。提高程序开发的效率。提高代码的重用性。......
  • The 2023 ICPC Asia Nanjing Regional Contest / The 2nd Universal Cup. Stage 11: N
    比赛链接I.Counter按时间排序即可,注意可以不清零。F.EquivalentRewriting对于每个位置,把所有有这个位置的操作编号连向这个位置最终的值,做个拓扑排序,看看字典序最大的即可。复杂度\(\Theta(n+m)\)。C.PrimitiveRoot枚举和\(m\)的公共前缀,设\(i\)位置\(m\)是\(1......
  • MegaCli64 命令详解
    MegaCli64是用于管理和监控基于LSI/Avago/BroadcomMegaRAID控制器的RAID阵列的命令行工具。可以使用它来查看硬RAID的健康状态和是否正在进行重建(rebuild)。1.查看RAID阵列的状态要检查RAID阵列的整体健康状态,可以运行以下命令:MegaCli64-LDInfo-Lall-aALL-LD......
  • 程序员世界大冒险d22
    今天上了Java课,老师让生成对话框,不怎么会,该学学的,下面是代码:importjava.util.Random;importjavax.swing.;importjava.awt.;importjava.awt.event.ActionEvent;importjava.awt.event.ActionListener;classMethod{publicString[][]generateQuestions(){Randomran......
  • 【2024.9.30】NOIP2024 赛前集训-刷题训练(4)
    【2024.9.30】NOIP2024赛前集训-刷题训练(4)Problem-2000D-Codeforces给一串数和一串LR字符,L可以向右连接R,覆盖部分的LR不能再使用,但覆盖部分可以有被禁用的LR。每次覆盖部分的数字之和计入答案,求最大答案。手玩一下发现可以贪心。从最左边的L和最右边的R开始贪心。......
  • 构建前缀信息解决子数组问题
    构建前缀信息解决子数组问题303.区域和检索-数组不可变#include<vector>usingnamespacestd;classNumArray{public://前缀和数组vector<int>prefixSum;NumArray(vector<int>&nums){prefixSum.resize(nums.size()+1);prefix......
  • 9.28 开发MES系统日志四
    今天开发MES系统的流程图以及数据库表,因为对MES系统的不了解,所以先加上了最基本的人员管理以及车间管理等基本表信息。      ......
  • 9.30
    [实验任务一]:UML复习阅读教材第一章复习UML,回答下述问题:面向对象程序设计中类与类的关系都有哪几种?分别用类图实例说明。1、关联关系       ①、单向关联  ②、双向关联  ③、多重性关联   ④、聚合关联  ⑤、组合关联  2、依赖关......
  • Connector C++ 连接 MySQL 数据库之增删改查
    在vcpkg中折腾了mysql-connector-cpp8.0很久,一直连接不上远程数据库,后面查官方文档,mysql-connector-cpp8.0好像只支持MySQL8.0以上的数据库,本来想把远程服务器上的MySQL升级到MySQL8.0,后面发现测试服务器的配置有点拉跨,架不住MySQL8.0,但是vcpkg中又没有mysql-c......