mirror of https://github.com/kivy/kivy.git
update Camera core class to use EventDispatcher
+ add on_load and on_frame event + uniform the camera selection to a index, starting from 0
This commit is contained in:
parent
23de1b3ffb
commit
1697726fa0
|
@ -0,0 +1,25 @@
|
|||
Camera:
|
||||
canvas:
|
||||
Color:
|
||||
rgb: (1, 1, 1)
|
||||
Rectangle:
|
||||
texture: self.texture
|
||||
size: (320, 240)
|
||||
Color:
|
||||
rgb: (.5, 0, 1)
|
||||
Rectangle:
|
||||
texture: self.texture
|
||||
pos: (320, 0)
|
||||
size: (320, 240)
|
||||
Color:
|
||||
rgb: (0, 1, 0)
|
||||
Rectangle:
|
||||
texture: self.texture
|
||||
pos: (320, 240)
|
||||
size: (320, 240)
|
||||
Color:
|
||||
rgb: (1, 0, 0)
|
||||
Rectangle:
|
||||
texture: self.texture
|
||||
pos: (0, 240)
|
||||
size: (320, 240)
|
|
@ -8,16 +8,19 @@ Core class for acquiring the camera, and convert the input to a
|
|||
|
||||
__all__ = ('CameraBase', 'Camera')
|
||||
|
||||
from kivy.event import EventDispatcher
|
||||
from kivy.logger import Logger
|
||||
from kivy.core import core_select_lib
|
||||
|
||||
class CameraBase(object):
|
||||
class CameraBase(EventDispatcher):
|
||||
'''Abstract Camera Widget class.
|
||||
|
||||
Concrete camera classes must implement initialization and
|
||||
frame capturing to buffer that can be uploaded to gpu.
|
||||
|
||||
:Parameters:
|
||||
`index`: int
|
||||
Source index of the camera.
|
||||
`size` : tuple (int, int)
|
||||
Size at which the image is drawn. If no size is specified,
|
||||
it defaults to resolution of the camera image.
|
||||
|
@ -26,23 +29,32 @@ class CameraBase(object):
|
|||
Used in the gstreamer pipeline by forcing the appsink caps
|
||||
to this resolution. If the camera doesnt support the resolution
|
||||
a negotiation error might be thrown.
|
||||
|
||||
:Events:
|
||||
`on_load`
|
||||
Fired when the camera is loaded, and the texture became available
|
||||
`on_frame`
|
||||
Fired each time the camera texture is updated
|
||||
'''
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
kwargs.setdefault('stopped', False)
|
||||
kwargs.setdefault('resolution', (640, 480))
|
||||
kwargs.setdefault('video_src', 0)
|
||||
kwargs.setdefault('index', 0)
|
||||
|
||||
self.stopped = kwargs.get('stopped')
|
||||
self._resolution = kwargs.get('resolution')
|
||||
self._video_src = kwargs.get('video_src')
|
||||
self._index = kwargs.get('index')
|
||||
self._buffer = None
|
||||
self._format = 'rgb'
|
||||
self._texture = None
|
||||
self.capture_device = None
|
||||
kwargs.setdefault('size', self._resolution)
|
||||
|
||||
super(CameraBase, self).__init__(**kwargs)
|
||||
super(CameraBase, self).__init__()
|
||||
|
||||
self.register_event_type('on_load')
|
||||
self.register_event_type('on_frame')
|
||||
|
||||
self.init_camera()
|
||||
|
||||
|
@ -58,14 +70,16 @@ class CameraBase(object):
|
|||
lambda self, x: self._set_resolution(x),
|
||||
doc='Resolution of camera capture (width, height)')
|
||||
|
||||
def _set_video_src(self, src):
|
||||
self._video_src = src
|
||||
def _set_index(self, x):
|
||||
if x == self._index:
|
||||
return
|
||||
self._index = x
|
||||
self.init_camera()
|
||||
def _get_video_src(self):
|
||||
return self._video_src
|
||||
video_src = property(lambda self: self._get_video_src(),
|
||||
lambda self, x: self._set_video_src(x),
|
||||
doc='Source of the camera')
|
||||
def _get_index(self):
|
||||
return self._x
|
||||
index = property(lambda self: self._get_index(),
|
||||
lambda self, x: self._set_index(x),
|
||||
doc='Source index of the camera')
|
||||
|
||||
def _get_texture(self):
|
||||
return self._texture
|
||||
|
@ -95,6 +109,13 @@ class CameraBase(object):
|
|||
return
|
||||
self._texture.blit_buffer(self._buffer, fmt=self._format)
|
||||
self._buffer = None
|
||||
self.dispatch('on_frame')
|
||||
|
||||
def on_frame(self):
|
||||
pass
|
||||
|
||||
def on_load(self):
|
||||
pass
|
||||
|
||||
# Load the appropriate provider
|
||||
Camera = core_select_lib('camera', (
|
||||
|
|
|
@ -4,7 +4,8 @@ GStreamer Camera: Implement CameraBase with GStreamer
|
|||
|
||||
__all__ = ('CameraGStreamer', )
|
||||
|
||||
import kivy
|
||||
|
||||
from kivy.graphics.texture import Texture
|
||||
from . import CameraBase
|
||||
|
||||
try:
|
||||
|
@ -33,11 +34,11 @@ class CameraGStreamer(CameraBase):
|
|||
'''
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
kwargs.setdefault('video_src', 'v4l2src')
|
||||
self._pipeline = None
|
||||
self._camerasink = None
|
||||
self._decodebin = None
|
||||
self._texturesize = None
|
||||
self._video_src = kwargs.get('video_src', 'v4l2src')
|
||||
super(CameraGStreamer, self).__init__(**kwargs)
|
||||
|
||||
def init_camera(self):
|
||||
|
@ -46,8 +47,16 @@ class CameraGStreamer(CameraBase):
|
|||
if self._pipeline:
|
||||
self._pipeline = None
|
||||
|
||||
video_src = self._video_src
|
||||
if video_src == 'v4l2src':
|
||||
video_src += ' device=/dev/video%d' % self._index
|
||||
elif video_src == 'dc1394src':
|
||||
video_src += ' camera-number=%d' % self._index
|
||||
|
||||
print video_src
|
||||
|
||||
GL_CAPS = 'video/x-raw-rgb,red_mask=(int)0xff0000,green_mask=(int)0x00ff00,blue_mask=(int)0x0000ff'
|
||||
self._pipeline = gst.parse_launch('%s ! decodebin name=decoder ! ffmpegcolorspace ! appsink name=camerasink emit-signals=True caps=%s' % (self.video_src, GL_CAPS) )
|
||||
self._pipeline = gst.parse_launch('%s ! decodebin name=decoder ! ffmpegcolorspace ! appsink name=camerasink emit-signals=True caps=%s' % (video_src, GL_CAPS) )
|
||||
self._camerasink = self._pipeline.get_by_name('camerasink')
|
||||
self._camerasink.connect('new-buffer', self._gst_new_buffer)
|
||||
self._decodebin = self._pipeline.get_by_name('decoder')
|
||||
|
@ -81,6 +90,7 @@ class CameraGStreamer(CameraBase):
|
|||
return
|
||||
self._copy_to_gpu()
|
||||
if self._texture is None and self._texturesize is not None:
|
||||
self._texture = kivy.Texture.create(
|
||||
self._texture = Texture.create(
|
||||
size=self._texturesize, fmt='rgb')
|
||||
self._texture.flip_vertical()
|
||||
self.dispatch('on_load')
|
||||
|
|
|
@ -20,23 +20,15 @@ except:
|
|||
|
||||
class CameraOpenCV(CameraBase):
|
||||
'''Implementation of CameraBase using OpenCV
|
||||
|
||||
:Parameters:
|
||||
`video_src` : int, default is 0
|
||||
Index of OpenCV camera to use (0 mean default camera)
|
||||
'''
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
# override the default source of video
|
||||
kwargs.setdefault('video_src', 0)
|
||||
|
||||
self._device = None
|
||||
|
||||
super(CameraOpenCV, self).__init__(**kwargs)
|
||||
|
||||
def init_camera(self):
|
||||
# create the device
|
||||
self._device = hg.cvCreateCameraCapture(self.video_src)
|
||||
self._device = hg.cvCreateCameraCapture(self._index)
|
||||
|
||||
try:
|
||||
# try first to set resolution
|
||||
|
@ -68,6 +60,7 @@ class CameraOpenCV(CameraBase):
|
|||
# create texture !
|
||||
self._texture = Texture.create(*self._resolution)
|
||||
self._texture.flip_vertical()
|
||||
self.dispatch('on_load')
|
||||
|
||||
if not self.stopped:
|
||||
self.start()
|
||||
|
|
|
@ -18,22 +18,16 @@ except:
|
|||
|
||||
class CameraVideoCapture(CameraBase):
|
||||
'''Implementation of CameraBase using VideoCapture
|
||||
|
||||
:Parameters:
|
||||
`video_src` : int, default is 0
|
||||
Index of VideoCapture camera to use (0 mean default camera)
|
||||
'''
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
# override the default source of video
|
||||
kwargs.setdefault('video_src', 0)
|
||||
self._device = None
|
||||
super(CameraVideoCapture, self).__init__(**kwargs)
|
||||
self._format = 'rgb'
|
||||
|
||||
def init_camera(self):
|
||||
# create the device
|
||||
self._device = Device(devnum=self.video_src, showVideoWindow=0)
|
||||
self._device = Device(devnum=self._index, showVideoWindow=0)
|
||||
# set resolution
|
||||
try:
|
||||
self._device.setResolution(self.resolution[0], self.resolution[1])
|
||||
|
@ -48,6 +42,7 @@ class CameraVideoCapture(CameraBase):
|
|||
# and create texture
|
||||
self._texture = kivy.Texture.create(
|
||||
size=self.size, fmt='bgr')
|
||||
self.dispatch('on_load')
|
||||
|
||||
# update buffer
|
||||
self._buffer = data
|
||||
|
|
Loading…
Reference in New Issue