OpenCV裁剪视频保存为MP4仅1KB?求代码排查与解决方案
问题排查与解决方法
核心错误点
- 帧率参数错误:创建
VideoWriter时误将视频总帧数(CAP_PROP_FRAME_COUNT)当作帧率传入,正确参数应为视频实际帧率(CAP_PROP_FPS)。 - 帧尺寸顺序颠倒:OpenCV要求
VideoWriter的尺寸格式为(宽度, 高度),但代码中传入的是(高度, 宽度)(first_frame_roi.shape[0]对应高度,shape[1]对应宽度)。 - 首帧丢失:初始化阶段已读取第一帧,但后续循环未将该帧写入输出文件,导致视频开头缺帧。
修复后的完整代码
import numpy as np import cv2 import matplotlib.pyplot as plt ORIGINAL_WINDOW_TITLE = 'Original' FIRST_FRAME_WINDOW_TITLE = 'First Frame' DIFFERENCE_WINDOW_TITLE = 'Difference' canvas = None drawing = False # true if mouse is pressed #Retrieve first frame def initialize_camera(cap): _, frame = cap.read() return frame # mouse callback function def mouse_draw_rect(event,x,y,flags, params): global drawing, canvas if drawing: canvas = params[0].copy() if event == cv2.EVENT_LBUTTONDOWN: drawing = True params.append((x,y)) #Save first point elif event == cv2.EVENT_MOUSEMOVE: if drawing: cv2.rectangle(canvas, params[1],(x,y),(0,255,0),2) elif event == cv2.EVENT_LBUTTONUP: drawing = False params.append((x,y)) #Save second point cv2.rectangle(canvas,params[1],params[2],(0,255,0),2) def select_roi(frame): global canvas #here, it is the copy of the first frame. canvas = frame.copy() params = [frame] ROI_SELECTION_WINDOW = 'Select ROI' cv2.namedWindow(ROI_SELECTION_WINDOW) cv2.setMouseCallback(ROI_SELECTION_WINDOW, mouse_draw_rect, params) roi_selected = False while True: cv2.imshow(ROI_SELECTION_WINDOW, canvas) key = cv2.waitKey(10) #Press Enter to break the loop if key == 13: break; cv2.destroyWindow(ROI_SELECTION_WINDOW) roi_selected = (3 == len(params)) print(len(params)) if roi_selected: p1 = params[1] p2 = params[2] if (p1[0] == p2[0]) and (p1[1] == p2[1]): roi_selected = False #Use whole frame if ROI has not been selected if not roi_selected: print('ROI Not Selected. Using Full Frame') p1 = (0,0) p2 = (frame.shape[1] - 1, frame.shape[0] -1) return roi_selected, p1, p2 if __name__ == '__main__': cap = cv2.VideoCapture(r'E:\cardiovascular\brad1low.mp4') #Grab first frame first_frame = initialize_camera(cap) #Select ROI for processing. Hit Enter after drawing the rectangle to finalize selection roi_selected, point1, point2 = select_roi(first_frame) #Grab ROI of first frame first_frame_roi = first_frame[point1[1]:point2[1], point1[0]:point2[0]] print(f'first frame roi is {first_frame_roi}') # 获取视频实际帧率 fps = cap.get(cv2.CAP_PROP_FPS) # 修正尺寸顺序:(宽度, 高度) roi_width = first_frame_roi.shape[1] roi_height = first_frame_roi.shape[0] # 使用兼容性更好的AVC1编码 out = cv2.VideoWriter(r'E:\cardiovascular\filename2.mp4', cv2.VideoWriter_fourcc(*'AVC1'), fps, (roi_width, roi_height)) # 写入首帧的ROI内容 out.write(first_frame_roi) while cap.isOpened(): ret, frame = cap.read() if ret: #ROI of current frame roi = frame[point1[1]:point2[1], point1[0]:point2[0]] print(f'roi is {roi}') cv2.imshow(DIFFERENCE_WINDOW_TITLE, roi) out.write(roi) key = cv2.waitKey(30) & 0xff if key == 27: break else: break cap.release() out.release() cv2.destroyAllWindows()
额外说明
- 若
AVC1编码仍无法生成有效视频,可尝试替换为XVID(需将输出文件后缀改为.avi)或MP4V,不同系统对编码的支持存在差异。 - 确保输出路径具备写入权限,避免因权限问题导致文件写入失败。
内容的提问来源于stack exchange,提问作者Vijith Kumar V
相关产品推荐
相关产品推荐

