【问题标题】:OpenCV displays the image triplicated in a single frameOpenCV 在单帧中显示三次重复的图像
【发布时间】:2014-03-20 13:24:51
【问题描述】:

我正在尝试构建一个应用程序来简单地获取、保存和显示来自我的相机 DMK 41BU02 的一些帧(您可以在以下链接中查阅设备的规格:datasheet

我的代码就这么简单:

#include "opencv2/opencv.hpp"

using namespace std;
using namespace cv;

int main(int, char**)
{
    String path="~/proof.jpg";
    VideoCapture cap(1); // /dev/video0 is the integrated webcam of my laptop, while /dev/video1 is the DMK41BU02 camera
    cvNamedWindow( "Video", CV_WINDOW_AUTOSIZE );
    if(!cap.isOpened())  // check if we succeeded
        return -1;

    Mat frame;
    cap >> frame;
    imwrite(path, frame);
    imshow("Video", frame);
    waitkey(0);

    return 0;
}

代码编译并执行没有任何问题,但是当图像显示在窗口上或保存在 jpg 文件中时出现错误,因为我得到类似于以下 jpg 的内容,其中图像被 三重复制 在框架中:

Resulting image of the code shown above

需要说明的一些方面:

  1. 代码正常执行,工作时返回正常图片 使用笔记本电脑的集成网络摄像头。
  2. DMK41BU02 摄像头正常工作,并在与 fswebcam 或 VLC 等其他应用程序一起使用时返回正常图像。
  3. 相机数据表显示它与 OpenCV 兼容。
  4. 我也尝试过无限循环的代码,因为我知道抓取的第一帧可能是空白的或出现某种类型的错误,但问题仍然存在。
  5. 我在安装相机驱动程序时遇到了一些问题,但我认为它们都已解决。
  6. 笔记本电脑是一台安装了 Ubuntu 的 32 位机器。这里可以看到uname -a的输出:Linux AsusPC 3.11.0-18-generic #32~precise1-Ubuntu SMP Thu Feb 20 17:54:21 UTC 2014 i686 i686 i386 GNU/Linux

我不知道如何调试这个问题,当然,我也不知道错误可能出在哪里。请给我一些提示好吗?

非常感谢。



更新:我忘记在程序开始时发布应用程序在终端中写入的奇怪输出:

VIDIOC_QUERYMENU: Invalid argument
VIDIOC_QUERYMENU: Invalid argument
VIDIOC_QUERYMENU: Invalid argument
VIDIOC_QUERYMENU: Invalid argument
libv4l2: error set_fmt gave us a different result then try_fmt!
HIGHGUI ERROR: libv4l unable convert to requested pixfmt
libv4l2: error set_fmt gave us a different result then try_fmt!
init done 
opengl support available

【问题讨论】:

  • waitkey(0) 似乎要等待 0 毫秒才能绘制图像并且似乎拼写错误(代码编译?),使用 waitKey(10);你也可以 cout frame.cols、frame.rows、frame.ch、frame.type() 吗?
  • @Vlad waitKey(0) 不会等到某个键被按下?我总是为此使用waitKey(-1),所以我不确定=)@Alejandro 我猜openCV会误解你相机的图像数据(看起来所有3个颜色通道都在一个太大的灰度图像内),但我不知道对VideoCapture 对象没有太多经验,所以我不能告诉你如何解决这个问题。
  • 据我所知,waitKey(0) 会一直等待,直到按下某个键,我的程序也是如此。
  • 抱歉,我没有发表我的全部评论,这里是其余的:我让你在这里,@Vlad,你要求的 cout(除了 frame.ch,因为我不知道做什么你的意思是): COLS:1280 ROWS:960 TYPE:16
  • 好吧,我的意思是 m.channels(),对不起。 16 表示您的图像类型是 CV_8UC3,它是 3 通道 rgb unsigned char 数组,根据需要。所以相机或 opecCV 代码应该有问题,而不是你的代码。不过,这三张图片并不是精确的复制品(请注意右下角的 4 个明亮的点簇),所以我会先检查你的相机。 yuv 格式的 A - uv 通常比 Y 压缩 4 倍,但您的图像大小相同,所以情况并非如此。

标签: c++ opencv


【解决方案1】:

我遇到了完全相同的问题。问题在于 openCV 本身,或者更多; cap_v4l.hpp(在 highgui 模块中)和 cap_libv4l.hpp 是如何实现的。

这里的问题是 OpenCV 似乎使用了错误的视频类型或通道类型来读取数据。尝试在 opencv 库中使用不同类型(yuyv 变体等)。

由于某种神奇的原因,cap_v4l.hpp 是 opencv 实际使用的代码,而 cap_lib4l 中的代码未使用,但似乎支持更多视频格式(可以左右切换,我不确定) .

切换这些文件并重新编译 opencv 对我来说确实有所改善。

【讨论】:

  • 非常感谢@Nallta,但我不确定我是否理解你;我一直在寻找那些文件,我只在我的机器中找到了一个 cap_v4l.cpp,其中有一些对这些 YUYV 变体的引用,但我不知道如何处理它们。你能再明确一点吗?非常感谢您的宝贵时间。还要看看更新的问题,所以我在程序的最开始发布了在终端中写入的输出。再次感谢您!:)
  • 我确实有一个 cap_lib4vl.cpp,它是 opencv 2.4.8 版本的一部分。您发布的额外错误与我遇到的相同。切换代码为我解决了这些问题。
  • 再次感谢您,@Nallath!但是切换代码是什么意思?将 cap_lib4l 的内容复制到另一个中?
  • 我就是这么做的。不过,您确实需要在之后重新编译它。
  • 我昨天尝试在切换cap_libv4l.cpp和cap_v4l.cpp的代码后重新编译OpenCV(我没有.hpp也没有.h)但是,我的程序不再编译了现在,它说cvNamedWindowCV_WINDOW_AUTOSIZE“未在此范围内声明”。我试图写 cv::cvNamedWindow 但它不起作用。还有什么想法吗?为什么我的机器中没有 .hpp 文件?非常感谢
【解决方案2】:

由于调用 cap>>frame 后您有三个通道(类型 = 16),因此您的捕获不知道您的相机是单色的。请改用grab-retrieve pairs,因为retrieve 指定了频道数。

bool VideoCapture::grab()  
bool VideoCapture::retrieve(Mat& image, int channel=0)

这里是示例code,它还显示了如何设置相机参数。您还可以尝试设置一些明确声明单色模式的相机参数。如果其他一切都失败了,你总是可以用

从你的三张图片中剪下一张图片
Rect rect(0, 0, frame.cols/3, frame.rows);
Mat true_img = frame(rect).clone();

不过,我有点喜欢你的情况。您有一个自然的帧队列,并且可以通过查看三个连续帧中发生的情况来分析运动可能的结构。

【讨论】:

  • 谢谢,这似乎是一个很好的解决方案!我明天试试,我们会看到:)
  • grab-retrieve 解决方案不起作用 :( 在决定简单裁剪图像之前,我会尝试其他解决方案,谢谢!!
猜你喜欢
  • 2019-12-03
  • 1970-01-01
  • 2013-10-31
  • 1970-01-01
  • 1970-01-01
  • 2016-02-02
  • 1970-01-01
  • 2013-08-08
  • 2017-05-04
相关资源
最近更新 更多