PyInstaller打包OpenCV标定程序exe后无法显示实时视频怎么办
实时相机标定程序PyInstaller打包故障排查
基础信息
- 开发环境:Python 3.8 64位、Windows操作系统、Visual Studio Code
- 实现功能:基于OpenCV展示相机实时采集画面,加载预先生成的标定参数对画面做去畸变校正
- 调试阶段状态:VSCode中直接运行源码时功能完全正常,标定参数以
calibration.npz文件名存储在代码同路径下,包含相机内参mtx、畸变系数dist、旋转向量rvecs、平移向量tvecs四类核心参数
相关实现代码
实时画面去畸变逻辑
h,w = frame.shape[:2] with np.load('calibration.npz') as X: mtx, dist, _ , _ = [X[i] for i in ('mtx','dist','rvecs','tvecs')] newcameramtx, roi = cv2.getOptimalNewCameraMatrix(mtx, dist, (w, h), 0) mapx, mapy = cv2.initUndistortRectifyMap(mtx, dist, None, newcameramtx,(w, h), 5) dst = cv2.remap(frame, mapx, mapy, cv2.INTER_LINEAR) global dst_final x, y, w, h = roi dst_final=dst[y:y+h, x:x+w]
标定参数文件生成代码
#!/usr/bin/env python import cv2 import numpy as np import os import glob CHECKERBOARD = (6,9) criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001) objpoints = [] imgpoints = [] objp = np.zeros((1, CHECKERBOARD[0] * CHECKERBOARD[1], 3), np.float32) objp[0,:,:2] = np.mgrid[0:CHECKERBOARD[0], 0:CHECKERBOARD[1]].T.reshape(-1, 2)*26 # 单格棋盘格边长为26mm prev_img_shape = None images = glob.glob('C:\\Users\\MyPc\\KHS\\test2\\*.jpg') for fname in images: img = cv2.imread(fname) gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) ret, corners = cv2.findChessboardCorners(gray, CHECKERBOARD, cv2.CALIB_CB_ADAPTIVE_THRESH + cv2.CALIB_CB_FAST_CHECK + cv2.CALIB_CB_NORMALIZE_IMAGE) if ret == True: objpoints.append(objp) corners2 = cv2.cornerSubPix(gray, corners, (11,11),(-1,-1), criteria) imgpoints.append(corners2) img = cv2.drawChessboardCorners(img, CHECKERBOARD, corners2, ret) cv2.imshow('img',img) cv2.waitKey(0) cv2.destroyAllWindows() h,w = img.shape[:2] ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None) newcameramtx, roi = cv2.getOptimalNewCameraMatrix(mtx, dist, (w, h), 0) mapx, mapy = cv2.initUndistortRectifyMap(mtx, dist, None, newcameramtx,(w, h), 5) dst = cv2.remap(img, mapx, mapy, cv2.INTER_LINEAR) x, y, w, h = roi dst=dst[y:y+h, x:x+w] cv2.imshow('num', dst) cv2.imshow('ori', img) cv2.waitKey(0) np.savez_compressed('calibration.npz',ret=ret,mtx=mtx,dist=dist,rvecs=rvecs,tvecs=tvecs)
打包命令
pyinstaller -w --ico=myico.ico --add-data *.png;. ABC.py
故障现象
未添加标定逻辑的程序版本打包为exe后可正常显示实时视频;添加标定逻辑后的exe运行无任何弹窗报错,但无法打开摄像头展示实时画面。
解决方法
- 修复相对路径失效问题:PyInstaller打包后exe运行时的工作目录和源码运行目录不一致,直接写
calibration.npz相对路径会触发文件找不到的异常,加-w参数打包的无控制台程序会直接静默吞掉这类错误,表现为程序无响应、画面不显示。在代码中添加路径解析函数,统一以exe/源码的实际所在目录为基准拼接文件路径:
将原代码中import sys import os def get_real_path(rel_path): if getattr(sys, 'frozen', False): base_dir = os.path.dirname(sys.executable) else: base_dir = os.path.dirname(os.path.abspath(__file__)) return os.path.join(base_dir, rel_path)np.load('calibration.npz')替换为np.load(get_real_path('calibration.npz'))即可。 - 补全打包资源配置:当前打包命令仅将png格式文件打包进exe,未包含
calibration.npz标定文件,就算路径逻辑正确也会找不到文件。修改打包命令,将npz文件加入附加资源列表:pyinstaller -w --ico=myico.ico --add-data *.png;. --add-data calibration.npz;. ABC.py - 排查隐藏报错:如果上述两步修改后仍存在问题,临时去掉打包命令中的
-w参数,打包出带控制台窗口的版本,运行时控制台会直接打印具体错误信息,可根据报错针对性修复。 - 优化代码性能:现有代码每一帧画面都重新计算
newcameramtx、mapx、mapy三个映射参数,这三个参数仅和相机内参、采集分辨率有关,不需要逐帧重复计算,在摄像头初始化阶段计算一次即可,既能降低性能开销,也能减少异常触发概率。
内容的提问来源于stack exchange,提问作者Yamm
相关产品推荐
相关产品推荐

