OpenCV生成全景图平移视频时触发段错误求助
OpenCV 4.6.0 + Python 在Linux 22.04下生成全景平移视频段错误的解决思路
问题描述
在Linux 22.04系统中,使用OpenCV 4.6.0与Python开发全景图平移视频时,前100帧生成正常,后续触发段错误。裁剪后的帧导出为JPG无异常,更换源图格式(PNG/JPG)、多种编码器均无法解决问题。相关代码如下:
import numpy as np import cv2 imgPath = './../pan/pan_01/pan_01_B_small.png' width=1920 height=1080 chan=3 fps=30 seconds=10 numframes = fps*seconds img = cv2.imread(imgPath, 1) print("Image Size:", img.shape) shiftPerFrame = (img.shape[1] - width) / numframes print(img.shape[1]) print("Shift/Frame: ", shiftPerFrame) # Define the codec and create VideoWriter object fourcc = cv2.VideoWriter_fourcc(*'XVID') out = cv2.VideoWriter('output.avi',fourcc, fps, (width,height)) for i in range(1,numframes): # init frames x = int(i * shiftPerFrame) crop_img = img[0:height, x:x+width] print("Frame: ", i, " Position x:", x, " to ", x+width, "size: ", crop_img.shape) out.write(crop_img) #cv2.imwrite("data/img" + str(i) + ".jpg", crop_img) out.release()
可能原因与解决步骤
1. 修复浮点累计偏移的边界越界问题
shiftPerFrame为浮点数,循环中int(i * shiftPerFrame)会产生累计误差,后期可能导致x+width超过图片实际宽度,触发内存越界。
解决代码:
total_shift = img.shape[1] - width # 用linspace生成无累计误差的整数偏移序列 x_positions = np.linspace(0, total_shift, numframes, endpoint=False, dtype=np.int32) for i in range(numframes): x = x_positions[i] # 强制裁剪范围不越界 crop_img = img[0:min(height, img.shape[0]), x:x+width] # 确保尺寸与VideoWriter一致 if crop_img.shape[0] < height: crop_img = cv2.copyMakeBorder(crop_img, 0, height - crop_img.shape[0], 0, 0, cv2.BORDER_CONSTANT) out.write(crop_img)
2. 强制帧格式与编码器参数匹配
部分编码器对帧格式的兼容性要求严格,显式指定颜色空间与格式:
修改代码:
# 更换为更稳定的MP4编码器 fourcc = cv2.VideoWriter_fourcc(*'mp4v') # 显式指定isColor参数,避免自动检测错误 out = cv2.VideoWriter('output.mp4', fourcc, fps, (width, height), isColor=True) # 裁剪后强制转换为uint8格式 crop_img = img[0:height, x:x+width].astype(np.uint8)
3. 升级OpenCV版本
OpenCV 4.6.0存在部分内存管理与编码器的已知bug,升级至4.8.0及以上版本可修复:
pip install --upgrade opencv-python
4. 添加调试与异常捕获
定位具体出错帧的边界情况,排查内存访问问题:
for i in range(numframes): try: x = x_positions[i] crop_img = img[0:height, x:x+width] if crop_img.shape != (height, width, chan): print(f"Frame {i}: 尺寸不匹配 {crop_img.shape}") continue out.write(crop_img) except Exception as e: print(f"Frame {i} 出错: {str(e)}, x={x}, 图片宽度={img.shape[1]}") break
内容的提问来源于stack exchange,提问作者Volker
相关产品推荐
相关产品推荐

