-
安装python,pycharm,自行安装。
-
Python下安装OpenCv
2.1 打开cmd,先安装opencv-python
pip install opencv-python --user -i https://pypi.tuna.tsinghua.edu.cn/simple
2.2 再安装opencv-contrib-python
pip install opencv-contrib-python --user -i https://pypi.tuna.tsinghua.edu.cn/simple
3.Pycharm安装opencv-python
打开pycharm,然后打开setting,打开python解析器
点击Go to tool window。下面红框处管理和下载python依赖包
点击下图的设置,然后点击管理仓库
新增python包仓库: https://pypi.tuna.tsinghua.edu.cn/simple/
在这里搜索并下载opencv-python,numpy
下载完成,新建py文件,执行代码。有窗口输出该路径的图片就说明成功了。
import cv2 as cv# 这段代码是测试opencv是否正常安装。运行下面这段代码出现图片就是成功的
src = cv.imread("C:\\Users\Administrator\Desktop\\city1.jpg")
cv.namedWindow("input image",cv.WINDOW_AUTOSIZE)
cv.imshow("input image",src)
cv.waitKey(0)
cv.destroyAllWindows()
print("hi python")
-
下载Tesseract OCR,去官网 https://github.com/UB-Mannheim/tesseract/wiki
下载exe。安装完成后,需要设置Tesseract-OCR的系统环境。详细看这篇文章
https://blog.csdn.net/qq_38463737/article/details/109679007 -
下载Tesseract OCR的语言包,中文语言包和英文语言包。
去官网 https://github.com/tesseract-ocr/tessdata 下载eng.traineddata和chi_sim.traineddata
然后把那两个文件放到**/Tesseract-OCR/tessdata
-
pycharm 的python包 安装pytesseract
-
在项目文件.venv/Lib/site-packages/pytesseract/pytesseract.py 文件中修改变量tesseract_cmd,路径自行修改。 这是为了解决BUG:”tesseract is not installed or it‘s not in your PATH“
-
安装gTTS 谷歌语音播报,pillow,pyttsx3 离线语音播报。
-
在手机上下载“IP 摄像头”,并安装。这里我在应用宝里下载了 IP 摄像头。使用该软件,要电脑连接手机热点,同处在局域网内。
10,全部py代码如下
# 本代码参考了https://blog.csdn.net/weixin_35752233/article/details/142606296 , https://blog.csdn.net/m0_58892312/article/details/120923578 和 AI
# 人脸模型库文件“ haarcascade_frontalface_default.xml ”,帮助摄像头获取的画面去对比
# 1. 第二句代码中的admin为我的IP摄像头用户名, admin为我的IP摄像头密码,这个可以在手机APP的设置里查看和修改,代码中的要使用自己的用户名、密码。
# 2. @后面的地址是局域网IP地址,这个在打开IP摄像头服务器之后的界面就能看到,也需要修改为自己的地址。
# 3.代码的其他部分无需修改。
import time
import cv2 as cv
import pytesseract
import numpy as np
import pyttsx3
from gtts import gTTS# 图像的裁剪和缩放是图像预处理的两个基本操作。裁剪主要是根据需要对图像的特定区域进行选取,剔除无效或干扰信息。缩放则是为了满足特定的分辨率或图像尺寸需求,对图像的大小进行调整。
# 裁剪图片
def crop_image(image, x, y, width, height):return image[y:y + height, x:x + width]# 缩放图片
def resize_image(image, width, height):return cv.resize(image, (width, height))# 灰度化. 图像的灰度化和二值化是将图像从彩色转换到灰度图像和黑白图像的过程,这些转换对于提高OCR的准确性和效率至关重要。
def to_grayscale(image):return cv.cvtColor(image, cv.COLOR_BGR2GRAY)# 二值化.
def to_binary(image, threshold=127, maxval=255):return cv.threshold(image, threshold, maxval, cv.THRESH_BINARY)[1]# 噪声去除是图像预处理中非常重要的一步。它通常通过滤波技术实现,可以减少图像中的随机噪声,提高图像质量,有助于后续的文字检测和识别。
def remove_noise(image, kernel_size=3):return cv.medianBlur(image, kernel_size)# 文本行检测 和字符分割是预处理的高级步骤,它们是为了从图像中准确地分离出单独的字符或文本行,这对于OCR识别至关重要。
def detect_text_lines(image):# 使用Canny边缘检测算法edged = cv.Canny(image, 100, 200)# 找到轮廓contours, _ = cv.findContours(edged, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)return contours# 字符分割
def segment_characters(image, contours):characters = []for contour in contours:x, y, w, h = cv.boundingRect(contour)roi_image = image[y:y + h, x:x + w]characters.append(roi_image)return characters# 识别并截取红色区域
def extract_red_region(image):# 转换为HSV颜色空间hsv = cv.cvtColor(image, cv.COLOR_BGR2HSV)# 定义红色的范围lower_red = np.array([0, 120, 70])upper_red = np.array([10, 255, 255])mask1 = cv.inRange(hsv, lower_red, upper_red)lower_red = np.array([170, 120, 70])upper_red = np.array([180, 255, 255])mask2 = cv.inRange(hsv, lower_red, upper_red)# 合并两个掩码mask = mask1 + mask2# 形态学操作kernel = np.ones((5, 5), np.uint8)mask = cv.morphologyEx(mask, cv.MORPH_CLOSE, kernel)mask = cv.morphologyEx(mask, cv.MORPH_OPEN, kernel)return mask# 文字保存为临时mp3文件
def text_to_speech(text, lang='en'):# 创建gTTS对象tts = gTTS(text=text, lang=lang)# 保存为临时文件temp_file = "temp_audio.mp3"tts.save(temp_file)return temp_file# 读取视频信息。 # @前为账号密码,@后为ip地址
cap = cv.VideoCapture("http://admin:admin@192.168.169.143:8081/video")
# cap = cv.VideoCapture(0)
while cap.isOpened():# 读取一帧图片f, image = cap.read()# 保存当前帧为图片文件cv.imwrite('captured_image.jpg', image)print("图片已保存为 captured_image.jpg")time.sleep(0.5)# 项目相对路径下captured_image.jpg,自行修改文件路径picture = cv.imread("D:\\download_software\\python_project\\camera_test\\captured_image.jpg")# 提取红色区域 -> 红色底纹白颜色文字red_mask = extract_red_region(picture)# 查找轮廓contours, _ = cv.findContours(red_mask, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)for contour in contours:x, y, w, h = cv.boundingRect(contour)roi = picture[y:y + h, x:x + w]# ps:没有必要灰度处理和二值化处理,因为红色区域的图像已经很清楚了# # 转换为灰度图像# gray_picture = cv.cvtColor(roi, cv.COLOR_BGR2GRAY)# # 二值化处理# _, binary_picture = cv.threshold(gray_picture, 200, 255, cv.THRESH_BINARY_INV)# 使用Tesseract OCR识别文字text = pytesseract.image_to_string(roi, config='--psm 6',lang="eng")print("OCR识别结果:" + text)cv.imshow("Red Region", roi)# 如果文本包含MAU或者AHU,播放mp3语音进行报警if "MAU" in text or "AHU" in text:# 创建语音引擎engine = pyttsx3.init()# 进行语音播报 指定要播报的文本engine.say(text)# 阻止 没播报完程序就退出engine.runAndWait()# 使用OpenCV的自定义函数进行图像预处理# # 设定裁剪区域的坐标和尺寸# x, y, width, height = 100, 100, 200, 200# cropped_image = crop_image(image, x, y, width, height)## # 设定缩放尺寸# new_width, new_height = 300, 300# resized_image = resize_image(cropped_image, new_width, new_height)# 读取图片并转换为灰度图# gray_picture = cv.cvtColor(picture, cv.COLOR_BGR2GRAY)# 读取图片并进行二值化# _, binary_picture = cv.threshold(gray_picture, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)# 读取图片并去除噪声# noise_free_picture = remove_noise(binary_picture)# 使用Tesseract进行OCR处理 chi_sim | eng# text = pytesseract.image_to_string(noise_free_picture,lang="eng")# 打印OCR结果# print("OCR识别结果:" + text)# cv.imshow("Video Stream", picture)#退出视频识别if cv.waitKey(1) & 0xFF == ord('q'):breakcap.release()
cv.destroyAllWindows()
- 运行效果展示。我手机的IP摄像头拍摄正对着wps那块区域,识别出来的红色区域在左上角。因为OCR识别使用我用的是english语言包,所以识别文字内容不太准确,汉字没有识别出来,但是我这里的需求只要识别英文单词就可以了。此时,电脑正在播放识别出来的文字内容。大致需求已经实现了。
【更新于2024-12-10】本次更新步骤10中的代码。因为步骤10的代码运行一段时间后会卡顿,是while循环把1秒内所拍摄的每一帧画面都进行了处理,导致主进程处理缓慢,后续时间识别的图像帧堆积在主进程的栈中,会导致识别延迟。
本次更新代码结合了队列、fps、线程等概念优化代码。1. 降低fps,在1秒内仅识别几帧图像,降低图像处理次数。 2. 主进程仅识别图像,提取并分割红色区域。开另一个线程进行ocr识别红色区域内的文字。 3. 主进程识别到的红色区域,进入ocr_queue。详细代码如下:
# 本代码参考了https://blog.csdn.net/weixin_35752233/article/details/142606296 , https://blog.csdn.net/m0_58892312/article/details/120923578 和 AI
# 1. 第二句代码中的admin为我的IP摄像头用户名, admin为我的IP摄像头密码,这个可以在手机APP的设置里查看和修改,代码中的要使用自己的用户名、密码。
# 2. @后面的地址是局域网IP地址,这个在打开IP摄像头服务器之后的界面就能看到,也需要修改为自己的地址。
import time
import cv2 as cv
import pytesseract
import numpy as np
import pyttsx3
import keyboard
from queue import Queue
from threading import Thread# 识别并截取红色区域
def extract_red_region(image):# 转换为HSV颜色空间hsv = cv.cvtColor(image, cv.COLOR_BGR2HSV)# 定义红色的范围lower_red = np.array([0, 120, 70])upper_red = np.array([10, 255, 255])mask1 = cv.inRange(hsv, lower_red, upper_red)lower_red = np.array([170, 120, 70])upper_red = np.array([180, 255, 255])mask2 = cv.inRange(hsv, lower_red, upper_red)# 合并两个掩码mask = mask1 + mask2# 形态学操作kernel = np.ones((5, 5), np.uint8)mask = cv.morphologyEx(mask, cv.MORPH_CLOSE, kernel)mask = cv.morphologyEx(mask, cv.MORPH_OPEN, kernel)return mask# 创建语音引擎
engine = pyttsx3.init()
# 设置发音速率,默认值为200
rate = engine.getProperty('rate')
engine.setProperty('rate', rate - 30)# 创建队列,队列存放每帧识别出来的红色区域
ocr_queue = Queue(maxsize=10)
#停止标志
stop_flag = False# OCR处理线程,处理红色区域
def ocr_thread():global stop_flag,jwhile not stop_flag:# start_time = time.time()if not ocr_queue.empty():roi = ocr_queue.get()# 在线程里面展示不了红色区域的图像 In OpenCV, the cv.imshow() function is not thread-safe,线程不安全# cv.imshow("Red Region in ocr_queue", roi)text = pytesseract.image_to_string(roi, lang="eng")if len(text) > 0:print("OCR识别结果:" + text)if any(keyword in text for keyword in ["MAU", "NAU", "nAU", "AHU","PHF-","PF-"]):# 打印高亮报警信息highlighted_text = "\033[1;31m" + text + "\033[0m"print(highlighted_text)engine.say("M A U机组或A H U机组或排风机报警,请确认。")engine.runAndWait()# end_time = time.time()# processing_time_ms = (end_time - current_time) * 1000# print(f"{processing_time_ms:.2f} milliseconds") # 花费12毫秒else:print("ocr_queue is empty")time.sleep(0.1)# 启动OCR线程
ocr_thread = Thread(target=ocr_thread)
ocr_thread.start()# 读取视频信息
cap = cv.VideoCapture("http://admin:admin@10.31.51.173:8081/video")# 设置帧率 Frames Per Second
fps = 5
# 帧与帧之间的时间间隔
frame_interval = 1 / fpslast_frame_time = time.time()
i = 0while not stop_flag:current_time = time.time()if current_time - last_frame_time >= frame_interval:i += 1print(i)# 读取一帧图片ret, picture = cap.read()if not ret:break# 将图像顺时针旋转90度rotated_picture = cv.rotate(picture, cv.ROTATE_90_CLOCKWISE)# 提取红色区域red_mask = extract_red_region(rotated_picture)# 查找轮廓contours, _ = cv.findContours(red_mask, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)for contour in contours:x, y, w, h = cv.boundingRect(contour)roi = rotated_picture[y:y + h, x:x + w]if not ocr_queue.full():ocr_queue.put(roi)cv.imshow("Red Region", roi)# 显示图像(每5帧显示一次)if i % 5 == 0:cv.imshow("rotated_picture", rotated_picture)last_frame_time = current_time# end_time = time.time()# processing_time_ms = (end_time - current_time) * 1000# print(f"{processing_time_ms:.2f} milliseconds") # 花费10毫秒# 检查退出条件if cv.waitKey(1) & 0xFF == ord('q') or keyboard.is_pressed('q'):stop_flag = True# 清理资源
cap.release()
cv.destroyAllWindows()
stop_flag = True
ocr_thread.join()
- 识别结果:右上角是识别的红色区域,右下是手机摄像头拍摄区域,左下红色打印是识别的文字