Skip to main content
 首页 » 编程设计

python之python中的用户指针

2025年05月04日10itcoder

*我正在尝试显示使用 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: expected a character buffer object

请您参考如下方法:

看起来像ctypes.string_at(address, size)是你想要的。这将为您提供一个 python 字符串缓冲区,其中包含指针地址处的内存内容。这应该适合传递给 Image.fromstring 或 pygame.image.frombuffer。