I just installed OpenCV 2.4 from source on Ubuntu 12.04. I'm trying to use a Python script to write the first frame of a video to a PNG image, but I'm getting some bizarre results. Here's the code:
import numpy as np
import cv
import cv2
import sys
video = cv.CaptureFromFile(sys.argv[1])
frame = cv.QueryFrame(video)
proxy = cv.CreateImage(cv.GetSize(frame), 8, 1)
cv.CvtColor(frame, proxy, cv.CV_BGR2GRAY)
a = np.asarray(cv.GetMat(proxy))
cv2.imwrite('image.png', a)
Problem is, the image comes out looking like this:
These are AVI files and otherwise seem to be fine. Any ideas?
Edit #1: Apologies, here is the ffmpeg version information:
ffmpeg version 0.10.2-4:0.10.2-0ubuntu0jon1
built on Mar 18 2012 09:59:38 with gcc 4.6.3
configuration: --extra-version='4:0.10.2-0ubuntu0jon1' --arch=amd64 --prefix=/usr --libdir=/usr/lib/x86_64-linux-gnu --disable-stripping --enable-vdpau --enable-bzlib --enable-libgsm --enable-libschroedinger --enable-libspeex --enable-libtheora --enable-libvorbis --enable-pthreads --enable-zlib --enable-libvpx --enable-runtime-cpudetect --enable-libfreetype --enable-vaapi --enable-frei0r --enable-gpl --enable-postproc --enable-x11grab --enable-librtmp --enable-libvo-aacenc --enable-version3 --enable-libvo-amrwbenc --enable-version3 --enable-libdc1394 --shlibdir=/usr/lib/x86_64-linux-gnu --enable-shared --disable-static
libavutil 51. 35.100 / 51. 35.100
libavcodec 53. 61.100 / 53. 61.100
libavformat 53. 32.100 / 53. 32.100
libavdevice 53. 4.100 / 53. 4.100
libavfilter 2. 61.100 / 2. 61.100
libswscale 2. 1.100 / 2. 1.100
libswresample 0. 6.100 / 0. 6.100
libpostproc 52. 0.100 / 52. 0.100
Edit #2: In my own troubleshooting, I upgraded ffmpeg from the default 12.04 ubuntu version to the one you see in Edit #1 above. This seems to have changed things a little bit: the video which generated the frame in this question now seems to work fine, but larger videos still present with corrupted bottom halves (or bottom thirds, or fourths). Even larger videos actually segfault entirely. I'm not really sure what to make of this, other than--yet again--faulty or missing codecs. It segfaults right on the QueryFrame
step.
Edit #3: I changed the code to make exclusive use of the cv2 interface (as per a link in one of the comments below). Now, video.retrieve()
always returns False
and no image is written.
Edit #4: I ran the following command on the video before using the new cv2 interface to read the video frames:
ffmpeg -sameq -i normal.avi p_normal.avi
The output of the command looked ok except for this one line following the initialization of ffmpeg and its description of the input:
Incompatible pixel format 'pal8' for codec 'mpeg4', auto-selecting format 'yuv420p'
Here's the full output of the command:
Input #0, avi, from 'normal.avi':
Duration: 00:01:37.60, start: 0.000000, bitrate: 1312 kb/s
Stream #0:0: Video: rawvideo, pal8, 128x256, 5 tbr, 5 tbn, 5 tbc
Incompatible pixel format 'pal8' for codec 'mpeg4', auto-selecting format 'yuv420p'
[buffer @ 0x11a0f80] w:128 h:256 pixfmt:pal8 tb:1/1000000 sar:0/1 sws_param:
[buffersink @ 0x11a1380] auto-inserting filter 'auto-inserted scale 0' between the filter 'src' and the filter 'out'
[scale @ 0x1197da0] w:128 h:256 fmt:pal8 -> w:128 h:256 fmt:yuv420p flags:0x4
Output #0, avi, to 'p_normal.avi':
Metadata:
ISFT : Lavf53.32.100
Stream #0:0: Video: mpeg4 (FMP4 / 0x34504D46), yuv420p, 128x256, q=2-31, 200 kb/s, 5 tbn, 5 tbc
Stream mapping:
Stream #0:0 -> #0:0 (rawvideo -> mpeg4)
Press [q] to stop, [?] for help
frame= 488 fps= 0 q=0.0 Lsize= 1497kB time=00:01:37.60 bitrate= 125.6kbits/s
video:1480kB audio:0kB global headers:0kB muxing overhead 1.165352%
Most importantly, the Python OpenCV code to read the frame (using the cv2 interface) still returns False (same behavior as before).
Edit #5: I have so far followed the instructions found here for installing ffmpeg and its dependencies from source, and that went smoothly. Without reinstalling OpenCV from source, I am still encountering the same problem as before where video.retrieve()
returns False. In attempting to recompile OpenCV 2.4 from source, I am getting the following error during compilation:
Linking CXX shared library ../../lib/libopencv_highgui.so
/usr/bin/ld: /usr/local/lib/libavcodec.a(avpacket.o): relocation R_X86_64_32S against `av_destruct_packet' can not be used when making a shared object; recompile with -fPIC
/usr/local/lib/libavcodec.a: could not read symbols: Bad value
If I recompile x264, libvpx, and ffmpeg with the --enable-pic
flag, OpenCV compilation still fails, this time with (kdbwin.o
, .rodata
) instead of (avpacket.o
, av_destruct_packet
) respectively in the snippet above.
Edit #6: Fixed the above error by adding --enable-shared
to the configuration options of libvpx and ffmpeg. OpenCV recompiled and built successfully, and ffmpeg worked just fine. Sadly, after running the previous command (ffmpeg -sameq -i normal.avi p_normal.avi
), my script still couldn't retrieve any frames; the flag returned was still False. Any further ideas?
Edit #7: Here's the latest script I'm using.
import numpy as np
import cv2
import sys
video = cv2.VideoCapture(sys.argv[1])
flag, frame = video.retrieve()
if not flag:
print 'Error'
quit()
proxy = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cv2.imwrite('image.png', proxy)
Edit #8: Got it! Here's what the code should be:
import numpy as np
import cv2
import sys
video = cv2.VideoCapture(sys.argv[1])
if video.grab():
flag, frame = video.retrieve()
if not flag:
print 'Error'
quit()
proxy = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cv2.imwrite('image.png', proxy)