python中的用户指针

发布于 2024-08-18 03:44:27 字数 2990 浏览 12 评论 0原文

*我正在尝试显示使用 v4l 捕获的网络摄像头的预览。

代码如下:

from ctypes import *
from v4l2 import *
from Image import fromstring
from Tkinter import Tk, Label
from ImageTk import PhotoImage
from ctypes.util import find_library

libc = CDLL(find_library('c'))
posix_memalign = libc.posix_memalign
getpagesize = libc.getpagesize


device_name = '/dev/video0'
ps = preview_settings = {
    'width': 320,
    'height': 240,
    'pixformat': 'RGB',
    }
PIX_FMT = V4L2_PIX_FMT_RGB555


preview = Tk()
image = PhotoImage(ps['pixformat'], (ps['width'], ps['height']))
label = Label(preview, text='Preview', image=image, width=ps['width'], height=ps['height'])
label.pack()


capability = v4l2_capability()
size = v4l2_frmsizeenum()
format = v4l2_format()
request = v4l2_requestbuffers()
buffer = v4l2_buffer()
b_address = c_void_p()
frame_name_count = '0'
type = V4L2_BUF_TYPE_VIDEO_CAPTURE

device = open(device_name, 'rw')

ioctl(device, VIDIOC_QUERYCAP, addr(capability))

size.pixel_format = PIX_FMT 
size.index = 0

format.type = type
format.fmt.pix.pixelformat = PIX_FMT
format.fmt.pix.width = size.discrete.width
format.fmt.pix.height = size.discrete.height
format.fmt.pix.field = V4L2_FIELD_NONE
format.fmt.pix.bytesperline = 0
format.fmt.pix.sizeimage = 0

request.type = type
request.memory = V4L2_MEMORY_USERPTR
request.count = 1

ioctl(device, VIDIOC_S_FMT, addr(format))

ioctl(device, VIDIOC_G_FMT, addr(format))

ioctl(device, VIDIOC_REQBUFS, addr(request))

posix_memalign(addressof(b_address), getpagesize(), format.fmt.pix.sizeimage)

buffer.type = request.type
buffer.memory = request.memory
buffer.index = 0
buffer.m.userptr = b_address.value
buffer.length = format.fmt.pix.sizeimage

while True:

    ioctl(device, VIDIOC_QBUF, addr(buffer))

    ioctl(device, VIDIOC_STREAMON, cast(type, c_void_p))

    ioctl(device, VIDIOC_DQBUF, addr(buffer))

    preview_data = string_at(buffer.m.userptr, buffer.length)
    im = fromstring(ps['pixformat'], (ps['width'], ps['height']), preview_data)
    image.paste(im)
    preview.update()

我得到 ValueError:没有足够的图像数据


好吧,我导入

c_lib = CDLL(find_library('c'))
posix_memalign = c_lib.posix_memalign
getpagesize = c_lib.getpagesize

然后之后

ioctl(device, VIDIOC_S_FMT, addr(format))
ioctl(device, VIDIOC_G_FMT, addr(format))

诸如此类的事情,我尝试获取内存

posix_memalign(addressof(b_address), getpagesize(), format.fmt.pix.sizeimage)

现在 b_address 不再 = None b_address 类似于 c_void_p(145014784)

然后我开始循环、QBUF、DQBUF 等。

事情是这样的当我调用 pygame.image.frombuffer

pg_img = pygame.image.frombuffer(
         buffer.m.userptr,
         (format.fmt.pix.width, format.fmt.pix.height),
         preview_settings['pixformat']
         )

我得到 TypeError:需要一个字符缓冲区对象

*I am trying to display preview from webcam captured using v4l.

Here is an idea of how the code looks like:

from ctypes import *
from v4l2 import *
from Image import fromstring
from Tkinter import Tk, Label
from ImageTk import PhotoImage
from ctypes.util import find_library

libc = CDLL(find_library('c'))
posix_memalign = libc.posix_memalign
getpagesize = libc.getpagesize


device_name = '/dev/video0'
ps = preview_settings = {
    'width': 320,
    'height': 240,
    'pixformat': 'RGB',
    }
PIX_FMT = V4L2_PIX_FMT_RGB555


preview = Tk()
image = PhotoImage(ps['pixformat'], (ps['width'], ps['height']))
label = Label(preview, text='Preview', image=image, width=ps['width'], height=ps['height'])
label.pack()


capability = v4l2_capability()
size = v4l2_frmsizeenum()
format = v4l2_format()
request = v4l2_requestbuffers()
buffer = v4l2_buffer()
b_address = c_void_p()
frame_name_count = '0'
type = V4L2_BUF_TYPE_VIDEO_CAPTURE

device = open(device_name, 'rw')

ioctl(device, VIDIOC_QUERYCAP, addr(capability))

size.pixel_format = PIX_FMT 
size.index = 0

format.type = type
format.fmt.pix.pixelformat = PIX_FMT
format.fmt.pix.width = size.discrete.width
format.fmt.pix.height = size.discrete.height
format.fmt.pix.field = V4L2_FIELD_NONE
format.fmt.pix.bytesperline = 0
format.fmt.pix.sizeimage = 0

request.type = type
request.memory = V4L2_MEMORY_USERPTR
request.count = 1

ioctl(device, VIDIOC_S_FMT, addr(format))

ioctl(device, VIDIOC_G_FMT, addr(format))

ioctl(device, VIDIOC_REQBUFS, addr(request))

posix_memalign(addressof(b_address), getpagesize(), format.fmt.pix.sizeimage)

buffer.type = request.type
buffer.memory = request.memory
buffer.index = 0
buffer.m.userptr = b_address.value
buffer.length = format.fmt.pix.sizeimage

while True:

    ioctl(device, VIDIOC_QBUF, addr(buffer))

    ioctl(device, VIDIOC_STREAMON, cast(type, c_void_p))

    ioctl(device, VIDIOC_DQBUF, addr(buffer))

    preview_data = string_at(buffer.m.userptr, buffer.length)
    im = fromstring(ps['pixformat'], (ps['width'], ps['height']), preview_data)
    image.paste(im)
    preview.update()

and I get ValueError: not enough image data


well, I import

c_lib = CDLL(find_library('c'))
posix_memalign = c_lib.posix_memalign
getpagesize = c_lib.getpagesize

and then after

ioctl(device, VIDIOC_S_FMT, addr(format))
ioctl(device, VIDIOC_G_FMT, addr(format))

and stuff like that, I try to acquire memory

posix_memalign(addressof(b_address), getpagesize(), format.fmt.pix.sizeimage)

now b_address is no longer = None
b_address is something like c_void_p(145014784)

then I start the loop, QBUF, DQBUF, etc..

the thing is, that when I call pygame.image.frombuffer

pg_img = pygame.image.frombuffer(
         buffer.m.userptr,
         (format.fmt.pix.width, format.fmt.pix.height),
         preview_settings['pixformat']
         )

I get TypeError: expected a character buffer object

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

晨曦÷微暖 2024-08-25 03:44:27

Looks like ctypes.string_at(address, size) is what you want. That'll give you a python string buffer with the contents of the memory at your pointer's address. This should be suitable to pass to Image.fromstring or pygame.image.frombuffer.

伴梦长久 2024-08-25 03:44:27

我对 ctypes 不太了解,但我正在做类似的事情(包装的 c++ 网络摄像头捕获,用 DirectPython 显示)。

就我而言,我只是在 python 中创建了一个缓冲区,如下所示:

bufferSize = imageWidth * imageHeight
buf = "\0" * bufferSize

将 buf 传递给您的图像捕获函数进行填充?

也许发布更完整的代码示例......

I don't know much about ctypes, but I am doing a similar thing (wrapped c++ webcam capture, displayed with DirectPython).

In my case I just made a buffer in python like this:

bufferSize = imageWidth * imageHeight
buf = "\0" * bufferSize

Pass buf to your image capture function for filling?

Maybe post a more complete code sample...

不再让梦枯萎 2024-08-25 03:44:27

您是否尝试过直接传递 buffer 作为第一个参数?如果这不起作用,并且您想使用 ctypes 创建可写字符缓冲区,create_string_buffer 是我知道的唯一方法(我不明白你从哪里获取 b_address.value em>)。

Have you tried passing buffer directly as the first arg? If that doesn't work and you want to make a writeable character buffer with ctypes, create_string_buffer is the only way I know (I don't understand where you're getting the b_address.value from).

薯片软お妹 2024-08-25 03:44:27

好吧,我所做的就是将 pygame 留给 Tkinter 和 PIL

现在,在相同的分配之后,我将其传递 buffer.m.userptr * 到 fromstring 方法从图像

首先我当然有以下内容:

import Image
import Tkinter

tk = Tkinter.Tk()
preview = ImageTk.PhotoImage(ps['pixformat'], (ps['width'], ps['height']))
label = Tkinter.Label(tk, text='Preview', image=preview, width=ps['width'], height=ps['height'])
label.pack()

现在预览:

im = Image.fromstring(ps['pixformat'], (format.fmt.pix.width, format.fmt.pix.height), '\0'*buffer.m.userptr)
preview.paste(im)
tk.update()

我做了@sipickles所说的,用'\0'来看看整个事情会成功的
它确实做到了:)

问题是如何正确地传递 userptr 以及其中的数据实际上是需要传递给预览的内容

我真的迷失在这里。有人知道 v4l2 吗?

OK, what I did was to leave pygame for Tkinter and PIL

now after the same allocation I pass buffer.m.userptr *to fromstring method from Image

first I have, of course, the following:

import Image
import Tkinter

tk = Tkinter.Tk()
preview = ImageTk.PhotoImage(ps['pixformat'], (ps['width'], ps['height']))
label = Tkinter.Label(tk, text='Preview', image=preview, width=ps['width'], height=ps['height'])
label.pack()

and now preview:

im = Image.fromstring(ps['pixformat'], (format.fmt.pix.width, format.fmt.pix.height), '\0'*buffer.m.userptr)
preview.paste(im)
tk.update()

I did what @sipickles said, with '\0' to see if the whole thing will work
And it did :)

the thing is how to pas that userptr correctly and is the data in it actually what it needs to be passed to the preview

I am really lost here. Someone knows v4l2?

终遇你 2024-08-25 03:44:27

好的。所以现在我通过自己设置 sizeimage 解决了 sizeimage 问题:

现在 frombuffer 显示的内容不是缓冲区中的帧。

from ctypes import *
from v4l2 import *
from Image import fromstring
from Tkinter import Tk, Label
from ImageTk import PhotoImage
from ctypes.util import find_library

libc = CDLL(find_library('c'))
posix_memalign = libc.posix_memalign
getpagesize = libc.getpagesize


device_name = '/dev/video0'
ps = preview_settings = {
    'width': 320,
    'height': 240,
    'pixformat': 'RGB',
    }
PIX_FMT = V4L2_PIX_FMT_RGB555


preview = Tk()
image = PhotoImage(ps['pixformat'], (ps['width'], ps['height']))
label = Label(preview, text='Preview', image=image, width=ps['width'], height=ps['height'])
label.pack()


capability = v4l2_capability()
size = v4l2_frmsizeenum()
format = v4l2_format()
request = v4l2_requestbuffers()
buffer = v4l2_buffer()
b_address = c_void_p()
type = V4L2_BUF_TYPE_VIDEO_CAPTURE

device = open(device_name, 'rw')

ioctl(device, VIDIOC_QUERYCAP, capability)

size.pixel_format = PIX_FMT 
size.index = 0

format.type = type
format.fmt.pix.pixelformat = PIX_FMT
format.fmt.pix.width = size.discrete.width
format.fmt.pix.height = size.discrete.height
format.fmt.pix.field = V4L2_FIELD_NONE

request.type = type
request.memory = V4L2_MEMORY_USERPTR
request.count = 1

format.fmt.pix.sizeimage = format.fmt.pix.width * format.fmt.pix.height * 4
buffer.length = format.fmt.pix.sizeimage

ioctl(device, VIDIOC_S_FMT, format)

posix_memalign(byref(b_address), getpagesize(), format.fmt.pix.sizeimage)

buffer.m.userptr = b_address.value

buffer.type = request.type
buffer.memory = request.memory

ioctl(device, VIDIOC_REQBUFS, request)

while True:

    ioctl(device, VIDIOC_QBUF, buffer)

    ioctl(device, VIDIOC_STREAMON, cast(type, c_void_p))

    ioctl(device, VIDIOC_DQBUF, buffer)

    **# What happens here? preview_data is wrong?**
    preview_data = string_at(buffer.m.userptr, buffer.length)

    im = frombuffer(ps['pixformat'], (ps['width'], ps['height']), preview_data)
    image.paste(im)
    preview.update()

Ok. so for now I fixed the sizeimage problem by setting the sizeimage myself:

Now frombuffer displays something that is not the frame from the buffer.

from ctypes import *
from v4l2 import *
from Image import fromstring
from Tkinter import Tk, Label
from ImageTk import PhotoImage
from ctypes.util import find_library

libc = CDLL(find_library('c'))
posix_memalign = libc.posix_memalign
getpagesize = libc.getpagesize


device_name = '/dev/video0'
ps = preview_settings = {
    'width': 320,
    'height': 240,
    'pixformat': 'RGB',
    }
PIX_FMT = V4L2_PIX_FMT_RGB555


preview = Tk()
image = PhotoImage(ps['pixformat'], (ps['width'], ps['height']))
label = Label(preview, text='Preview', image=image, width=ps['width'], height=ps['height'])
label.pack()


capability = v4l2_capability()
size = v4l2_frmsizeenum()
format = v4l2_format()
request = v4l2_requestbuffers()
buffer = v4l2_buffer()
b_address = c_void_p()
type = V4L2_BUF_TYPE_VIDEO_CAPTURE

device = open(device_name, 'rw')

ioctl(device, VIDIOC_QUERYCAP, capability)

size.pixel_format = PIX_FMT 
size.index = 0

format.type = type
format.fmt.pix.pixelformat = PIX_FMT
format.fmt.pix.width = size.discrete.width
format.fmt.pix.height = size.discrete.height
format.fmt.pix.field = V4L2_FIELD_NONE

request.type = type
request.memory = V4L2_MEMORY_USERPTR
request.count = 1

format.fmt.pix.sizeimage = format.fmt.pix.width * format.fmt.pix.height * 4
buffer.length = format.fmt.pix.sizeimage

ioctl(device, VIDIOC_S_FMT, format)

posix_memalign(byref(b_address), getpagesize(), format.fmt.pix.sizeimage)

buffer.m.userptr = b_address.value

buffer.type = request.type
buffer.memory = request.memory

ioctl(device, VIDIOC_REQBUFS, request)

while True:

    ioctl(device, VIDIOC_QBUF, buffer)

    ioctl(device, VIDIOC_STREAMON, cast(type, c_void_p))

    ioctl(device, VIDIOC_DQBUF, buffer)

    **# What happens here? preview_data is wrong?**
    preview_data = string_at(buffer.m.userptr, buffer.length)

    im = frombuffer(ps['pixformat'], (ps['width'], ps['height']), preview_data)
    image.paste(im)
    preview.update()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文