Ich arbeite an einem Video Capture-Skript für Python in Raspbian (Raspberry Pi 2) und ich habe Probleme mit der Python-Bindungen für v4l2, da ich keinen Erfolg auf Speicher- maping die Puffer.v4l2 Python - Streaming-Video - Mapping-Puffer
Was ich brauche:
- Capture-Video von einem HD-Webcam (wird später zwei von ihnen zugleich sein).
- Sie können das Video über WLAN streamen (Kompromiss zwischen Netzwerklast und Verarbeitungsgeschwindigkeit).
- In der Zukunft können Filter auf das Bild vor dem Streaming angewendet werden (nicht obligatorisch).
Was ich versucht habe:
- Verwenden OpenCV (cv2). Es ist sehr einfach zu bedienen, aber es fügt eine Menge Verarbeitungslast hinzu, da es die JPEG-Frames der Webcam in unformatierte Bilder umwandelt, und dann musste ich sie zurück in JPEG konvertieren, bevor sie über WLAN gesendet wurden.
- Lesen Sie direkt von '/ dev/video0'. Es wäre toll, da die Webcam die Frames bereits komprimiert sendet und ich sie einfach lesen und senden kann, aber es scheint, dass meine Kamera das nicht unterstützt.
- Verwenden Sie v4l2-Bindungen für Python. Dies ist jetzt die vielversprechendste Option, aber ich blieb stecken, als ich die Videopuffer zuordnen musste. Ich habe keine Möglichkeit gefunden, die "Memory Pointer/Mappings", die dieses Zeug zu benötigen scheint, zu überwinden.
Was ich gelesen habe:
- In diesem Handbuch: http://www.jayrambhia.com/blog/capture-v4l2/
- v4l2 Dokumentation (ein Teil davon).
- Dieses Beispiel in C: https://linuxtv.org/downloads/v4l-dvb-apis/capture-example.html
- Einige andere Beispiele in C/C++. Ich habe keine Beispiele gefunden, die v4l2-Bindungen direkt auf Python verwenden.
Meine Fragen:
- Gibt es einen besseren Weg, dies zu tun? oder wenn nicht ...
-
Könnte ich OpenCV sagen, das Bild nicht zu dekomprimieren? Es wäre schön, OpenCV zu verwenden, um zukünftige Erweiterungenanwenden zu können. Ich habe here gefunden, dass es nicht erlaubt ist. - Wie konnte ich den Mapping-Schritt in Python auflösen? (? Any Arbeitsbeispiel)
Hier ist mein (langsam) Arbeitsbeispiel mit 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
print 'Test finished. ' + str(t) + ' sec. per img.'
print str(fps) + ' fps reached'
video.release()
Und hier, was ich mit v4l2 gemacht habe:
FRAME_COUNT = 5
import v4l2
import fcntl
import mmap
def xioctl(fd, request, arg):
r = 0
cond = True
while cond == True:
r = fcntl.ioctl(fd, request, arg)
cond = r == -1
#cond = cond and errno == 4
return r
class buffer_struct:
start = 0
length = 0
# Open camera driver
fd = open('/dev/video1','r+b')
BUFTYPE = v4l2.V4L2_BUF_TYPE_VIDEO_CAPTURE
MEMTYPE = v4l2.V4L2_MEMORY_MMAP
# Set format
fmt = v4l2.v4l2_format()
fmt.type = BUFTYPE
fmt.fmt.pix.width = 640
fmt.fmt.pix.height = 480
fmt.fmt.pix.pixelformat = v4l2.V4L2_PIX_FMT_MJPEG
fmt.fmt.pix.field = v4l2.V4L2_FIELD_NONE # progressive
xioctl(fd, v4l2.VIDIOC_S_FMT, fmt)
buffer_size = fmt.fmt.pix.sizeimage
print "buffer_size = " + str(buffer_size)
# Request buffers
req = v4l2.v4l2_requestbuffers()
req.count = 4
req.type = BUFTYPE
req.memory = MEMTYPE
xioctl(fd, v4l2.VIDIOC_REQBUFS, req)
if req.count < 2:
print "req.count < 2"
quit()
n_buffers = req.count
buffers = list()
for i in range(req.count):
buffers.append(buffer_struct())
# Initialize buffers. What should I do here? This doesn't work at all.
# I've tried with USRPTR (pointers) but I know no way for that in Python.
for i in range(n_buffers):
buf = v4l2.v4l2_buffer()
buf.type = BUFTYPE
buf.memory = MEMTYPE
buf.index = i
xioctl(fd, v4l2.VIDIOC_QUERYBUF, buf)
buffers[i].length = buf.length
buffers[i].start = mmap.mmap(fd.fileno(), buf.length,
flags = mmap.PROT_READ,# | mmap.PROT_WRITE,
prot = mmap.MAP_SHARED,
offset = buf.m.offset)
Ich werde schätzen jede Hilfe oder Beratung. Danke vielmals!