2

*v4l を使用してキャプチャされた Web カメラからプレビューを表示しようとしています。

コードがどのように見えるかのアイデアは次のとおりです。

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: not enough image data


さて、私はインポートします

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 はもはや = なし 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 が表示されます

4

5 に答える 5

1

あなたが望むもののように見えctypes.string_at(address, size)ます。これにより、ポインターのアドレスにあるメモリの内容を含む python 文字列バッファーが得られます。Image.fromstringこれは、またはに渡すのに適しているはずpygame.image.frombufferです。

于 2010-01-18T22:49:46.653 に答える
0

OK、私がしたことは、Tkinter と PIL のために pygame を残すことでした

同じ割り当ての後、 buffer.m.userptr Image から *to 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を知っていますか?

于 2010-01-18T11:49:39.897 に答える
0

私は ctypes についてあまり知りませんが、同様のことを行っています (ラップされた C++ Web カメラ キャプチャ、DirectPython で表示)。

私の場合、次のようにPythonでバッファを作成しました:

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

塗りつぶしのために画像キャプチャ関数に buf を渡しますか?

たぶん、より完全なコードサンプルを投稿してください...

于 2010-01-15T13:24:45.107 に答える
0

buffer最初の引数として直接渡そうとしましたか? それが機能せず、 で書き込み可能な文字バッファーを作成したい場合はctypescreate_string_bufferが私が知っている唯一の方法です (どこb_address.value からを取得しているのかわかりません)。

于 2010-01-15T16:36:42.540 に答える
0

Ok。今のところ、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()
于 2010-01-26T12:53:35.857 に答える