Python OpenCV配合Arduino触发存图运行速度慢该如何优化?
代码优化方案
核心问题原因
- OpenCV的VideoCapture默认启用多帧缓存,每次读取的是数秒前的缓存帧,不是实时数据,导致状态和画面不同步
- 串口读取逻辑未设置超时/缓存清理,Arduino发送的开关数据积压在串口缓冲区,程序读到的是十几秒前的旧数据,这是15秒延迟的核心诱因
- 代码执行顺序错误:先展示1080P原始帧再做resize,浪费算力;开关检测放在帧读取处理之后,优先级不够
- 循环固定等待40ms(即25帧上限),没有清串口缓存的逻辑,延迟持续累积
- 原代码保存图片时直接覆盖同路径文件,没有按计数区分,会导致历史拍摄结果丢失
优化后代码
import os import cv2 # 若你使用自定义封装的SerialObject类,替换对应串口接口即可 import serial # 初始化串口,设置10ms超时,非阻塞读取避免卡死 Arduino = serial.Serial('你的串口号', 对应波特率, timeout=0.01) if os.path.exists(PathCouleur) and os.path.exists(PathGris): # Windows环境用CAP_DSHOW、Linux用CAP_V4L2、Mac用CAP_AVFOUNDATION,走原生驱动避免系统层缓存 Images = cv2.VideoCapture(Camera, cv2.CAP_DSHOW) # 摄像头只保留1帧缓存,每次读都是最新实时帧 Images.set(cv2.CAP_PROP_BUFFERSIZE, 1) # 摄像头参数设置 Images.set(cv2.CAP_PROP_FRAME_WIDTH, 1920) Images.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080) Images.set(cv2.CAP_PROP_BRIGHTNESS, Brightness) Compte = 0 Switch = "0" while True: # 先清空串口积压数据,只取最新的开关值 while Arduino.in_waiting > 0: Switch = Arduino.readline().decode('utf-8').strip() # 读取实时帧 Sucess, Video = Images.read() if not Sucess: continue # 先做resize,后续预览、检测都用小帧,节省算力 Video_resized = cv2.resize(Video, (Largeur, Hauteur)) # 预览用小帧即可,不需要渲染1080P大画面 cv2.imshow("Camera", Video_resized) # 开关触发逻辑 if Switch == "1": blur = cv2.Laplacian(Video_resized, cv2.CV_64F).var() if blur < MinBlur: # 按计数命名保存文件,避免覆盖 cv2.imwrite(f"{PathCouleur}_{Compte}.png", Video_resized) cv2.imwrite(f"{PathGris}_{Compte}.png", cv2.cvtColor(Video_resized, cv2.COLOR_BGR2GRAY)) Compte += 1 # 触发后重置开关状态、清空串口缓存,避免重复触发 Switch = "0" Arduino.reset_input_buffer() # waitKey只等1ms,提高循环响应速度 if cv2.waitKey(1) == 27: break # 释放所有资源 Images.release() Arduino.close() cv2.destroyAllWindows() else: print("Erreur, aucun Path")
补充说明
如果你的SerialObject是自定义封装的串口类,只需要把代码中串口读取、缓存清理的部分替换为你封装类对应的接口即可,核心优化逻辑不变。优化后开关响应延迟可以降到100ms以内,完全满足实时拍摄需求。
内容的提问来源于stack exchange,提问作者Vi Peeters
相关产品推荐
相关产品推荐

