Python OpenCV 2.4编写半完整的PNG视频帧 [英] Python OpenCV 2.4 writes half-complete PNG video frames

查看:93
本文介绍了Python OpenCV 2.4编写半完整的PNG视频帧的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚在Ubuntu 12.04上从源代码安装了OpenCV 2.4.我正在尝试使用Python脚本将视频的第一帧写入PNG图像,但结果却有些奇怪.这是代码:

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:

这些是AVI文件,否则似乎还可以.有什么想法吗?

These are AVI files and otherwise seem to be fine. Any ideas?

编辑#1:抱歉,以下是ffmpeg版本信息:

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

编辑#2:在我自己的问题排查中,我将ffmpeg从默认的12.04 ubuntu版本升级到了您在上面的编辑#1中看到的版本.这似乎已经改变了一点:在这个问题中生成帧的视频现在似乎可以正常工作,但是较大的视频仍然存在损坏的下半部分(或下三分之一或四分之一).甚至更大的视频实际上也完全是段错误.除了(但还是要再次)出现故障或缺少编解码器之外,我真的不确定要怎么做.它会在QueryFrame步骤上进行段错误.

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.

编辑#3:我更改了代码,以独占使用cv2接口(根据以下注释之一中的链接).现在,video.retrieve()始终返回False并且没有图像被写入.

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.

编辑#4:在使用新的cv2界面读取视频帧之前,我在视频上运行了以下命令:

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

除了ffmpeg初始化及其输入描述后的这一行外,命令的输出看起来正常:

The output of the command looked ok except for this one line following the initialization of ffmpeg and its description of the input:

编解码器"mpeg4"的像素格式"pal8"不兼容,自动选择 格式为"yuv420p"

Incompatible pixel format 'pal8' for codec 'mpeg4', auto-selecting format 'yuv420p'

这是命令的完整输出:

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%

最重要的是,用于读取框架(使用cv2接口)的Python OpenCV代码仍然返回False(与以前的行为相同).

Most importantly, the Python OpenCV code to read the frame (using the cv2 interface) still returns False (same behavior as before).

编辑#5:到目前为止,我已经按照说明进行操作找到了在这里从源代码安装ffmpeg及其依赖项,一切顺利.没有从源代码重新安装OpenCV,我仍然遇到与以前相同的问题,其中video.retrieve()返回False.尝试从源代码重新编译OpenCV 2.4时,在编译过程中出现以下错误:

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

如果我使用--enable-pic标志重新编译x264,libvpx和ffmpeg,则OpenCV编译仍然会失败,这次是分别使用(kdbwin.o.rodata)而不是(avpacket.oav_destruct_packet)上面的代码段.

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.

编辑#6:通过将--enable-shared添加到libvpx和ffmpeg的配置选项中,修复了上述错误. OpenCV重新编译并成功构建,并且ffmpeg运行正常.可悲的是,在运行上一个命令(ffmpeg -sameq -i normal.avi p_normal.avi)之后,我的脚本 still 无法检索到任何帧.返回的标志仍然为False.还有其他想法吗?

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?

编辑#7:这是我正在使用的最新脚本.

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)

编辑#8:知道了!代码如下:

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)

推荐答案

问题最有可能与ffmpeg和使用的视频编解码器有关.您可以分享其中一个视频吗?然后我们可以检查编解码器,看看有什么问题.另外,我们也不知道您的系统上装有什么ffmpeg版本.

Most likely the problem is with ffmpeg and the used video codec. Could you share one of these videos? then we can check the codec and see what's wrong. Also we don't know what ffmpeg version you've got on your system.

请注意,为什么要混合使用cv和cv2接口?仅使用cv2接口,代码看起来会更好.

Just side note, why are you mixing the cv and cv2 interfaces? the code would look better by using just the cv2 interface.

编辑:我忘了提一下,我已经测试了代码,所以当然问题不在代码中.

I forgot to mention, I tested the code, so certainly the problem isn't in the code.

可能是ffmpeg无法处理您的视频的问题.如果不测试相关视频,就很难说了.您可以尝试使用cv2界面, cv2.VideoCapture 是您用来从视频文件中抓取帧的方法.

Edit 2: It's likely the problem is with ffmpeg not being able to handle your videos. Without testing the videos in question it's hard to say. You can give the cv2 interface a try, cv2.VideoCapture is what you should use to grab frames from a video file.

我看了一段视频,看来OpenCV使用ffmpeg的方式对您的视频有问题.一个快速的解决方法是在通过OpenCV打开之前使用ffmpeg处理您的视频. ffmpeg -sameq -i normal.avi p_norma.avi为您提供了一个视频p_norma.avi,您可以通过OpenCV毫无问题地对其进行处理.对于normal.avi:

Edit 3: I had a look at the video, it seems the way OpenCV uses ffmpeg has a problem with your video. A quick workaround is to process your videos with ffmpeg before opening by OpenCV. ffmpeg -sameq -i normal.avi p_norma.avi gives you a video, p_norma.avi, that you can process by OpenCV without problem. For normal.avi:

Selected video codec: [rawbgr8flip] vfm: raw (RAW BGR8)

以及生成的视频p_norma.avi:

Selected video codec: [ffodivx] vfm: ffmpeg (FFmpeg MPEG-4)

因此,生成的视频大约小10倍.对您来说这可能是解决方案吗?

Hence, the generated video is about 10 times smaller. Would that be a possible solution for you?

这篇关于Python OpenCV 2.4编写半完整的PNG视频帧的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆