使用openCV和Python从摄像机流式传输RAW8视频[Windows]

carvr3hs  于 2022-11-15  发布在  Python
关注(0)|答案(2)|浏览(206)

我们有一台摄像机,它可以在1920 x1080的速度下传输RAW 8视频。使用的GUID是灰色的。我们可以在Windows上使用ffmpeg通过以下命令从该摄像机传输视频:

ffmpeg -f dshow -pix_fmt gray -video_size 1920x1080 -i video="CAM0" -f nut - | ffplay -

我们现在尝试使用OpenCV从这个摄像头抓取图像,使用下面的代码片段,但是它无法抓取任何帧(frame_grab总是false)

import cv2
import numpy as np

# reading the video from CAM0
source = cv2.VideoCapture(1)

height = 1920
width = 1080

source.set(cv2.CAP_PROP_FRAME_WIDTH, width)
source.set(cv2.CAP_PROP_FRAME_HEIGHT, height)

image = np.zeros([height, width, 3], np.uint8)

while True:
    # Extracting the frames
    frame_grabbed , image = source.read()

    if (frame_grabbed ):
        colour1 = cv2.cvtColor(image, cv2.COLOR_BayerRG2BGR)
        cv2.imshow("Demosaiced image", colour1)
    else:
        print("No images grabbed")

#Exit on q
    key = cv2.waitKey(1)
    if key == ord("q"):
       break

# closing the window
cv2.destroyAllWindows()
source.release()

我们是不是漏掉了什么?
然后我们看到了这篇文章,它把ffmpeg输出通过管道传输到python(link)。但是,当我们传递下面的命令时:

command = [ 'ffmpeg.exe',
            '-f', 'dshow',
            '-i', 'video="CAM0"',
            '-pix_fmt', 'gray',
            '-video_size','1920x1080'
            '-f', 'nut', '-']

其投掷
在视频类型的源设备中找不到名为[“CAM 0”]的视频设备。video=“CAM 0”:I/O错误
我已使用以下命令验证摄像头是否存在:

command = [ 'ffmpeg.exe',
            '-list_devices', 'true',
            '-f', 'dshow',
            '-i', 'dummy']

这将检测CAM 0,如下所示:

ffmpeg version 5.0.1-full_build-www.gyan.dev Copyright (c) 2000-2022 the FFmpeg developers
  built with gcc 11.2.0 (Rev7, Built by MSYS2 project)
  configuration: --enable-gpl --enable-version3 --enable-static --disable-w32threads --disable-autodetect --enable-fontconfig --enable-iconv --enable-gnutls --enable-libxml2 --enable-gmp --enable-bzlib --enable-lzma --enable-libsnappy --enable-zlib --enable-librist --enable-libsrt --enable-libssh --enable-libzmq --enable-avisynth --enable-libbluray --enable-libcaca --enable-sdl2 --enable-libdav1d --enable-libdavs2 --enable-libuavs3d --enable-libzvbi --enable-librav1e --enable-libsvtav1 --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxavs2 --enable-libxvid --enable-libaom --enable-libopenjpeg --enable-libvpx --enable-mediafoundation --enable-libass --enable-frei0r --enable-libfreetype --enable-libfribidi --enable-liblensfun --enable-libvidstab 
--enable-libvmaf --enable-libzimg --enable-amf --enable-cuda-llvm --enable-cuvid --enable-ffnvcodec --enable-nvdec --enable-nvenc --enable-d3d11va --enable-dxva2 --enable-libmfx --enable-libshaderc --enable-vulkan --enable-libplacebo --enable-opencl --enable-libcdio --enable-libgme --enable-libmodplug --enable-libopenmpt --enable-libopencore-amrwb --enable-libmp3lame --enable-libshine --enable-libtheora --enable-libtwolame --enable-libvo-amrwbenc --enable-libilbc --enable-libgsm --enable-libopencore-amrnb --enable-libopus --enable-libspeex --enable-libvorbis --enable-ladspa --enable-libbs2b --enable-libflite --enable-libmysofa --enable-librubberband --enable-libsoxr --enable-chromaprint
  libavutil      57. 17.100 / 57. 17.100
  libavcodec     59. 18.100 / 59. 18.100
  libavformat    59. 16.100 / 59. 16.100
  libavdevice    59.  4.100 / 59.  4.100
  libavfilter     8. 24.100 /  8. 24.100
  libswscale      6.  4.100 /  6.  4.100
  libswresample   4.  3.100 /  4.  3.100
  libpostproc    56.  3.100 / 56.  3.100
[dshow @ 000001ea39e40600] "HP HD Camera" (video)
[dshow @ 000001ea39e40600]   Alternative name "@device_pnp_\\?\usb#vid_04f2&pid_b6bf&mi_00#6&1737142c&0&0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\global"
[dshow @ 000001ea39e40600] "CAM0" (video)
[dshow @ 000001ea39e40600]   Alternative name "@device_pnp_\\?\usb#vid_0400&pid_0011&mi_00#7&1affbd5b&0&0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\global"

简而言之,我们可以使用ffmpeg命令行捕获视频,但无法使用OpenCV videocapture或opencv中的ffmpeg捕获任何帧。
谢谢你!

xsuvu9jc

xsuvu9jc1#

我不知道为什么使用OpenCV阅读帧不起作用,但我们可以使用FFmpeg CLI代替。

  • 执行FFmpeg作为子进程,并将输出设置为stdout管道。
  • stdout管道读取原始视频帧,并将每个帧转换为1920x1080 uint8 NumPy数组。

代码示例:

import cv2
import numpy as np
import subprocess as sp

width = 1920
height = 1080

ffmpeg_command = ['ffmpeg',  # Make sure ffmpeg.exe is in the execution path
                  '-f', 'dshow',  # The input format is dshow (camera)
                  '-video_size', f'{width}x{height}',  # input resolution is 1920x1080
                  '-pixel_format', 'gray',  # input pixel format is gray
                  '-i', 'video=CAM0',  # May also try 'video="CAM0"'
                  '-f', 'rawvideo',  # The output format is rawvideo
                  '-pix_fmt', 'gray',  # The output pixel format is gray
                  'pipe:']  # Output the video to stdout pipe

# Open sub-process that gets in_stream as input and uses stdout as an output PIPE.
ffmpeg_process = sp.Popen(ffmpeg_command, stdout=sp.PIPE)

while True:
    # Read width*height bytes from stdout (1 frame)
    raw_frame = ffmpeg_process.stdout.read(width*height)

    if len(raw_frame) != (width*height):
        print('Error reading frame!!!')  # Break the loop in case of an error (too few bytes were read).
        break

    # Convert the bytes read into a NumPy array, and reshape it to video frame dimensions
    frame = np.frombuffer(raw_frame, np.uint8).reshape((height, width))

    # Show the video frame
    cv2.imshow('frame', frame)
    key = cv2.waitKey(1)
    if key == ord("q"):
        break

ffmpeg_process.stdout.close();  # Closing stdout pipe also terminates FFmpeg sub-process.
cv2.destroyAllWindows()
kwvwclae

kwvwclae2#

尝试使用'rawvide'作为输出格式。您可能需要将所有相机选项移到-i参数的左侧。
你可以试试我的ffmpegio package如果你需要一个快速和肮脏的方式:

import ffmpegio

show_log = True

# if you have to record for a fixed duration 
t_record = 5
fs,F = ffmpegio.video.read('video=CAM0',f_in='dshow',
                           'pix_fmt='gray', video_size_in='1920x1080', t=5,
                           show_log=show_log)

# if you need to stream input
with ffmpegio.open('video=CAM0','rv', f_in='dshow',
                   'pix_fmt_in='gray', video_size_in='1920x1080',
                   show_log=show_log) as cam:
    for frame in cam:
        # frame = np.array of shape (1x)1920x1080x1 (I think, reshape as needed)

如果你需要这方面的帮助,请在GitHub讨论板上创建一个主题(不要在这里乱作一团)。

相关问题