Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added queueing of produced frame data #18

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions PyKinect2.pyproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<SchemaVersion>2.0</SchemaVersion>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

<ProjectGuid>862156b9-96a7-4f85-bb66-b7ec70418cf7</ProjectGuid>
<ProjectHome>.</ProjectHome>
<StartupFile>pykinect2/PyKinectBodyGame.py</StartupFile>
<StartupFile>examples/PyKinectBodyGame.py</StartupFile>
<SearchPath>
</SearchPath>
<WorkingDirectory>.</WorkingDirectory>
Expand All @@ -23,7 +23,7 @@
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
</PropertyGroup>
<ItemGroup>
<Compile Include="pykinect2/examples/PyKinectBodyGame.py" />
<Compile Include="examples/PyKinectBodyGame.py" />
<Compile Include="pykinect2/PyKinectRuntime.py" />
<Compile Include="pykinect2/PyKinectV2.py" />
</ItemGroup>
Expand Down
8 changes: 2 additions & 6 deletions examples/PyKinectBodyGame.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,14 +132,10 @@ def run(self):

# --- Getting frames and drawing
# --- Woohoo! We've got a color frame! Let's fill out back buffer surface with frame's data
if self._kinect.has_new_color_frame():
frame = self._kinect.get_last_color_frame()
self.draw_color_frame(frame, self._frame_surface)
frame = None
self.draw_color_frame(self._kinect.get_last_color_frame(), self._frame_surface)

# --- Cool! We have a body frame, so can get skeletons
if self._kinect.has_new_body_frame():
self._bodies = self._kinect.get_last_body_frame()
self._bodies = self._kinect.get_last_body_frame()

# --- draw skeletons to _frame_surface
if self._bodies is not None:
Expand Down
173 changes: 45 additions & 128 deletions pykinect2/PyKinectRuntime.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,21 @@
import sys
import numpy
import time

import importlib

if sys.hexversion >= 0x03000000:
import _thread as thread
from queue import Queue, Empty
else:
import thread
import thread
from Queue import Queue, Empty

KINECT_MAX_BODY_COUNT = 6


class PyKinectRuntime(object):
"""manages Kinect objects and simplifying access to them"""
def __init__(self, frame_source_types):
def __init__(self, frame_source_types, max_frames_stored=2):
# recipe to get address of surface: http://archives.seul.org/pygame/users/Apr-2008/msg00218.html
is_64bits = sys.maxsize > 2**32
if not is_64bits:
Expand Down Expand Up @@ -52,14 +54,6 @@ def __init__(self, frame_source_types):
self._long_exposure_infrared_frame_arrived_event = 0
self._audio_frame_arrived_event = 0

self._color_frame_lock = thread.allocate()
self._depth_frame_lock = thread.allocate()
self._body_frame_lock = thread.allocate()
self._body_index_frame_lock = thread.allocate()
self._infrared_frame_lock = thread.allocate()
self._long_exposure_infrared_frame_lock = thread.allocate()
self._audio_frame_lock = thread.allocate()

#initialize sensor
self._sensor = ctypes.POINTER(PyKinectV2.IKinectSensor)()
hres = ctypes.windll.kinect20.GetDefaultKinectSensor(ctypes.byref(self._sensor))
Expand Down Expand Up @@ -137,28 +131,18 @@ def __init__(self, frame_source_types):
self._body_frame_data = ctypes.cast(self._body_frame_data_type(), ctypes.POINTER(ctypes.POINTER(IBody)))
self._body_frame_reader = self._body_source.OpenReader()
self._body_frame_arrived_event = self._body_frame_reader.SubscribeFrameArrived()
self._body_frame_bodies = None
self._handles[self._waitHandleCount] = self._body_frame_arrived_event
self._waitHandleCount += 1

thread.start_new_thread(self.kinect_frame_thread, ())

self._last_color_frame = None
self._last_depth_frame = None
self._last_body_frame = None
self._last_body_index_frame = None
self._last_infrared_frame = None
self._last_long_exposure_infrared_frame = None
self._last_audio_frame = None

start_clock = time.clock()
self._last_color_frame_access = self._last_color_frame_time = start_clock
self._last_body_frame_access = self._last_body_frame_time = start_clock
self._last_body_index_frame_access = self._last_body_index_frame_time = start_clock
self._last_depth_frame_access = self._last_depth_frame_time = start_clock
self._last_infrared_frame_access = self._last_infrared_frame_time = start_clock
self._last_long_exposure_infrared_frame_access = self._last_long_exposure_infrared_frame_time = start_clock
self._last_audio_frame_access = self._last_audio_frame_time = start_clock
self._color_frame_queue = Queue(maxsize=max_frames_stored)
self._depth_frame_queue = Queue(maxsize=max_frames_stored)
self._body_frame_queue = Queue(maxsize=max_frames_stored)
self._body_index_frame_queue = Queue(maxsize=max_frames_stored)
self._infrared_frame_queue = Queue(maxsize=max_frames_stored)
self._long_exposure_infrared_frame_queue = Queue(maxsize=max_frames_stored)
self._audio_frame_queue = Queue(maxsize=max_frames_stored)

def close(self):
if self._sensor is not None:
Expand Down Expand Up @@ -198,75 +182,33 @@ def surface_as_array(self, surface_buffer_interface):
bytes.object = surface_buffer_interface
return bytes

def has_new_color_frame(self):
has = (self._last_color_frame_time > self._last_color_frame_access)
return has

def has_new_depth_frame(self):
has = (self._last_depth_frame_time > self._last_depth_frame_access)
return has

def has_new_body_frame(self):
has = (self._last_body_frame_time > self._last_body_frame_access)
return has

def has_new_body_index_frame(self):
has = (self._last_body_index_frame_time > self._last_body_index_frame_access)
return has

def has_new_infrared_frame(self):
has = (self._last_infrared_frame_time > self._last_infrared_frame_access)
return has

def has_new_long_exposure_infrared_frame(self):
has = (self._last_long_exposure_infrared_frame_time > self._last_long_exposure_infrared_frame_access)
return has

def has_new_audio_frame(self):
has = (self._last_audio_frame_time > self._last_audio_frame_access)
return has


def get_last_color_frame(self):
with self._color_frame_lock:
if self._color_frame_data is not None:
data = numpy.copy(numpy.ctypeslib.as_array(self._color_frame_data, shape=(self._color_frame_data_capacity.value,)))
_last_color_frame_access = time.clock()
return data
else:
return None

def get_last_depth_frame(self):
with self._depth_frame_lock:
if self._depth_frame_data is not None:
data = numpy.copy(numpy.ctypeslib.as_array(self._depth_frame_data, shape=(self._depth_frame_data_capacity.value,)))
_last_color_frame_access = time.clock()
return data
else:
return None

def get_last_body_index_frame(self):
with self._body_index_frame_lock:
if self._body_index_frame_data is not None:
data = numpy.copy(numpy.ctypeslib.as_array(self._body_index_frame_data, shape=(self._body_index_frame_data_capacity.value,)))
_last_color_frame_access = time.clock()
return data
else:
return None

def get_last_body_frame(self):
with self._body_frame_lock:
if self._body_frame_bodies is not None:
_last_body_frame_access = time.clock()
return self._body_frame_bodies.copy()
else:
return None
def get_last_color_frame(self, blocking=True):
try:
return self._color_frame_queue.get(block=blocking)
except Empty:
return None

def get_last_depth_frame(self, blocking=True):
try:
return self._depth_frame_queue.get(block=blocking)
except Empty:
return None

def get_last_body_frame(self, blocking=True):
try:
return self._body_frame_queue.get(block=blocking)
except Empty:
return None

def get_last_body_index_frame(self, blocking=True):
try:
return self._body_index_frame_queue.get(block=blocking)
except Empty:
return None

def body_joint_to_color_space(self, joint):
return self._mapper.MapCameraPointToColorSpace(joint.Position)


def body_joints_to_color_space(self, joints):
joint_points = numpy.ndarray((PyKinectV2.JointType_Count), dtype=numpy.object)

Expand All @@ -275,7 +217,6 @@ def body_joints_to_color_space(self, joints):

return joint_points


def kinect_frame_thread(self):
while 1:
wait = ctypes.windll.kernel32.WaitForMultipleObjects(self._waitHandleCount, self._handles, False, PyKinectV2._INFINITE)
Expand All @@ -300,42 +241,31 @@ def kinect_frame_thread(self):
else:
break


def handle_color_arrived(self, handle_index):
colorFrameEventData = self._color_frame_reader.GetFrameArrivedEventData(self._handles[handle_index])
colorFrameRef = colorFrameEventData.FrameReference
try:
colorFrame = colorFrameRef.AcquireFrame()
try:
with self._color_frame_lock:
colorFrame.CopyConvertedFrameDataToArray(self._color_frame_data_capacity, self._color_frame_data, PyKinectV2.ColorImageFormat_Bgra)
self._last_color_frame_time = time.clock()
except:
colorFrame.CopyConvertedFrameDataToArray(self._color_frame_data_capacity, self._color_frame_data, PyKinectV2.ColorImageFormat_Bgra)
self._color_frame_queue.put(numpy.copy(numpy.ctypeslib.as_array(self._color_frame_data, shape=(self._color_frame_data_capacity.value,))))
except:
pass
colorFrame = None
except:
pass
colorFrameRef = None
colorFrameEventData = None


def handle_depth_arrived(self, handle_index):
depthFrameEventData = self._depth_frame_reader.GetFrameArrivedEventData(self._handles[handle_index])
depthFrameRef = depthFrameEventData.FrameReference
try:
depthFrame = depthFrameRef.AcquireFrame()
try:
with self._depth_frame_lock:
depthFrame.CopyFrameDataToArray(self._depth_frame_data_capacity, self._depth_frame_data)
self._last_depth_frame_time = time.clock()
depthFrame.CopyFrameDataToArray(self._depth_frame_data_capacity, self._depth_frame_data)
self._depth_frame_queue.put(numpy.copy(numpy.ctypeslib.as_array(self._depth_frame_data, shape=(self._depth_frame_data_capacity.value,))))
except:
pass
depthFrame = None
except:
pass
depthFrameRef = None
depthFrameEventData = None


def handle_body_arrived(self, handle_index):
bodyFrameEventData = self._body_frame_reader.GetFrameArrivedEventData(self._handles[handle_index])
Expand All @@ -344,41 +274,30 @@ def handle_body_arrived(self, handle_index):
bodyFrame = bofyFrameRef.AcquireFrame()

try:
with self._body_frame_lock:
bodyFrame.GetAndRefreshBodyData(self._body_frame_data_capacity, self._body_frame_data)
self._body_frame_bodies = KinectBodyFrameData(bodyFrame, self._body_frame_data, self.max_body_count)
self._last_body_frame_time = time.clock()
bodyFrame.GetAndRefreshBodyData(self._body_frame_data_capacity, self._body_frame_data)
self._body_frame_queue.put(KinectBodyFrameData(bodyFrame, self._body_frame_data, self.max_body_count).copy())

# need these 2 lines as a workaround for handling IBody referencing exception
self._body_frame_data = None
self._body_frame_data = ctypes.cast(self._body_frame_data_type(), ctypes.POINTER(ctypes.POINTER(IBody)))

except:
pass

bodyFrame = None
except:
pass
bofyFrameRef = None
bodyFrameEventData = None


def handle_body_index_arrived(self, handle_index):
bodyIndexFrameEventData = self._body_index_frame_reader.GetFrameArrivedEventData(self._handles[handle_index])
bodyIndexFrameRef = bodyIndexFrameEventData.FrameReference
try:
bodyIndexFrame = bodyIndexFrameRef.AcquireFrame()
try:
with self._body_index_frame_lock:
bodyIndexFrame.CopyFrameDataToArray(self._body_index_frame_data_capacity, self._body_index_frame_data)
self._last_body_index_frame_time = time.clock()
except:
bodyIndexFrame.CopyFrameDataToArray(self._body_index_frame_data_capacity, self._body_index_frame_data)
self._body_index_frame_queue.put(numpy.copy(numpy.ctypeslib.as_array(self._body_index_frame_data, shape=(self._body_index_frame_data_capacity.value,))))
except:
pass
bodyIndexFrame = None
except:
pass
bodyIndexFrame = None
bodyIndexFrameEventData = None

def handle_infrared_arrived(self, handle_index):
pass
Expand All @@ -390,7 +309,6 @@ def handle_audio_arrived(self, handle_index):
pass



class KinectBody(object):
def __init__(self, body = None):
self.is_restricted = False
Expand Down Expand Up @@ -443,5 +361,4 @@ def copy(self):
res.floor_clip_plane = self.floor_clip_plane
res.bodies = numpy.copy(self.bodies)
return res



6 changes: 4 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from setuptools import setup, find_packages
from distutils.core import Extension

setup(name='pykinect2',
version='1.0',
Expand All @@ -8,5 +9,6 @@
url='https://github.com/Kinect/PyKinect2/',
packages=find_packages(),
install_requires=['numpy>=1.9.2',
'comtypes>=1.1.1']
)
'comtypes>=1.1.1'],
ext_modules=[Extension('windummy', sources=['src/win_dummy.c'])]
)
7 changes: 7 additions & 0 deletions src/win_dummy.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#include <Windows.h>
#include <Python.h>

PyMODINIT_FUNC PyInit_windummy(void)
{
return 0;
}