配置环境
在终端输入这些密令:
bash
pip install paddlepaddle==2.6.2
pip install paddleocr==2.8.1
PaddlePaddle/PaddleOCR有关代码参考链接:
https://gitee.com/paddlepaddle/PaddleOCR/tree/v2.6.0
paddleocr快速使用及参数详解参考如下文章:
一、使用PaddleOCR库实现了图像中的文字检测与识别功能,并在原图上可视化识别结果
- 初始化OCR引擎
python
from paddleocr import PaddleOCR
import cv2
import numpy as np
ocr = PaddleOCR(use_angle_cls=True, use_gpu=False,show_log=False, lang='en')
use_angle_cls=True:启用文本方向分类(检测倾斜文字)
use_gpu=False:使用CPU运算
show_log=False:关闭日志输出
lang='en':设置识别英文文本
- 图像处理流程
python
frame=cv2.imread('img.png')
result = ocr.ocr(frame)
通过OpenCV读取img.png图像文件
调用OCR引擎进行文字检测与识别,返回包含文本位置和内容的结果
- 结果可视化
python
if not None in result:
for line in result[0]:
# 转换为整数坐标
pts_int = np.array(line[0], dtype=np.int32)
# 确保坐标数组的形状是 (n, 1, 2) 以符合 OpenCV 函数的要求
pts = pts_int.reshape((-1, 1, 2))
cv2.polylines(frame, [pts], True, (147, 20, 255),2)
cv2.putText(frame, line[1][0], (pts_int[0][0], pts_int[0][1]-10),cv2.FONT_HERSHEY_SIMPLEX, 1,
(0, 0, 255), 3)
遍历每个检测到的文本行:
line[0]:文本包围框的4个顶点坐标
line[1][0]:识别出的文本内容
使用红色((R=0, G=0, B=255))绘制文本标签
使用品红色((R=147, G=20, B=255))绘制多边形文本框
- 结果展示
python
cv2.imshow('x', frame)
cv2.waitKey(0)
原图img.png


根据结果图看出,对于图片文字能进行基础的英文识别
改进代码:
python
from paddleocr import PaddleOCR
import cv2
import numpy as np
from PIL import Image, ImageDraw, ImageFont新增了 PIL 相关库
#新增了中文绘制函数
def cv2AddChineseText(img, text, position, textColor=(0, 255, 0), textSize=30):
""" 向图片中添加中文 """
if (isinstance(img, np.ndarray)): # 判断是否OpenCV图片类型
img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))#实现array到image的转换
draw = ImageDraw.Draw(img) # 在img图片上创建一个绘图的对象
# 字体的格式
fontStyle = ImageFont.truetype( "simsun.ttc", textSize, encoding="utf-8")
draw.text(position, text, textColor, font=fontStyle) # 绘制文本
return cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)# 转换回OpenCV格式
#lang='en' → lang='ch'(从英文识别 → 改为中文识别)
ocr = PaddleOCR(use_angle_cls=True,use_gpu=True,show_log=False,lang='ch') #'ch'就是识别中文
frame=cv2.imread('img.png')
result = ocr.ocr(frame, cls=True)
if not None in result:
for line in result[0]:
# 转换为整数坐标
pts_int = np.array(line[0], dtype=np.int32)
# 确保坐标数组的形状是 (n, 1, 2) 以符合 OpenCV 函数的要求
pts = pts_int.reshape((-1, 1, 2))
zi=line[1][0]
x,y=pts_int[0]
cv2.polylines(frame, [pts], isClosed=True, color=(147, 20, 255), thickness=2)
frame = cv2AddChineseText(frame, zi, (x,y-30))
cv2.imshow( 'x',frame)
cv2.waitKey(0)
运行结果:能识别出中文打印并且将中文框起来。

二、OCR摄像头:
python
from paddleocr import PaddleOCR
import cv2
import numpy as np
from PIL import Image, ImageDraw, ImageFont
def cv2AddChineseText(img, text, position, textColor=(0, 255, 0), textSize=30):
""" 向图片中添加中文 """
if (isinstance(img, np.ndarray)): # 判断是否OpenCV图片类型
img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))#实现array到image的转换
draw = ImageDraw.Draw(img) # 在img图片上创建一个绘图的对象
# 字体的格式
fontStyle = ImageFont.truetype( "simsun.ttc", textSize, encoding="utf-8")
draw.text(position, text, textColor, font=fontStyle) # 绘制文本
return cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)# 转换回OpenCV格式
ocr = PaddleOCR(use_angle_cls=True,use_gpu=True,show_log=False,lang='ch') #'ch'就是识别中文
cap=cv2.VideoCapture(0)
while True:
_,frame=cap.read()
# frame=cv2.imread('img.png')
result = ocr.ocr(frame, cls=True)
if not None in result:
for line in result[0]:
# 转换为整数坐标
pts_int = np.array(line[0], dtype=np.int32)
# 确保坐标数组的形状是 (n, 1, 2) 以符合 OpenCV 函数的要求
pts = pts_int.reshape((-1, 1, 2))
zi=line[1][0]
x,y=pts_int[0]
cv2.polylines(frame, [pts], isClosed=True, color=(147, 20, 255), thickness=2)
frame = cv2AddChineseText(frame, zi, (x,y-30))
cv2.imshow( 'x',frame)
if cv2.waitKey(1)==27:
break
结果:能用摄像头实时识别画面中的文字并将它们打印输出
三、PyQt5 前端和 PaddleOCR 实现的实时中文 OCR 识别软件:
代码:
导入库:
python
import sys
import cv2
import numpy as np
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QMainWindow, QApplication
from paddleocr import PaddleOCR
from PIL import Image, ImageDraw, ImageFont
中文绘制函数:
python
def cv2AddChineseText(img, text, position, textColor=(0, 255, 0), textSize=30):
if isinstance(img, np.ndarray):
img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
draw = ImageDraw.Draw(img)
try:
fontStyle = ImageFont.truetype("simsun.ttc", textSize, encoding="utf-8")
except:
fontStyle = ImageFont.load_default()
draw.text(position, text, textColor, font=fontStyle)
return cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)
界面设计

python
# GUI前端页面设计
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(900, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
# 图像显示区域
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(30, 30, 640, 480))
self.label.setText("")
self.label.setScaledContents(True)
# 文本结果显示区域
self.textEdit = QtWidgets.QTextEdit(self.centralwidget)
self.textEdit.setGeometry(QtCore.QRect(690, 30, 180, 480))
self.textEdit.setReadOnly(True)
# 打开/关闭按钮
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(400, 530, 100, 40))
self.pushButton.setText("打开")
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "OCR实时识别"))
主逻辑类
连接 GUI、摄像头、OCR 识别,实现实时处理
python
# 主逻辑入口:摄像头 + OCR + 界面刷新
class PyQtMainEntry(QMainWindow, Ui_MainWindow):
def __init__(self):
super().__init__()
self.setupUi(self)
# 打开摄像头
self.camera1 = cv2.VideoCapture(0, cv2.CAP_DSHOW)
self.is_camera_opened = False
# 加载PaddleOCR模型
self.ocr = PaddleOCR(lang='ch', use_textline_orientation=True, show_log=False)
# 定时器:每30ms抓取一帧
self._timer = QtCore.QTimer(self)
self._timer.timeout.connect(self._queryFrame)
self._timer.setInterval(30)
self.pushButton.clicked.connect(self.slot1)
# 按钮开关控制
def slot1(self):
self.is_camera_opened = not self.is_camera_opened
if self.is_camera_opened:
self.pushButton.setText("关闭")
self._timer.start()
else:
self.pushButton.setText("打开")
self._timer.stop()
# =======================
# 核心:实时帧处理 + OCR识别
# =======================
def _queryFrame(self):
ret1, frame = self.camera1.read()
if not ret1:
return
frame = cv2.resize(frame, (640, 480))
# OCR识别
result = self.ocr.ocr(frame, cls=True)
text_list = []
if result is not None and result[0] is not None:
for line in result[0]:
pts_int = np.array(line[0], dtype=np.int32)
pts = pts_int.reshape((-1, 1, 2))
zi = line[1][0]
text_list.append(zi)
x, y = pts_int[0]
# 绘制文字框
cv2.polylines(frame, [pts], isClosed=True, color=(147, 20, 255), thickness=2)
# 绘制中文
frame = cv2AddChineseText(frame, zi, (x, y - 30))
# 右侧文本框显示结果
if text_list:
self.textEdit.setText("\n".join(text_list))
# 图像转为Qt格式显示
rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
h, w, ch = rgb.shape
bytes_per_line = ch * w
qimage = QtGui.QImage(rgb.data, w, h, bytes_per_line, QtGui.QImage.Format_RGB888)
self.label.setPixmap(QtGui.QPixmap.fromImage(qimage))
# 关闭窗口时释放资源
def closeEvent(self, event):
if self.camera1.isOpened():
self.camera1.release()
self._timer.stop()
event.accept()
主程序运行
python
# 主程序运行
if __name__ == "__main__":
app = QApplication(sys.argv)
window = PyQtMainEntry()
window.show()
sys.exit(app.exec_())
运行结果:

四、正则判断:
从一串文本中筛选出符合规则的「有效编码」,比如产品编号、设备码、序列号等,自动过滤掉普通英文单词。
代码:
python
import re
def process_string(input_string):
aa = []
# 用空格切分字符串
parts = input_string.split()
# 正则表达式1:包含数字和字母
pattern_alphanumeric = re.compile(r'(?=.*[a-zA-Z])(?=.*\d)[a-zA-Z\d-]{2,8}$')
# 正则表达式2:至少四个以上数字的纯数字
pattern_at_least_two_digits = re.compile(r'\d{4,7}$')
# 遍历每个切分后的部分
for part in parts:
# 检查是否包含数字和字母或者纯数字
if pattern_alphanumeric.match(part) or pattern_at_least_two_digits.match(part):
aa.append(part)
return aa
a = 'Aceite p04476'
b = 'sdighsg'
c = 's4967xl'
d = 'v0-4985'
e = 'shfsf v0-4985'
f = '123'
g = '1234568956'
h = '45825'
ylist = []
llist = [a, b, c, d, e, f, g, h]
for i in llist:
ma = process_string(i)
ylist.extend(ma)
print(ylist)
核心过滤函数 process_string
功能:输入一句话 → 输出筛选后的有效编码列表
内部两条规则:
• 规则 1:字母 + 数字组合(2--8 位)
• 规则 2:纯数字(4--7 位)
满足任意一条就保留,否则丢弃。
运行结果:
bash
C:\Users\Dell\AppData\Local\Programs\Python\Python39\python.exe D:\software\Pycharm\pyqt5库\2.正则判断.py
['p04476', 's4967xl', 'v0-4985', 'v0-4985', '45825']
五、三进一:
这段代码实现了一个可复用的周期触发装饰器 。它可以让任意函数每执行 N 次,就自动执行一次指定操作
- 定义装饰器工具
python
import re
# 定义一个"每调用n次就触发一次任务"的装饰器
def execute_after_n_calls(n, w2set):
# 真正的装饰器
def decorator(func):
# 包装函数:用来计数+执行
def wrapper(*args, **kwargs):
wrapper.count += 1 # 每次调用都 +1
result = func(*args, **kwargs) # 执行原来的函数
if wrapper.count % n == 0: # 每满 n 次
w2set() # 自动执行传入的函数
return result
wrapper.count = 0 # 初始化计数器
return wrapper
return decorator
- 定义被触发的函数 bb ()
python
def bb():
print('b')
- 给 aa () 加上装饰器
python
@execute_after_n_calls(3, bb)
def aa():
print('a')
- 测试调用 6 次
python
aa()
aa()
aa()
aa()
aa()
aa()
5.运行结果
python
a
a
a
b
a
a
a
b
六、threading 库
实现并发执行任务,让程序可以同时做多件事。
python
# 导入线程库 和 时间库
import threading
import time
# ======================
# 案例1:最简单的线程(无参数)
# ======================
def worker():
print("线程开始执行")
# 循环5次模拟工作
for i in range(5):
print(f"线程正在工作:{i}")
print("线程执行完毕")
# 创建线程:target=要执行的函数名
thread = threading.Thread(target=worker)
# 启动线程
thread.start()
# 主线程不会等待子线程,会直接往下执行
print("****主线程继续执行*****")
print("-"*50) # 分割线
# ======================
# 案例2:带参数的多线程(两个线程同时跑)
# ======================
def worker(name):
print(f"{name}线程开始执行")
for i in range(5):
print(f"{name}正在工作:{i}")
time.sleep(0.5) # 暂停0.5秒,让切换效果更明显
print(f"{name}线程执行完毕")
# 创建线程1,传入参数 args=("线程1",)
thread1=threading.Thread(target=worker,args=("线程1",))
# 创建线程2
thread2=threading.Thread(target=worker,args=("线程2",))
# 启动两个线程 → 同时运行、交替打印
thread1.start()
thread2.start()
print("****主线程继续执行******")
print("-"*50)
# ======================
# 案例3:带延时的线程(演示并发等待)
# ======================
def run(t):
time.sleep(t) # 暂停 t 秒
print(f'我等了{t}秒')
# 创建线程:3秒后输出
t1 = threading.Thread(target=run,args=(3,))
# 创建线程:6秒后输出
t2 = threading.Thread(target=run,args=(6,))
# 启动后两个线程同时计时,不是先后执行!
t1.start()
print('开始计时')
t2.start()
运行结果:
bash
C:\Users\Dell\AppData\Local\Programs\Python\Python39\python.exe D:\software\Pycharm\pyqt5库\threading库.py
线程开始执行
线程正在工作:0****主线程继续执行*****
--------------------------------------------------
线程正在工作:1
线程正在工作:2
线程正在工作:3
线程正在工作:4
线程执行完毕
线程1线程开始执行
线程1正在工作:0
线程2线程开始执行****主线程继续执行******
线程2正在工作:0
--------------------------------------------------
开始计时
线程2正在工作:1
线程1正在工作:1
线程2正在工作:2线程1正在工作:2
线程1正在工作:3
线程2正在工作:3
线程2正在工作:4
线程1正在工作:4
线程2线程执行完毕
线程1线程执行完毕
我等了3秒
我等了6秒
进程已结束,退出代码0
七、基于 OpenCV 的实时颜色识别系统 ,用于从摄像头画面中检测棕色牛皮纸箱。
代码
python
# 导入OpenCV库和数值计算库numpy
import cv2
import numpy as np
# 打开默认摄像头(0表示系统默认摄像头)
cap = cv2.VideoCapture(0)
# 持续循环读取摄像头画面
while True:
try:
# 读取一帧图像
# ret:是否读取成功
# frame3:读取到的画面
ret, frame3 = cap.read()
# 将图像从BGR格式转换为HSV颜色空间
# HSV更适合做颜色识别
hsv_image = cv2.cvtColor(frame3, cv2.COLOR_BGR2HSV)
# 定义棕色在HSV空间中的下限范围
lower_brown = np.array([10, 30, 30])
# 定义棕色在HSV空间中的上限范围
upper_brown = np.array([30, 255, 255])
# 根据颜色范围生成掩码
# 棕色区域变成白色(255),其他区域变成黑色(0)
mask = cv2.inRange(hsv_image, lower_brown, upper_brown)
# 显示掩码图像(黑白二值图)
cv2.imshow('mask', mask)
# 统计掩码中白色像素的数量(即棕色区域像素数)
white_pixels = np.sum(mask == 255)
# 计算整张图像的总像素数
total_pixels = mask.shape[0] * mask.shape[1]
# 计算棕色区域占整个画面的百分比
color_percentage = (white_pixels / total_pixels) * 100
# 如果棕色区域占比 >= 20%,判定为牛皮纸箱
if color_percentage >= 20:
print("检测到牛皮纸箱")
# 显示原始摄像头画面
cv2.imshow('Filtered Image1', frame3)
# 按下ESC键退出循环
if cv2.waitKey(1) == 27:
break
# 出现异常时跳过(防止画面卡顿/崩溃)
except:
pass
运行结果:
