howdy/src/pyv4l2_reader.py
Tim Welch 6a73634ac2 Adding support for v4l2 devices directly in python
v4l2l.py is included in src dir. The version you get from pip install does not work with python3 (at least not on my system), so I had to modify a bunch of the functions returning a list() of range() instead of the original range().
2018-12-23 12:08:18 -05:00

110 lines
2.9 KiB
Python

# Class that simulates the functionality of opencv so howdy can use v4l2 devices seamlessly
# Import required modules. lib4l-dev package is also required.
import v4l2
import fcntl
import numpy
import sys
from cv2 import cvtColor, COLOR_GRAY2BGR, CAP_PROP_FRAME_WIDTH, CAP_PROP_FRAME_HEIGHT
try:
from pyv4l2.frame import Frame
except ImportError:
print("Missing pyv4l2 module, please run:")
print(" pip3 install pyv4l2\n")
sys.exit(13)
class pyv4l2_reader:
""" This class was created to look as similar to the openCV features used in Howdy as possible for overall code cleanliness. """
# Init
def __init__(self, device_name, device_format):
self.device_name = device_name
self.device_format = device_format
self.height = 0
self.width = 0
self.probe()
self.frame = ""
def set(self, prop, setting):
""" Setter method for height and width """
if prop == CAP_PROP_FRAME_WIDTH:
self.width = setting
elif prop == CAP_PROP_FRAME_HEIGHT:
self.height = setting
def get(self, prop):
""" Getter method for height and width """
if prop == CAP_PROP_FRAME_WIDTH:
return self.width
elif prop == CAP_PROP_FRAME_HEIGHT:
return self.height
def probe(self):
""" Probe the video device to get height and width info """
vd = open(self.device_name, 'r')
fmt = v4l2.v4l2_format()
fmt.type = v4l2.V4L2_BUF_TYPE_VIDEO_CAPTURE
ret = fcntl.ioctl(vd, v4l2.VIDIOC_G_FMT, fmt)
vd.close()
if ret == 0:
height = fmt.fmt.pix.height
width = fmt.fmt.pix.width
else:
# Could not determine the resolution from ioctl call. Reverting to slower ffmpeg.probe() method
import ffmpeg
probe = ffmpeg.probe(self.device_name)
height = int(probe['streams'][0]['height'])
width = int(probe['streams'][0]['width'])
if self.get(CAP_PROP_FRAME_HEIGHT) == 0:
self.set(CAP_PROP_FRAME_HEIGHT, int(height))
if self.get(CAP_PROP_FRAME_WIDTH) == 0:
self.set(CAP_PROP_FRAME_WIDTH, int(width))
def record(self):
""" Start recording """
self.frame = Frame(self.device_name)
def grab(self):
""" Read a sigle frame from the IR camera. """
self.read()
def read(self):
""" Read a sigle frame from the IR camera. """
if not self.frame:
self.record()
# Grab a raw frame from the camera
frame_data = self.frame.get_frame()
# Convert the raw frame_date to a numpy array
img = (
numpy
.frombuffer(frame_data, numpy.uint8)
)
# Convert the numpy array to a proper grayscale image array
img_bgr = cvtColor(img, COLOR_GRAY2BGR)
# Convert the grayscale image array into a proper RGB style numpy array
img2 = (
numpy
.frombuffer(img_bgr, numpy.uint8)
.reshape([352, 352, 3])
)
# Return a single frame of video
return 0, img2
def release(self):
""" Empty our array. If we had a hold on the camera, we would give it back here. """
self.video = ()
self.num_frames_read = 0
if self.frame:
self.frame.close()