Python中OpenCV读取MATLAB生成的未压缩AVI文件时cap.read()崩溃问题求助
cap.read() Segmentation Fault with MATLAB-Generated Uncompressed BGR24 AVI I recently ran into a frustrating issue where using cap.read() in OpenCV to load an uncompressed AVI file generated by MATLAB's VideoWriter would immediately crash my Python program with a segmentation fault (zsh: segmentation fault python3 t.py). Here's a breakdown of the problem, my debugging steps, and the solutions I found:
Problem Details
- The video file plays normally in IINA, and ffmpeg can extract frames successfully, but converting it to other formats fails.
- OpenCV's
cap.isOpened()returnsTrue, and I can retrieve all metadata (FPS, frame count, width/height) correctly. However,cap.get(cv2.CAP_PROP_FOURCC)returns0.0, which is a red flag. - MATLAB-generated grayscale AVIs work fine with OpenCV, but this BGR24 color version does not.
Test Code
import cv2 video_path = '/Users/aravind/Downloads/test.avi' cap = cv2.VideoCapture(video_path) print(cap.get(cv2.CAP_PROP_FOURCC)) print("FPS:", cap.get(cv2.CAP_PROP_FPS)) print("Frame count:", cap.get(cv2.CAP_PROP_FRAME_COUNT)) print("Width:", cap.get(cv2.CAP_PROP_FRAME_WIDTH)) print("Height:", cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) while cap.isOpened(): print("Working here") ret, frame = cap.read() # Crash occurs here
FFprobe Output
{ "streams": [ { "index": 0, "codec_name": "rawvideo", "codec_long_name": "raw video", "codec_type": "video", "codec_tag_string": "[0][0][0][0]", "codec_tag": "0x0000", "width": 192, "height": 192, "coded_width": 192, "coded_height": 192, "has_b_frames": 0, "pix_fmt": "bgr24", "level": -99, "r_frame_rate": "30/1", "avg_frame_rate": "30/1", "time_base": "1/30", "start_pts": 0, "start_time": "0.000000", "duration_ts": 60, "duration": "2.000000", "bit_rate": "26991946", "nb_frames": "60", "extradata_size": 9, "disposition": { "default": 0, "dub": 0, "original": 0, "comment": 0, "lyrics": 0, "karaoke": 0, "forced": 0, "hearing_impaired": 0, "visual_impaired": 0, "clean_effects": 0, "attached_pic": 0, "timed_thumbnails": 0, "non_diegetic": 0, "captions": 0, "descriptions": 0, "metadata": 0, "dependent": 0, "still_image": 0, "multilayer": 0 } } ] }
FFmpeg Frame Extraction Success
ffmpeg version 8.1 Copyright (c) 2000-2026 the FFmpeg developers built with Apple clang version 21.0.0 (clang-2100.0.123.102) configuration: --prefix=/opt/homebrew/Cellar/ffmpeg/8.1 --enable-shared --enable-pthreads --enable-version3 --cc=clang --host-cflags= --host-ldflags= --enable-ffplay --enable-gpl --enable-libsvtav1 --enable-libopus --enable-libx264 --enable-libmp3lame --enable-libdav1d --enable-libvmaf --enable-libvpx --enable-libx265 --enable-openssl --enable-videotoolbox --enable-audiotoolbox --enable-neon libavutil 60. 26.100 / 60. 26.100 libavcodec 62. 28.100 / 62. 28.100 libavformat 62. 12.100 / 62. 12.100 libavdevice 62. 3.100 / 62. 3.100 libavfilter 11. 14.100 / 11. 14.100 libswscale 9. 5.100 / 9. 5.100 libswresample 6. 3.100 / 6. 3.100 Input #0, avi, from '/Users/aravind/Downloads/test.avi': Duration: 00:00:02.00, start: 0.000000, bitrate: 26813 kb/s Stream #0:0: Video: rawvideo, bgr24, 192x192, 26991 kb/s, 30 fps, 30 tbr, 30 tbn File '/tmp/test_frame.png' already exists. Overwrite? [y/N] y Stream mapping: Stream #0:0 -> #0:0 (rawvideo (native) -> png (native)) Press [q] to stop, [?] for help Output #0, image2, to '/tmp/test_frame.png': Metadata: encoder : Lavf62.12.100 Stream #0:0: Video: png, rgb24(pc, gbr/unknown/unknown, progressive), 192x192, q=2-31, 200 kb/s, 30 fps, 30 tbn Metadata: encoder : Lavc62.28.100 png [image2 @ 0xbe7018280] The specified filename '/tmp/test_frame.png' does not contain an image sequence pattern or a pattern is invalid. [image2 @ 0xbe7018280] Use a pattern such as %03d for an image sequence or use the -update option (with -frames:v 1 if needed) to write a single image. [out#0/image2 @ 0xbe6c54180] video:2KiB audio:0KiB subtitle:0KiB other streams:0KiB global headers:0KiB muxing overhead: unknown frame= 1 fps=0.0 q=-0.0 Lsize=N/A time=00:00:00.03 bitrate=N/A speed=7.15x elapsed=0:00:00.00
Root Cause
Looking at the ffprobe output, the key issue is the codec_tag: "0x0000" — MATLAB's VideoWriter didn't set a valid FOURCC identifier for the uncompressed BGR24 video. OpenCV relies on FOURCC to determine how to decode frame data; without a valid tag, it can't correctly parse the raw pixel data, leading to a memory access violation (segmentation fault). Grayscale AVIs work because they likely use a FOURCC that OpenCV recognizes by default.
Solutions
1. Transcode the Video with FFmpeg
Add a valid FOURCC tag that OpenCV understands using ffmpeg:
ffmpeg -i test.avi -c:v rawvideo -pix_fmt bgr24 -fourcc CVFP test_fixed.avi
CVFP corresponds to OpenCV's CV_FOURCC('C','V','F','P'), which is a supported FOURCC for uncompressed BGR24 video. After transcoding, OpenCV will read the file without crashing.
2. Use PyAV (FFmpeg-Based Library) to Read the Video
PyAV is a Python wrapper for FFmpeg that handles rawvideo formats correctly. Install it first:
pip install av
Then use this code to read the video and convert frames to OpenCV format:
import av import cv2 import numpy as np video_path = '/Users/aravind/Downloads/test.avi' container = av.open(video_path) fps = container.streams.video[0].average_rate for frame in container.decode(video=0): # Convert PyAV frame to OpenCV-compatible BGR array img = frame.to_ndarray(format='bgr24') cv2.imshow('Frame', img) # Control playback speed if cv2.waitKey(int(1000 / fps)) & 0xFF == ord('q'): break cv2.destroyAllWindows()
3. Modify MATLAB's Video Generation
Generate the AVI with a valid FOURCC that OpenCV recognizes. In MATLAB, you can specify the compression method or set the FOURCC directly:
% Create VideoWriter object with uncompressed format vidObj = VideoWriter('test_compatible.avi', 'Uncompressed AVI'); % Set FOURCC to CVFP (OpenCV's BGR24 format) vidObj.FourCC = ['C' 'V' 'F' 'P']; vidObj.FrameRate = 30; open(vidObj); % Write your frames here (example with a random frame) frame = uint8(rand(192,192,3)*255); writeVideo(vidObj, frame); close(vidObj);
This ensures the output AVI has a FOURCC tag that OpenCV can interpret correctly.
内容的提问来源于stack exchange,提问作者RajaKrishnappa

