如何在Linux上从网络摄像头捕获静止图像
我正在尝试为Linux编写一个C ++/Qt程序,在该程序中,我从网络摄像头拍摄了静态图像照片,并对照片进行了一些转换(裁剪,调整大小等),然后将其保存到jpeg文件中.
I am trying to write a C++/Qt program for linux, where I take a still image photo from a webcam, make some transformations to a photo (cropping, resizing, etc.), and save it to a jpeg file.
但是我遇到了一些问题.主要问题是Standart UVC(USB视频设备类)Linux驱动程序当前不支持直接静止图像捕获: http://www.ideasonboard .org/uvc/.
But I have encountered some problems. The main problem is that standart UVC (usb video device class) linux driver currently does not support direct still image capture: http://www.ideasonboard.org/uvc/ .
因此,有两种可能的方式来捕获静止图像.您可以从相机的视频流中拍摄一帧,也可以拍摄单独的照片,例如数码便携式相机. linux uvc驱动程序不支持第二种方法,因此第一种方法是唯一的方法.但是问题是,如果要从视频流中取一帧,则照片的大小不能大于视频预览窗口中的视频大小.因此,如果我想拍摄2百万像素的照片,则必须以1600x1200的大小开始视频流,这并不是那么舒服(至少在Qt中,视频流的大小取决于视频预览窗口的大小).
So, there are two possible ways to capture still image. You can take one frame from the video stream from the camera, or you can take a separate photo, like a digital portable camera. The second way is not supported in linux uvc driver, so the first method is the only way. But the problem is, that if you want to take a frame from the video stream, the size of the photo can't be bigger than the size of video in the video preview window. So, if I want to take 2 megapixel photo, I must start videostream with the size 1600x1200, which is not so comfortable (At least, in Qt the size of the videostream depends on the videopreview window size).
我知道有用于linux 2 API的视频,这可能对完成此任务很有帮助,但是我不知道如何使用它.我目前正在学习gstreamer,但现在无法弄清楚如何使用这些工具来完成所需的工作.
I know that there is video for linux 2 API, which may be helpful in this task, but I don't know how to use it. I am currently learning gstreamer, but I can't now figure out how to do what I need using these tools.
因此,我将不胜感激.对于那些了解Linux,GStreamer,v4l2 API和其他特定于Linux的知识的人来说,我认为这不是一个难题.
So, I will appreciate any help. I think it is not a hard problem for people who know Linux, GStreamer, v4l2 API, and other linux-specific things.
顺便说一句,该程序将仅与网络摄像机Logitech C270 HD一起使用.
By the way, the program will be used only with web-camera Logitech C270 HD.
请帮帮我.我不知道什么API或框架可以帮助我做到这一点.也许你知道.
Please, help me. I don't know what API or framework can help me do this. May be you know.
不幸的是,opencv中的C4V2调用不适用于我尝试使用UVC驱动程序开箱即用的任何相机进行的静态图像捕获.
Unfortunately the C4V2 calls in opencv did not work for still image capture with any camera I have tried out of the box using the UVC driver.
要调试此问题,我一直在尝试通过直接调用c4v2的C代码来完成此任务.
To debug the issue I have been playing with trying to accomplish this with c code calling c4v2 directly.
我一直在使用此处找到的示例代码.它使用从视频流中提取帧的方法.
I have been playing with the example code found here. It uses the method of pulling frames from the video stream.
您可以使用以下命令进行编译:
You can compile it with:
gcc -O2 -Wall `pkg-config --cflags --libs libv4l2` filename.c -o filename
我已经尝试了3台Logitech相机.最好的似乎是Logitech C910.但是,即使它也有重大问题.
I have experimented with 3 logitech cameras. The best of the lot seems to be the Logitech C910. But even it has significant issues.
这是我尝试用此代码完成相同任务时遇到的问题.
Here are the problems I have encountered trying to accomplish your same task with this code.
每次将其宽度和高度设置为1920x1080时,它几乎都能正常工作.
It works pretty much every time with width and height set to 1920x1080.
例如,当我直接从命令行查询其他可能性时,
When I query other possibilities directly from the command line using for example:
v4l2-ctl --list-formats-ext
,然后尝试将其挂在选择中的其他一些可用"较小尺寸中,以等待相机释放缓冲区.
and I try some of the other "available" smaller sizes it hangs in the select waiting for the camera to release the buffer.
另外,当我尝试使用以下命令直接从命令行设置其他尺寸时:
Also when I try to set other sizes directly from the command line using for example:
v4l2-ctl -v height=320 -v width=240 -v pixelformat=YUYV
然后使用
v4l2-ctl -V
我发现它返回正确的像素格式,但通常返回的尺寸不正确.
I find that it returns the correct pixel format but quite often not the correct size.
显然,在 UVC站点上列出的此摄像机是UVC,因此不兼容v4l2达到鼻烟.我怀疑这对其他相机同样有害.我尝试的其他两个在该站点上也被列为兼容,但存在更严重的问题.
Apparently this camera which is listed on the UVC site as being UVC and therefore v4l2 compatible is not up to snuff. I suspect it is just as bad for other cameras. The other two I tried were also listed as compatible on the site but had worse problems.
发布此文件后,我在LogitechC910上做了更多测试.我以为我会发布结果,以防其他人解决.
I did some more testing on the LogitechC910 after I posted this. I thought I would post the results in case it helps someone else out.
我写了一个脚本来测试上述提到的v4l2采集卡代码,使用v4l2查询相机声称支持的所有格式,以下是结果:
I wrote a script to test v4l2 grabber code mentioned above on all the formats the camera claims it supports when it is queried with v4l2 here are the results:
640x480 => Hangs on clearing buffer
160x120 => Works
176x144 => Works
320x176 => Works
320x240 => Works
432x240 => Works
352x288 => Works
544x288 => Works
640x360 => Works
752x416 => Hangs on clearing buffer
800x448 => Hangs on clearing buffer
864x480 => Works
960x544 => Works
1024x576 => Works
800x600 => Works
1184x656 => Works
960x720 => Works
1280x720 => Works
1392x768 => Works
1504x832 => Works
1600x896 => Works
1280x960 => Works
1712x960 => Works
1792x1008 => Works
1920x1080 => Works
1600x1200 => Works
2048x1536 => Works
2592x1944 => Hangs on clearing buffer.
事实证明,默认设置640x480不起作用,这正是我和大多数其他张贴在留言板上的人所困的.
It turns out that the default setting of 640x480 doesnt work and that is what trapped me and most others who have posted on message boards.
由于它正在抓取视频帧,因此启动时抓取的第一帧可能具有错误的曝光(通常为黑色或接近黑色).我相信这是因为,由于它被用作摄像机,因此可以随时调整曝光,而不必担心前几帧.我相信这也使我和其他人陷入困境,他们看到第一帧为黑色或接近黑色,并认为这是某种错误.以后的相框曝光正确
Since it is grabbing a video frame the first frame it grabs when starting up may have incorrect exposure (often black or close to it). I believe this is because since it is being used as a video camera it adjusts exposure as it goes and doesnt care about the first frames. I believe this also trapped me and other who saw the first frame as black or nearly black and thought it was some kind of error. Later frames have the correct exposure
事实证明,如果您避免上面列出的地雷并忽略所有错误消息,那么带有python包装器的opencv可以在此相机上正常工作.错误消息是由于相机接受v4l2命令而无法正确响应所致.因此,如果您设置宽度,它实际上会正确设置,但是它会以不正确的宽度进行响应.
It turns out that opencv with python wrappers works fine with this camera if you avoid the land mines listed above and ignore all the error messages. The error messages are due to the fact while the camera accepts v4l2 commands it doesnt respond correctly. So if you set the width it actually gets set correctly but it responds with an incorrect width.
要在带有Python包装程序的opencv下运行,您可以执行以下操作:
To run under opencv with python wrappers you can do the following:
import cv2
import numpy
cap = cv2.VideoCapture(0) #ignore the errors
cap.set(3, 960) #Set the width important because the default will timeout
#ignore the error or false response
cap.set(4, 544) #Set the height ignore the errors
r, frame = cap.read()
cv2.imwrite("test.jpg", frame)