我正在为Raspbian(Raspberry Pi 2)中的Python开发视频捕获脚本,由于在内存映射缓冲区方面没有成功,因此无法为v4l2使用Python绑定(bind)。

我需要的:

  • 从HD-WebCam捕获视频(将同时播放其中的2个视频)。
  • 能够通过WLAN流传输该视频(在网络负载和处理速度之间折衷)。
  • 将来,可以在流式传输之前对图像应用滤镜(不是必须的)。

  • 我尝试过的
  • 使用OpenCV(cv2)。它非常易于使用,但是由于它将网络摄像头的JPEG帧转换为原始图像,因此增加了很多处理负载,然后我不得不将它们转换回JPEG,然后再通过WLAN发送。
  • 直接从'/ dev / video0'读取。很棒,因为网络摄像头发送已压缩的帧,而我可以读取并发送它们,但是看来我的相机不支持该帧。
  • 对Python使用v4l2绑定(bind)。到目前为止,这是最有前途的选择,但是当我不得不映射视频缓冲区时,我陷入了困境。我发现没有办法克服这些东西似乎需要的“内存指针/映射”。

  • 我读过的东西:
  • 本指南:http://www.jayrambhia.com/blog/capture-v4l2/
  • v4l2文档(其中一些)。
  • C语言中的此示例:https://linuxtv.org/downloads/v4l-dvb-apis/capture-example.html
  • C / C++中的其他一些示例。我没有找到直接在Python上使用v4l2绑定(bind)的示例。

  • 我的问题:
  • 有更好的方法吗?或者如果不是...
  • 我可以告诉OpenCV不要解压缩图像吗?最好使用OpenCV来应用将来的扩展。我发现here不允许使用。
  • 如何解决Python中的映射步骤? (任何可行的示例?)

  • 这是我的(缓慢的)OpenCV工作示例:
    import cv2
    import time
    
    video = cv2.VideoCapture(0)
    
    print 'Starting video-capture test...'
    
    t0 = time.time()
    for i in xrange(100):
        success, image = video.read()
        ret, jpeg = cv2.imencode('.jpg',image)
    
    t1 = time.time()
    t = ( t1 - t0 ) / 100.0
    fps = 1.0 / t
    
    print 'Test finished. ' + str(t) + ' sec. per img.'
    print str( fps ) + ' fps reached'
    
    video.release()
    

    这是我对v4l2所做的事情:
    FRAME_COUNT = 5
    
    import v4l2
    import fcntl
    import mmap
    
    def xioctl( fd, request, arg):
    
        r = 0
    
        cond = True
        while cond == True:
            r = fcntl.ioctl(fd, request, arg)
            cond = r == -1
            #cond = cond and errno == 4
    
        return r
    
    class buffer_struct:
        start  = 0
        length = 0
    
    # Open camera driver
    fd = open('/dev/video1','r+b')
    
    BUFTYPE = v4l2.V4L2_BUF_TYPE_VIDEO_CAPTURE
    MEMTYPE = v4l2.V4L2_MEMORY_MMAP
    
    # Set format
    fmt = v4l2.v4l2_format()
    fmt.type = BUFTYPE
    fmt.fmt.pix.width       = 640
    fmt.fmt.pix.height      = 480
    fmt.fmt.pix.pixelformat = v4l2.V4L2_PIX_FMT_MJPEG
    fmt.fmt.pix.field       = v4l2.V4L2_FIELD_NONE # progressive
    
    xioctl(fd, v4l2.VIDIOC_S_FMT, fmt)
    
    buffer_size = fmt.fmt.pix.sizeimage
    print "buffer_size = " + str(buffer_size)
    
    # Request buffers
    req = v4l2.v4l2_requestbuffers()
    
    req.count  = 4
    req.type   = BUFTYPE
    req.memory = MEMTYPE
    
    xioctl(fd, v4l2.VIDIOC_REQBUFS, req)
    
    if req.count < 2:
        print "req.count < 2"
        quit()
    
    n_buffers = req.count
    
    buffers = list()
    for i in range(req.count):
        buffers.append( buffer_struct() )
    
    # Initialize buffers. What should I do here? This doesn't work at all.
    # I've tried with USRPTR (pointers) but I know no way for that in Python.
    for i in range(n_buffers):
    
        buf = v4l2.v4l2_buffer()
    
        buf.type      = BUFTYPE
        buf.memory    = MEMTYPE
        buf.index     = i
    
        xioctl(fd, v4l2.VIDIOC_QUERYBUF, buf)
    
        buffers[i].length = buf.length
        buffers[i].start  = mmap.mmap(fd.fileno(), buf.length,
                                      flags  = mmap.PROT_READ,# | mmap.PROT_WRITE,
                                      prot   = mmap.MAP_SHARED,
                                      offset = buf.m.offset )
    

    我将不胜感激任何帮助或建议。非常感谢!

    最佳答案

    只需在我刚刚发现的此处添加另一个选项,您还可以将V4L2后端与OpenCV一起使用。

    您只需要在VideoCapture构造函数中指定它即可。例如

    cap = cv2.VideoCapture()
    
    cap.open(0, apiPreference=cv2.CAP_V4L2)
    
    cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc('M', 'J', 'P', 'G'))
    cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
    cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 960)
    cap.set(cv2.CAP_PROP_FPS, 30.0)
    

    如果未明确指定,则OpenCV通常会使用其他摄像头API(例如gstreamer),该API通常比较慢且麻烦。在此示例中,我从限制为4-5 FPS到720p(使用Intel Atom Z8350)达到15。

    如果您希望将其与环形缓冲区(或其他内存映射的缓冲区)一起使用,请查看以下资源:

    https://github.com/Battleroid/seccam

    https://github.com/bslatkin/ringbuffer

    关于python-2.7 - v4l2 Python-流视频-映射缓冲区,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36426826/

    10-13 04:13