在正常的快门延迟中,传感器驱动程序将捕获的图像缓冲区提供给v4l2层,这里jpeg(硬件)标头添加了一些额外的数据(exif信息和缩略图),并且该层使图像缓冲区预览堆(在HAL层中)以进行进一步处理.但是在零快门滞后的情况下拍摄照片的过程是什么.这与正常的快门滞后相同吗?如何缩短拍照和图像处理之间的时间.如果不是解释.
我正在尝试使用 gstreamer 将网络摄像头的流保存为一系列图像。到目前为止我已经写了这段代码......
#!/usr/bin/python
import sys, os
import pygtk, gtk, gobject
import pygst
pygst.require("0.10")
import gst
def __init__(self):
#....
# Code to create a gtk Window
#....
self.player = gst.Pipeline("player")
source = gst.element_factory_make("v4l2src", "video-source")
sink = gst.element_factory_make("xvimagesink", "video-output")
caps = gst.Caps("video/x-raw-yuv, width=640, height=480")
filter = gst.element_factory_make("capsfilter", "filter")
filter.set_property("caps", caps)
self.player.add(source, filter, sink)
gst.element_link_many(source, filter, sink)
Run Code Online (Sandbox Code Playgroud)
之后,我尝试通过总线创建一个信号来侦听来自源或接收器的任何消息,以指示已发送或接收新帧,以便可以保存它。
bus = self.player.get_bus()
bus.add_signal_watch()
bus.connect("message::any", self.save_file,"Save file")
Run Code Online (Sandbox Code Playgroud)
其中 save_file 是我的回调,我要在其中保存文件。
def save_file(self, bus, msg):
print "SAVED A NEW FILE"
Run Code Online (Sandbox Code Playgroud)
我有两个问题,
更新(2012 …
我正在尝试设置网络摄像头的 fps 和分辨率,并通过 v4l2 Python 进行捕获。
v4l2 Python 文档仅限于;
>>> import v4l2
>>> import fcntl
>>> vd = open('/dev/video0', 'rw')
>>> cp = v4l2.v4l2_capability()
>>> fcntl.ioctl(vd, v4l2.VIDIOC_QUERYCAP, cp)
0
>>> cp.driver
'ov534'
>>> cp.card
'USB Camera-B4.09.24.1'
Run Code Online (Sandbox Code Playgroud)
查看 videodev2.h ;
#define VIDIOC_S_PARM _IOWR('V', 22, struct v4l2_streamparm)
Run Code Online (Sandbox Code Playgroud)
VIDIOC_S_PARM 与 v4l2_streamparm 相关;
struct v4l2_streamparm {
enum v4l2_buf_type type;
union {
struct v4l2_captureparm capture;
struct v4l2_outputparm output;
__u8 raw_data[200]; /* user-defined */
} parm;
};
Run Code Online (Sandbox Code Playgroud)
如果我想设置参数;
import v4l2
import fcntl
vd = open('/dev/video1', 'rw') …Run Code Online (Sandbox Code Playgroud) 如何使用libavdevice正确查询系统中的所有视频设备?打开输入int err = avformat_open_input(&context, NULL, fmt, NULL);失败,因为未提供设备名称(第二个参数是设备名称,"/dev/video0"例如,如果提供,则仅找到该设备):
avcodec_register_all();
avdevice_register_all();
AVFormatContext* context = avformat_alloc_context();
AVInputFormat *fmt = av_find_input_format("video4linux");
printf("trying to open input");
int err = avformat_open_input(&context, "/dev/video0", fmt, NULL);
if(err != 0){
fprintf(stderr, "ffmpeg failed to open input");
}
static struct AVDeviceInfoList* devices_list;
avdevice_list_devices(context, &devices_list);
int devices_count = devices_list->nb_devices;
for(int i = 0; i < devices_count; i++){
printf("Checking device nr. %d \n", i);
AVDeviceInfo* current_device_info = devices_list->devices[i];
printf("Find Device: %s", current_device_info->device_description);
}
avformat_free_context(context);
Run Code Online (Sandbox Code Playgroud)
如何初始化 AVFormatContext 以查找所有 v4l2 …
我正在使用OpenCV 3.1和Python 2.7从我的网络摄像头Logitech C270捕获视频帧。我也在使用video4linux2(v4l2)来设置我的相机的属性,但这导致了一些问题。我的操作系统是Ubuntu 15.04。
我要更改的特定属性是absolute_exposure。
我可以通过终端使用v4l2 API手动更改它,使用命令v4l2-ctl --set-ctrl exposure_absolute=40,它工作得很好,但我需要为此任务编写脚本。
使用 OpenCVset(cv2.CAP_PROP_EXPOSURE, 20)会导致“VIDEOIO ERROR: V4L: Property Exposure(15) not supported by device”。我确定网络摄像头支持更改此属性,因为可以使用 v4l2 这样做,然后我假设问题出在 OpenCV 的包装器上。
我还试图用子LIB发送终端命令,并使用更改属性V4L2。命令是subprocess.call('v4l2-ctl --device=/dev/video0 --set-ctrl exposure_absolute=20', shell=True).
结果是 Exposure_absolute 发生了变化,但它不适用于我当前的视频捕获。图 1 显示了通过脚本设置属性后的结果。图 2 显示了通过终端设置相同属性后的结果,相同的视频捕获处于活动状态。
图 2 是在图 1 之后拍摄的,突出显示的线与图 1 相同。
我在子流程调用上做错了什么吗?或者如何使用脚本更改此属性?
另外,为什么要cv2.VideoCapture(id)重置相机属性,在运行脚本之前更改它们是没有用的,是否可以停止?
__________________________________________________
编辑:我可能找到了解决此问题的方法。子进程调用确实是正确的,我只需要cv2.read()在更改属性之前使用一次,显然第一个 …
我正在为Raspbian(Raspberry Pi 2)中的Python开发视频捕获脚本,由于在内存映射缓冲区方面没有成功,因此无法为v4l2使用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 …Run Code Online (Sandbox Code Playgroud) 我正在开发一个 v4l2 API,用于从嵌入式平台上的原始传感器捕获图像。我的捕获例程与[1]上的示例有关。建议的流式传输方法是使用 mmaped 缓冲区作为环形缓冲区。
对于初始化,使用带有 VIDIOC_REQBUFS 标识符的 ioctl 请求缓冲区(默认 = 4 个缓冲区)。随后,它们使用 VIDIOC_QBUF 排队。此处描述了整个流式传输过程[2]。一旦流开始,驱动程序就会用数据填充排队的缓冲区。v4l2_buffer 结构的时间戳表示捕获的第一个字节的时间,在我的情况下,这导致缓冲区之间的时间间隔约为 8.3 ms (=120fps)。到现在为止还挺好。
现在我对环形缓冲区的期望是新捕获以循环方式自动覆盖旧捕获。但事实并非如此。只有当缓冲区在出队 (VIDIOC_DQBUF) 和处理(去马赛克、跟踪步骤等)后再次排队 (VIDIOC_QBUF) 时,才会将新帧分配给缓冲区。如果我确实满足时序条件(处理 < 8.3 ms),则出队时我不会得到最新捕获的帧,而是最旧的捕获帧(根据 FIFO),因此是当前帧之前 3x8.3 ms 的帧。如果不满足时序条件,则时间跨度会变得更大,因为缓冲区不会被覆盖。
所以我有几个问题:
1. 这个跟踪应用程序有一个环形缓冲区是否有意义,因为我真的不需要帧的历史记录?我当然对此表示怀疑,但是通过使用建议的 mmap 方法,驱动程序通常需要请求最少数量的缓冲区。
2. 一个单独的线程是否应该连续使用 DQBUF 和 QBUF 来完成缓冲区覆盖?这怎么可能实现?
3. 作为一种解决方法,您可能会在每次捕获时使所有缓冲区出队和重新入队,但这听起来不对。是否有人在实时捕获和流式传输方面具有更多经验,可以指出“正确”的方法?
4. 目前,我正在 DQBUF 和 QBUF 之间进行预处理步骤(去马赛克)以及之后的跟踪步骤。在再次调用 QBUF 之前是否也应该执行跟踪步骤?
所以主要代码基本上是在一个while循环中依次执行Capture()和Track()。Capture 例程如下所示:
cv::Mat v4l2Camera::Capture( size_t timeout ) {
fd_set fds;
FD_ZERO(&fds);
FD_SET(mFD, &fds);
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 0;
const bool …Run Code Online (Sandbox Code Playgroud) 我有一个科学应用程序,可以捕获 video4Linux 视频流。捕捉每一帧并且不丢失任何人是至关重要的。不幸的是,框架到处都不见了,我不知道为什么。
为了检测丢帧,我在读取帧后直接将 v4l2_buffer 的序列号与我自己的计数器进行比较:
void detectDroppedFrame(v4l2_buffer* buffer) {
_frameCounter++;
auto isLastFrame = buffer->sequence == 0 && _frameCounter > 1;
if (!isLastFrame && _frameCounter != buffer->sequence+1)
{
std::cout << "\n####### WARNING! Missing frame detected!" << std::endl;
_frameCounter = buffer->sequence+1; // re-sync our counter with correct frame number from driver.
}
}
Run Code Online (Sandbox Code Playgroud)
我的运行 1 文件示例要点可以在 github 上找到(基于官方 V4L2 捕获示例):https://gist.github.com/SebastianMartens/7d63f8300a0bcf0c7072a674b3ea4817
在笔记本硬件(uvcvideo 驱动程序)上的 Ubuntu 18.04 虚拟机上使用网络摄像头进行了测试,并在本地运行 ubuntu 18.04 的嵌入式硬件上使用 CSI 摄像头进行了测试。帧未处理,缓冲区似乎被足够快地抓取(使用 VIDIOC_QUERYBUF 检查缓冲区状态,这表明所有缓冲区都在驱动程序的传入队列中,并且未设置 V4L2_BUF_FLAG_DONE 标志)。我使用 MMAP 以及 UserPtr 方法丢失了帧。而且它似乎与像素格式、图像大小和帧速率无关!
对我来说,如果相机/v4l2驱动程序无法足够快地填充可用缓冲区,但使用VIDIOC_S_PRIORITY命令增加文件描述符优先级也没有帮助(仍然可能是线程调度问题?)。
=> …
我正在尝试从我的网络摄像头创建一个环回设备,以便可以从 Zoom 和浏览器访问。我创建了三个 v4l2loopback 设备:
sudo modprobe v4l2loopback devices=3 video_nr=10,11,12 card_label="Loopback_1","Loopback_2","Virtual_cam" exclusive_caps=1,1,0
Run Code Online (Sandbox Code Playgroud)
其次是:
ffmpeg -i /dev/video0 -f v4l2 -vcodec rawvideo -pix_fmt yuv420p /dev/video10 -f v4l2 /dev/video11
Run Code Online (Sandbox Code Playgroud)
Chrome 可以检测到这两种设备,但 Zoom 和 Firefox 都无法检测到。根据 stackoverflow 上其他问题的建议,我尝试使用 v4l2loopback-ctl 设置设备属性,使用v4l2loopback-ctl set-caps "video/x-raw,format=UYVY,width=640,height=480" /dev/video10,并得到响应:
将管道设置为暂停...错误:管道不想暂停。错误:来自元素 /GstPipeline:pipeline0/GstV4l2Sink:v4l2sink0:设备“/dev/video10”不是输出设备。附加调试信息:v4l2_calls.c(636):gst_v4l2_open():/GstPipeline:pipeline0/GstV4l2Sink:v4l2sink0:功能:0x85208000将管道设置为NULL...释放管道...输出到/dev/video10失败
我还尝试使用 gst-launch-1.0:
gst-launch-1.0 v4l2src device=/dev/video0 ! v4l2sink device=/dev/video10
Run Code Online (Sandbox Code Playgroud)
这告诉我 /dev/video10 不是输出设备:
将管道设置为暂停...错误:管道不想暂停。错误:来自元素 /GstPipeline:pipeline0/GstV4l2Sink:v4l2sink0:设备“/dev/video10”不是输出设备。附加调试信息:v4l2_calls.c(636):gst_v4l2_open():/GstPipeline:pipeline0/GstV4l2Sink:v4l2sink0:功能:0x85208000将管道设置为NULL...释放管道...
我正在运行 Xubuntu 20.04、内核版本 5.4.0-52-generic、v4l2loopback-dkms v.0.12.3-1ubuntu0.1 和 v4l2loopback-utils。
我的目标是让桌面 Node.js 服务器使用一个设备,该服务器将使用xdg-open(因此需要 Chrome 和 Firefox)打开一个 Web 应用程序,该应用程序将输出可被视频使用的已处理视频流聊天应用程序,例如 Zoom 或 Jitsi。
任何帮助将不胜感激。
我一直在努力编写 C++ 代码来从网络摄像头捕获图片。我成功地做到了,但我想对我所采取的过程进行一些澄清。
所以我的代码可以用6个步骤来描述,我将它们和我的问题一起写在这里: 一、步骤:初始化设备并设置图像格式。
const char* dev_name = "/dev/video0";
int width=320;
int height=240;
int fd = v4l2_open(dev_name, O_RDWR | O_NONBLOCK, 0);
struct v4l2_format format = {0};
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
format.fmt.pix.width = width;
format.fmt.pix.height = height;
format.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;//V4L2_PIX_FMT_YUYV //V4L2_PIX_FMT_RGB24
format.fmt.pix.field = V4L2_FIELD_NONE; //V4L2_FIELD_NONE
xioctl(fd, VIDIOC_S_FMT, &format);
Run Code Online (Sandbox Code Playgroud)
二. 步骤:请求缓冲区。
struct v4l2_requestbuffers req = {0};
req.count = 2;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
xioctl(fd, VIDIOC_REQBUFS, &req);
Run Code Online (Sandbox Code Playgroud)
三.步骤:查询缓冲区和映射。
struct v4l2_buffer buf;
buffer* buffers;
unsigned int i;
buffers = (buffer*) …Run Code Online (Sandbox Code Playgroud) v4l2 ×10
c++ ×3
python ×3
ffmpeg ×2
gstreamer ×2
opencv ×2
python-2.7 ×1
subprocess ×1
ubuntu-15.04 ×1
v4l2loopback ×1
webcam ×1