基于Pyqt5实现笔记本摄像头拍照及PaddleOCR测试

news2024/11/16 7:21:32

在上一篇文章《基于百度飞桨PaddleOCR的图片文字识别》的基础上,做了个简单的扩展:
1、通过Pyqt5做个简单的UI界面;
2、通过OpenCV操作笔记本摄像头进行视频显示、拍照等功能;
3、加载图片;
4、对拍照图片或者加载的图片,进行PaddleOCR的图片文字识别;

一、UI界面设计

1、PyCharm工程中,在ocrtest文件夹下新建ocr_camera.ui文件,然后右键,找到"External Tools",选择QT Designer,进入QT5的UI设计界面
在这里插入图片描述
2、添加相应的控件、设置好参数。如显示视频及图片的QLable,默认情况下是透明的,设置背景色方便设置大小。
QLable设置背景色:2.1、选中autoFillBackground
2.2、改变Window调色板
在这里插入图片描述
最终的UI界面如下:
在这里插入图片描述
3、保存ui文件。

如果先打开QT Designer,设计后,保存ocr_camera.ui到ocrtest文件夹下,效果是一样的。

4、回到PyCharm工程,ocr_camera.ui文件,然后右键,找到"External Tools",选择PyUIC,将UI设计文件转换为ocr_camera.py文件。
在这里插入图片描述
ocr_camera.py文件如下:

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'ocr_camera.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.


from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_ocr_camera(object):
    def setupUi(self, ocr_camera):
        ocr_camera.setObjectName("ocr_camera")
        ocr_camera.resize(1278, 750)
        self.imageocrButton = QtWidgets.QPushButton(ocr_camera)
        self.imageocrButton.setGeometry(QtCore.QRect(970, 20, 81, 23))
        self.imageocrButton.setObjectName("imageocrButton")
        self.takephotosButton = QtWidgets.QPushButton(ocr_camera)
        self.takephotosButton.setGeometry(QtCore.QRect(670, 20, 75, 23))
        self.takephotosButton.setObjectName("takephotosButton")
        self.closeCameraButton = QtWidgets.QPushButton(ocr_camera)
        self.closeCameraButton.setGeometry(QtCore.QRect(770, 20, 75, 23))
        self.closeCameraButton.setObjectName("closeCameraButton")
        self.openCameraButton = QtWidgets.QPushButton(ocr_camera)
        self.openCameraButton.setGeometry(QtCore.QRect(570, 20, 75, 23))
        self.openCameraButton.setObjectName("openCameraButton")
        self.loadImageButton = QtWidgets.QPushButton(ocr_camera)
        self.loadImageButton.setGeometry(QtCore.QRect(870, 20, 75, 23))
        self.loadImageButton.setObjectName("loadImageButton")
        self.showtext = QtWidgets.QTextEdit(ocr_camera)
        self.showtext.setGeometry(QtCore.QRect(450, 70, 791, 601))
        self.showtext.setObjectName("showtext")
        self.cameralabel = QtWidgets.QLabel(ocr_camera)
        self.cameralabel.setGeometry(QtCore.QRect(10, 30, 401, 281))
        palette = QtGui.QPalette()
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Base, brush)
        brush = QtGui.QBrush(QtGui.QColor(0, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Window, brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Base, brush)
        brush = QtGui.QBrush(QtGui.QColor(0, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Window, brush)
        brush = QtGui.QBrush(QtGui.QColor(0, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Base, brush)
        brush = QtGui.QBrush(QtGui.QColor(0, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Window, brush)
        self.cameralabel.setPalette(palette)
        self.cameralabel.setTabletTracking(False)
        self.cameralabel.setAcceptDrops(False)
        self.cameralabel.setAutoFillBackground(True)
        self.cameralabel.setText("")
        self.cameralabel.setOpenExternalLinks(False)
        self.cameralabel.setObjectName("cameralabel")
        self.imagelabel = QtWidgets.QLabel(ocr_camera)
        self.imagelabel.setGeometry(QtCore.QRect(10, 380, 401, 281))
        palette = QtGui.QPalette()
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Base, brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 170, 127))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Window, brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Base, brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 170, 127))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Window, brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 170, 127))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Base, brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 170, 127))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Window, brush)
        self.imagelabel.setPalette(palette)
        self.imagelabel.setAutoFillBackground(True)
        self.imagelabel.setText("")
        self.imagelabel.setObjectName("imagelabel")

        self.retranslateUi(ocr_camera)
        QtCore.QMetaObject.connectSlotsByName(ocr_camera)

    def retranslateUi(self, ocr_camera):
        _translate = QtCore.QCoreApplication.translate
        ocr_camera.setWindowTitle(_translate("ocr_camera", "Form"))
        self.imageocrButton.setText(_translate("ocr_camera", "图片文字识别"))
        self.takephotosButton.setText(_translate("ocr_camera", "拍照"))
        self.closeCameraButton.setText(_translate("ocr_camera", "关闭摄像头"))
        self.openCameraButton.setText(_translate("ocr_camera", "打开摄像头"))
        self.loadImageButton.setText(_translate("ocr_camera", "导入图片"))

到此,界面设计完成。

二、功能实现

1、ocrtest文件夹下新建main.py文件。所有功能在此文件实现。
注意:
1、main.py里添加import paddleocr;
2、paddleocr.py注释掉“if name == ‘main’:”这段测试代码,main.py中有实现。

话不多说,直接上代码,main.py:

# -*- coding: utf-8 -*-

import os
import sys

from PyQt5 import QtGui
from PyQt5.Qt import *
import cv2
from ocr_camera import Ui_ocr_camera # 增加文本显示器
import paddleocr
from ppocr.utils.logging import get_logger

logger = get_logger()
from ppocr.utils.utility import get_image_file_list


class ocrTestUI(Ui_ocr_camera, QWidget):
    def __init__(self):
        super().__init__()

        self.setupUi(self)
        self.timer = QTimer()
        self.timer.timeout.connect(self.show_stream)    #定时刷新摄像头视频流
        self.cap = cv2.VideoCapture()                   #初始化摄像头

        self.cameralabel.setScaledContents(True)        #摄像头自适应
        self.imagelabel.setScaledContents(True)         #图片自适应

        self.openCameraButton.clicked.connect(self.openCamera)      #打开摄像头
        self.takephotosButton.clicked.connect(self.takePhotos)      #拍照
        self.closeCameraButton.clicked.connect(self.closeCamera)    #关闭摄像头
        self.loadImageButton.clicked.connect(self.loadImage)        #加载图片
        self.imageocrButton.clicked.connect(self.imageRecognition)  #图片OCR测试

    def show_stream(self):
        flag, self.image = self.cap.read()                  #从视频流中读取图片
        image_show = cv2.resize(self.image, (1280, 720))    #把读到的帧的大小重新设置为 1280*720
        width, height = image_show.shape[:2]
        image_show = cv2.cvtColor(image_show, cv2.COLOR_BGR2RGB)    #opencv读的通道是BGR,要转成RGB
        #把读取到的视频数据变成QImage形式(图片数据、高、宽、RGB颜色空间,三个通道各有2**8=256种颜色)
        self.showImage = QtGui.QImage(image_show.data, height, width, QImage.Format_RGB888)
        self.cameralabel.setPixmap(QPixmap.fromImage(self.showImage))  #往显示视频的Label里显示QImage


    def openCamera(self):
        self.cap = cv2.VideoCapture(0)  #打开摄像头
        self.timer.start(40)            #每40毫秒读取一次,即刷新率为25帧

    def takePhotos(self):
        global ocrimage
        if self.cap.isOpened():     #摄像头已打开
            self.imagelabel.setPixmap(QtGui.QPixmap.fromImage(self.showImage))
            self.showImage.save('./img/temp.jpg')
            ocrimage = 'img/temp.jpg'
        else:                       #摄像头未打开
            self.cap = cv2.VideoCapture(0)
            flag, self.image = self.cap.read()                  #从视频流中读取图片
            image_show = cv2.resize(self.image, (1280, 720))    #把读到的帧的大小重新设置为 1280*720
            width, height = image_show.shape[:2]
            image_show = cv2.cvtColor(image_show, cv2.COLOR_BGR2RGB)  # opencv读的通道是BGR,要转成RGB
            #把读取到的视频数据变成QImage形式(图片数据、高、宽、RGB颜色空间,三个通道各有2**8=256种颜色)
            self.showImage = QtGui.QImage(image_show.data, height, width, QImage.Format_RGB888)
            self.imagelabel.setPixmap(QPixmap.fromImage(self.showImage))  #往显示图片的Label里显示QImage
            self.showImage.save('./img/temp.jpg')
            ocrimage = 'img/temp.jpg'
            self.cap.release()      #释放摄像头

    def closeCamera(self):
        self.timer.stop()           #停止读取
        self.cap.release()          #释放摄像头
        self.cameralabel.clear()    #清除cameralabel组件上的图片

    def loadImage(self):
        global ocrimage
        fname, _ = QFileDialog.getOpenFileName(self, '选择图片', './', 'Image files(*.jpg *.gif *.png*.bmp)')
        self.showImage = fname
        ocrimage = self.showImage
        self.imagelabel.setPixmap(QPixmap(self.showImage))
        self.showtext.append("loadImage {}".format(ocrimage))

    def imageRecognition(self):
        global ocrimage
        self.showtext.append("loadImage {}".format(ocrimage))
        self.OCRmain(ocrimage)


    def OCRmain(self,image_dir):
        #self.showtext.append("hello ")
        args = paddleocr.parse_args(mMain=True)

        #image_dir = 'img/test.jpg'
        self.showtext.append(image_dir)
        image_file_list = get_image_file_list(image_dir)
        if len(image_file_list) == 0:
            self.showtext.append("no images find")

        engine = paddleocr.PaddleOCR()

        for img_path in image_file_list:
            img_name = os.path.basename(img_path).split('.')[0]
            logger.info('{}{}{}'.format('*' * 10, img_path, '*' * 10))

            result = engine.ocr(img_path,
                                det=True,   #识别
                                rec=True,   #检测
                                cls=True)   #使用方向分类器识别180度旋转文字
            if result is not None:
                for idx in range(len(result)):
                    res = result[idx]
                    for line in res:
                        logger.info(line)
                        self.showtext.append("{}".format(line))
            else:
                print("result is none")

            # 显示结果
            from PIL import Image

            result = result[0]
            image = Image.open(img_path).convert('RGB')
            boxes = [line[0] for line in result]
            txts = [line[1][0] for line in result]
            scores = [line[1][1] for line in result]
            im_show = paddleocr.draw_ocr(image, boxes, txts, scores, font_path='./fonts/simfang.ttf')
            im_show = Image.fromarray(im_show)
            im_show.save('img/result.jpg')


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = ocrTestUI()
    window.show()
    sys.exit(app.exec())

三、测试

1、打开摄像头,拍照、关闭摄像头如下:
在这里插入图片描述
打开摄像头,上面的lable会显示视频流。拍照后,下面lable显示图片。
也可以不用打开摄像头,直接拍照。

2、拍照图片文字识别,结果如下:
在这里插入图片描述
在这里插入图片描述

3、加载图片并识别,结果如下:

在这里插入图片描述
在这里插入图片描述

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

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

相关文章

Python贝叶斯回归分析住房负担能力数据集

我想研究如何使用pymc3在贝叶斯框架内进行线性回归。根据从数据中学到的知识进行推断。 最近我们被客户要求撰写关于贝叶斯回归的研究报告,包括一些图形和统计输出。 视频:线性回归中的贝叶斯推断与R语言预测工人工资数据案例 贝叶斯推断线性回归与R语言…

猿如意---Visual Studio手把手教学安装和下载.

亲自为大家示范如何使用猿如意以及在猿如意当中下载,安装和使用python3.10版本,让大家喜欢上这款好用的app—猿如意。 文章目录前言一、手把手教你猿如意的安装、下载二、手把手教你Visual Studio的安装、下载1.找到我需要的工具2.我需要的工具的安装、下…

最新Crack:foxit pdf sdk 8.4.1_win_java

Foxit pdf sdk一个功能强大、易于使用的核心 API,用于呈现、查看、注释、签名、保护和管理 PDF 中的表单。 Foxit pdf sdk开发人员的最佳工具 快速整合 C、C#、C、Python 和 Java 中功能强大且易于使用的核心 API。系统要求:Windows XP、Vista、7、8 和…

【云原生 | Kubernetes 实战】12、K8s 四层代理 Service 入门到企业实战应用(上)

目录 一、Service 四层代理基本介绍 1.1 四层负载均衡 Service:概念、原理解读 1 为什么要有Service? 2 Service 概述 3 Service 工作原理 4 kubernetes 集群中有三类 IP 地址 二、创建 Service 资源 2.1 Service 的四种类型 2.2 Service 的端口…

k8s编程operator实战之云编码平台——①架构设计

文章目录1、想法来源2、初步设想2.1 通过反向代理的方式访问后端Pod3、架构设计3.1 技术栈3.2 架构设计k8s编程operator系列:k8s编程operator——(1) client-go基础部分k8s编程operator——(2) client-go中的informerk8s编程operator——(3) 自定义资源CRDk8s编程op…

SpringSecurity管理接口权限

使用SpringSecurity管理具体接口访问权限。 需要先有授权服务器和资源服务器 Springboot利用Security做OAuth2授权验证_LO嘉嘉VE的博客-CSDN博客 Springboot利用Security做OAuth2资源服务器_LO嘉嘉VE的博客-CSDN博客 配置接口具体访问权限再有以上两个的基础上就比较简单了…

antd-vue 累加表单编辑和删除(完善版)

一、业务场景&#xff1a; 最近在使用Antd-Vue组件库的时候&#xff0c;发现在累加表单 时没有直接可以用的&#xff0c;必须自己在官网上手动合并几个才能实现&#xff0c;为了大家后面遇到和我一样的问题&#xff0c;给大家分享一下 二、具体实现步骤&#xff1a; <temp…

新一代最强开源UI自动化测试神器Playwright(Java版)环境搭建

Playwright 是专门为满足端到端测试的需要而创建的。Playwright 支持所有现代渲染引擎&#xff0c;包括 Chromium、WebKit 和 Firefox。在 Windows、Linux 和 macOS 上进行本地测试或在 CI 上进行测试&#xff0c;无外设或带本机移动仿真。 一.安装 在JAVA中&#xff0c;使用…

嵌入式技术之IAP,自从有了它老板再也不担心我的代码了!(上)

1.惨痛的教训 那是一个严寒的冬日&#xff0c;客户在现场使用我们公司新研发的设备&#xff0c;设备最初设计可以允许最多连接20个温湿度传感器&#xff0c;但是由于现场空间非常大&#xff0c;客户要求连接30个温湿度传感器。这个需求修改非常简单&#xff0c;只用修改程序中…

帮公司面试了个要25K的测试,我问了他这些问题...

深耕IT行业多年&#xff0c;我们发现&#xff0c;对于一个程序员而言&#xff0c;能去到一线互联网公司&#xff0c;会给我们以后的发展带来多大的影响。 很多人想说&#xff0c;这个我也知道&#xff0c;但是进大厂实在是太难了&#xff0c;简历投出去基本石沉大海&#xff0…

spring security安全认证登录全流程分析

文章目录前言一、登录时序图二、配置与代码1.引入库2.代码文件参考文档前言 本文章主要从spring security安全认证登录内部调用流程来流程分析登录过程。 一、登录时序图 时序原图 二、配置与代码 1.引入库 pom.xml&#xff1a; <!-- Spring框架基本的核心工具 -->&…

截至到2022年12月12日,知网最新改进 YOLO 核心论文合集 | 22篇创新点速览

截至到2022年12月12日&#xff0c;知网最新改进YOLO核心论文合集 本篇博文仅供学习交流&#xff0c;不对文章质量进行评价&#xff0c;请尊重每一位同学的科研成果&#x1f91d;。 文章目录截至到2022年12月12日&#xff0c;知网最新改进YOLO核心论文合集引言&#x1f4a1;0. 什…

Vue.use()的用法详解

目录 &#x1f53d; 前言 &#x1f53d; 官方解释 &#x1f53d; Demo演示 &#x1f388; Object对象 &#x1f449; 创建项目 &#x1f449; 创建组件 &#x1f449; 使用组件 &#x1f388; function函数 &#x1f449; 创建函数 &#x1f449; 引入 &#x1f449…

机器人与视觉,基于坐标系的运动偏移

基于可移动坐标系的机器人坐标偏移 在生产过程中&#xff0c;当需要建造多个坐标系的时候&#xff0c;我们可以采用基于坐标系偏移&#xff0c;可以实现使用机器人坐标系直接完成多个坐标系的联动。 由于实现多个坐标系的联动情况&#xff0c;那么通常都会伴随着坐标系的移动和…

力扣1781. 子字符串的美丽值之和(cpp实现+解析)

文章目录1781.子字符串的美丽值之和完整代码1781.子字符串的美丽值之和 力扣传送门&#xff1a; https://leetcode.cn/problems/sum-of-beauty-of-all-substrings/description/ 题目描述&#xff1a; 一个字符串的 美丽值 定义为&#xff1a;出现频率最高字符与出现频率最低字…

CMake中add_compile_options/target_compile_options的使用

CMake中的add_compile_options命令用于向源文件的编译添加选项&#xff0c;其格式如下&#xff1a; add_compile_options(<option> ...) 将选项添加到COMPILE_OPTIONS目录属性。从当前目录及以下目录编译target时&#xff0c;将使用这些选项。 add_compile_option…

48-90-Scala-函数式编程基础特性等

48-Scala-函数式编程&#xff1a; 函数式编程 1、完全面向对象编程 2、函数式编程&#xff0c;万物皆函数&#xff0c;程序语句的集合&#xff0c;称为函数。类中的函数称之方法。函数无重载重写概念&#xff0c;方法可以。函数可以嵌套 3、函数的定义def test3(s:String):…

电子书资源:分享10个非常好用的免费书籍资源网站

❤️作者主页&#xff1a;IT技术分享社区 ❤️作者简介&#xff1a;大家好,我是IT技术分享社区的博主&#xff0c;从事C#、Java开发九年&#xff0c;对数据库、C#、Java、前端、运维、电脑技巧等经验丰富。 ❤️个人荣誉&#xff1a; 数据库领域优质创作者&#x1f3c6;&#x…

Qt扫盲-QCheckBox 理论总结

QCheckBox 理论总结1. 简述2. 分组3. 状态&信号4. 外观&快捷键1. 简述 QCheckBox是一个选项按钮&#xff0c;可以 选中 或 未选中。复选框通常用于表示应用程序中可以启用或禁用的功能&#xff0c;而不会影响其他功能。可以实现不同类型的行为。一般是很多个联用的。 …

Cookie、Session、Token比较

1 Cookie cookie 指的就是浏览器里面能永久存储的一种数据&#xff0c;仅仅是浏览器实现的一种数据存储功能。 cookie由服务器生成&#xff0c;发送给浏览器&#xff0c;浏览器把cookie以 key-value 形式保存到某个目录下的文本文件内&#xff0c;下一次请求同一网站时会把该…