OpenCV和GoPro-VideoCapture流中的空帧

OpenCV and GoPro - empty frames in VideoCapture stream

本文关键字:GoPro-VideoCapture OpenCV      更新时间:2023-10-16

我有一个GoPro Hero 3+(黑色),它连接到视频捕获卡(AverMedia Game Broadcaster HD)。我只是想在OpenCV中获得视频流。有了罗技网络摄像头就没有问题了。使用的代码如下。

VideoCapture cap;
cap.open(0);
waitKey(300);
//cap.set(CV_CAP_PROP_FRAME_WIDTH, 1280);
//cap.set(CV_CAP_PROP_FRAME_HEIGHT, 720);
if (cap.isOpened()){
    cout << "Cam identified" << endl;
}
namedWindow("dst", 1);
while (1){
Mat frame;
if (!cap.read(frame)) {
    std::cout << "Unable to read frame from video stream" << std::endl;
    continue;
}
imshow("dst", frame);
[...]
}

使用GoPro会发生以下情况:OpenCV能够打开VideoCapture("摄像头已识别"),但无法读取任何帧(只有灰色屏幕和输出:"无法从视频流中读取帧")。我还用frame.empty();检查了这一点;。

我知道视频捕获卡工作正常,因为Unity使用GoPro流打开WebCamTexture没有任何问题。我读到OpenCv中的编解码器问题,所以我已经尝试编译支持FFMPEG的OpenCv。现在可以显示GoPro录制的MP4视频,但流仍然不起作用。

我使用OpenCV 2.48、Windows 7和Visual Studio 2013。


编辑:以下是libVLC解决方案的代码:

struct ctx
{
uint8_t* pixeldata;
std::mutex imagemutex;
};
static void display(void *data, void *id);
static void unlock(void *data, void *id, void *const *p_pixels);
static void *lock(void *data, void **p_pixels);
struct ctx ctx;
libvlc_instance_t *inst;
libvlc_media_player_t *mp;
libvlc_media_t *m;
int main(int argc, char* argv[])
{
    ctx.pixeldata = new uint8_t[1280 * 720 * 3];
    char const *vlc_argv[] =
    {
        "-vvv",
        "--no-audio", /* skip any audio track */
        "--no-xlib", /* tell VLC to not use Xlib */
    };
    int vlc_argc = sizeof(vlc_argv) / sizeof(*vlc_argv);
    inst = libvlc_new(vlc_argc, vlc_argv);
    const char *options[] =
    {
        ":dshow-vdev=AVerMedia HD Capture",
        ":dshow-adev=none",
        //":dshow-size=1280x720",
        ":dshow-fps=24",
        ":dshow-chroma=YUY2",
        ":dshow-video-input=1",
        ":dshow-video-output=1",
        ":dshow-aspect-ratio=16:9",
        ":live-caching=80",
        NULL
    };
    m = libvlc_media_new_location(inst, "dshow://");
    for (const char **opt = options; *opt; opt++)
        libvlc_media_add_option(m, *opt);
    mp = libvlc_media_player_new_from_media(m);
    libvlc_media_release(m);
    libvlc_video_set_callbacks(mp, lock, unlock, display, &ctx);
    libvlc_video_set_format(mp, "RV24", 1280, 720, 1280 * 3);
    libvlc_media_player_play(mp);
    namedWindow("all", 1);
    Mat frame(720, 1280, CV_8UC3);
    while (1){
        ctx.imagemutex.lock();
        memcpy(gesamt.data, ctx.pixeldata, 1280 * 720 * sizeof(uint8_t) * 3);
        ctx.imagemutex.unlock();
        imshow("all", gesamt);
        if (waitKey(30) == 27) //wait for 'esc' key press for 30ms. If 'esc' key is pressed, break loop
        {
            cout << "esc key is pressed by user" << endl;
            break;
        }
    }
    libvlc_media_player_stop(mp);
    libvlc_media_player_release(mp);
    libvlc_release(inst);
    delete[] ctx.pixeldata;
    return 0;
}
void display(void *data, void *id){
    (void)data;
    assert(id == NULL);
}
void unlock(void *data, void *id, void *const *p_pixels){
    struct ctx *ctx = (struct ctx*)data;
    ctx->imagemutex.unlock();
    assert(id == NULL);
}
void *lock(void *data, void **p_pixels){
    struct ctx *ctx = (struct ctx*)data;
    ctx->imagemutex.lock();
    *p_pixels = ctx->pixeldata;
    return NULL;
}

我在尝试通过Avermedia捕获卡流式传输索尼动作摄像头时遇到了同样的问题。一个快速的解决方案似乎是使用DVDrive,它使您的捕获卡输出看起来像网络摄像头。我已经成功地将此作为一种变通方法。