OpenCV视频保存异常:输出视频仅1kB且无法打开
OpenCV视频保存异常:输出视频仅1kB且无法打开
嘿,我仔细看了你的代码,找到几个导致视频保存失败的核心问题,咱们一步步来解决:
VideoWriter通道数不匹配(最关键的问题)
你创建的new_video是按照彩色视频的规格初始化的(默认是3通道BGR格式),但你写入的所有帧都是单通道灰度图(比如new_frame的形状是(frame_height, frame_width),只有一个通道)。这种不匹配会让视频编码器无法正确写入有效帧,最终生成的文件只有空的文件头,大小就只有1kB,自然无法打开。解决方法很简单,二选一就行:
- 把灰度帧转换成3通道BGR后写入:每次写入前加一行代码,把单通道转成3通道:
这样就和你初始化new_frame_3ch = cv2.cvtColor(new_frame, cv2.COLOR_GRAY2BGR) new_video.write(new_frame_3ch)VideoWriter时的彩色格式匹配了,兼容性也更好。 - 初始化VideoWriter时适配单通道灰度:修改
VideoWriter的初始化参数,加上isColor=False,告诉OpenCV这是灰度视频:
不过这种方式要注意编码器是否支持灰度输出,推荐第一种方法。new_video = cv2.VideoWriter(output_file_name, fourcc, frame_rate, (frame_width, frame_height), isColor=False)
- 把灰度帧转换成3通道BGR后写入:每次写入前加一行代码,把单通道转成3通道:
循环逻辑的小bug
你在进入循环前先执行了success, current_video_frame = video.read(),然后循环里第一行又读next_video_frame,这会导致原视频的第一帧被跳过,没有参与后续的差值计算。如果这不是你的预期,可以调整循环逻辑:# 先读取第一帧作为current success, current_video_frame = video.read() while success: success, next_video_frame = video.read() if not success: break # 差值处理逻辑... current_video_frame = next_video_frame数值溢出的潜在问题
你用new_frame = new_frame + difference来累加差值,但因为都是uint8类型(取值范围0-255),相加会直接溢出(比如250+10会变成4),这可能不是你想要的视觉效果。建议改用cv2.add或者手动限制最大值:# 方式1:用cv2.add自动处理溢出(超过255的部分会被截断为255) new_frame = cv2.add(new_frame, difference) # 方式2:手动限制最大值 new_frame = np.clip(new_frame + difference, 0, 255).astype(np.uint8)
下面是整合了所有修复点的完整代码,你可以直接运行试试:
import cv2 import numpy as np file_name = "Touhou - Bad Apple.mp4" output_file_name = "Touhou - Bad Apple difference flip.mp4" # Open the video file video = cv2.VideoCapture(file_name) # Get the dimensions of the video frame_width = int(video.get(cv2.CAP_PROP_FRAME_WIDTH)) frame_height = int(video.get(cv2.CAP_PROP_FRAME_HEIGHT)) frame_rate = video.get(cv2.CAP_PROP_FPS) # Create a VideoWriter object to write the new video file fourcc = cv2.VideoWriter_fourcc(*'mp4v') # Codec for .mp4 files new_video = cv2.VideoWriter(output_file_name, fourcc, frame_rate, (frame_width, frame_height)) # Create first frame and convert to 3-channel BGR new_frame = np.random.randint(0, 256, (frame_height, frame_width), dtype=np.uint8) new_video.write(cv2.cvtColor(new_frame, cv2.COLOR_GRAY2BGR)) # Read first frame of original video success, current_video_frame = video.read() while success: success, next_video_frame = video.read() if not success: break difference = cv2.absdiff(current_video_frame, next_video_frame) difference = cv2.cvtColor(difference, cv2.COLOR_BGR2GRAY) # Handle overflow when adding frames new_frame = cv2.add(new_frame, difference) # Convert to 3-channel before writing new_video.write(cv2.cvtColor(new_frame, cv2.COLOR_GRAY2BGR)) current_video_frame = next_video_frame cv2.imshow('Difference', new_frame) if cv2.waitKey(1) == ord('q'): break # Release the video objects video.release() new_video.release() cv2.destroyAllWindows()
备注:内容来源于stack exchange,提问作者Akut Luna
相关产品推荐
相关产品推荐

