|
From: Yoda-JM <yo...@us...> - 2010-11-26 13:08:12
|
Module: performous Branch: kinect Commit: 91bdeeaf09a1f6cc5882e4b423590db063960897 Author: Vincent Le Ligeour <yo...@us...> Date: Fri Nov 26 14:05:41 2010 +0100 Added some dummy Kinect to start with --- cmake/Modules/FindLibfreenect.cmake | 28 +++++++ game/CMakeLists.txt | 15 ++++ game/kinect.cc | 148 +++++++++++++++++++++++++++++++++++ 3 files changed, 191 insertions(+), 0 deletions(-) diff --git a/cmake/Modules/FindLibfreenect.cmake b/cmake/Modules/FindLibfreenect.cmake new file mode 100644 index 0000000..341bac8 --- /dev/null +++ b/cmake/Modules/FindLibfreenect.cmake @@ -0,0 +1,28 @@ +# - Try to find Libfreenect +# Once done, this will define +# +# Libfreenect_FOUND - system has Jpeg +# Libfreenect_INCLUDE_DIRS - the Jpeg include directories +# Libfreenect_LIBRARIES - link these to use Jpeg +# +# See documentation on how to write CMake scripts at +# http://www.cmake.org/Wiki/CMake:How_To_Find_Libraries + +include(LibFindMacros) + +libfind_pkg_check_modules(Libfreenect_PKGCONF libfreenect) + +find_path(Libfreenect_INCLUDE_DIR + NAMES libfreenect.hpp + PATHS ${Libfreenect_PKGCONF_INCLUDE_DIRS} +) + +find_library(Libfreenect_LIBRARY + NAMES freenect + PATHS ${Libfreenect_PKGCONF_LIBRARY_DIRS} +) + +set(Libfreenect_PROCESS_INCLUDES Libfreenect_INCLUDE_DIR) +set(Libfreenect_PROCESS_LIBS Libfreenect_LIBRARY) +libfind_process(Libfreenect) + diff --git a/game/CMakeLists.txt b/game/CMakeLists.txt index ccf5faf..e374d94 100644 --- a/game/CMakeLists.txt +++ b/game/CMakeLists.txt @@ -116,6 +116,21 @@ else() message(STATUS "Webcam support: Disabled (explicitly disabled)") endif() +if(NOT NO_KINECT) + find_package(OpenCV) + find_package(Libfreenect) + if(OpenCV_FOUND AND Libfreenect_FOUND) + include_directories(${OpenCV_INCLUDE_DIRS} ${Libfreenect_INCLUDE_DIRS}) + list(APPEND LIBS ${OpenCV_LIBRARIES} ${Libfreenect_LIBRARIES}) + add_definitions("-DUSE_KINEeCT") + message(STATUS "Kinect support: Enabled") + else() + message(STATUS "Kinect support: Disabled (libcv/libhighgui/libfreenect not found)") + endif() +else() + message(STATUS "Kinect support: Disabled (explicitly disabled)") +endif() + # Set default compile flags for GCC if(CMAKE_COMPILER_IS_GNUCXX) diff --git a/game/kinect.cc b/game/kinect.cc new file mode 100644 index 0000000..a3ac786 --- /dev/null +++ b/game/kinect.cc @@ -0,0 +1,148 @@ +#include "surface.hh" + +#include <iostream> +#include <vector> +#include <boost/thread/mutex.hpp> + +#ifdef USE_KINECT +#include <libfreenect.hpp> +#include <cv.h> +#include <highgui.h> + +class MyFreenectDevice : public Freenect::FreenectDevice { + public: + MyFreenectDevice(freenect_context *_ctx, int _index) : Freenect::FreenectDevice(_ctx, _index), m_buffer_depth(FREENECT_FRAME_PIX), m_new_depth_frame(false) { + } + void RGBCallback(freenect_pixel *, uint32_t) { + //std::cout << "RGB callback" << std::endl; + }; + void DepthCallback(void *_depth, uint32_t) { + //std::cout << "Depth callback" << std::endl; + boost::mutex::scoped_lock l(m_depth_mutex); + freenect_depth *depth = static_cast<freenect_depth *>(_depth); + std::copy(depth, depth+FREENECT_FRAME_PIX, m_buffer_depth.begin()); + m_new_depth_frame = true; + } + + bool getDepth(IplImage* depth_image) { + boost::mutex::scoped_lock l(m_depth_mutex); + if(m_new_depth_frame) { + m_new_depth_frame = false; + for(unsigned int i = 0 ; i < FREENECT_FRAME_PIX ; ++i) { + if( m_buffer_depth[i] >= 0x07ff) { + depth_image->imageData[i] = 0xff; + } else { + depth_image->imageData[i] = (2048 * 256) / (2048 - m_buffer_depth[i]); + } + } + return true; + } else { + return false; + } + } + private: + std::vector<boost::uint16_t> m_buffer_depth; + boost::mutex m_depth_mutex; + bool m_new_depth_frame; +}; + +class BoundingBoxes { + public: + BoundingBoxes(boost::uint8_t _near = 0, boost::uint8_t _far = 255) : m_grey_image(NULL), m_near(_near), m_far(_far) { + m_storage = cvCreateMemStorage(0); + } + ~BoundingBoxes() { + if(m_grey_image == NULL) + cvReleaseImage(&m_grey_image); + cvReleaseMemStorage(&m_storage); + } + void process(IplImage* depth_image, std::vector<CvRect> &boxes) { + CvSeq* seq; + boxes.clear(); + cvClearMemStorage(m_storage); + if(m_grey_image == NULL) + m_grey_image = cvCreateImage(cvGetSize(depth_image), IPL_DEPTH_8U, 1); + //cvSaveImage("in.png", depth_image); + cvThreshold(depth_image, m_grey_image, m_far, 0, CV_THRESH_TOZERO_INV); + cvThreshold(m_grey_image, m_grey_image, m_near, 255, CV_THRESH_BINARY); + //cvSaveImage("out.png", m_grey_image); + cvFindContours(m_grey_image, m_storage, &seq); + for(; seq; seq = seq->h_next) { + CvRect boundbox = cvBoundingRect(seq); + if(boundbox.width >= MIN_WIDTH && boundbox.height >= MIN_HEIGHT) { + boxes.push_back(boundbox); + } + } + } + void setNear(boost::uint8_t _near) {m_near = _near;} + void setFar(boost::uint8_t _far) {m_far = _far;} + private: + CvMemStorage* m_storage; + IplImage* m_grey_image; + boost::uint8_t m_near; + boost::uint8_t m_far; + static const int MIN_WIDTH = 50; + static const int MIN_HEIGHT = 50; +}; + + +class Kinect { + public: + Kinect() : m_freenect(), m_device(m_freenect.createDevice(0)), m_boxes(90, 130), m_new_image(false) { + m_device.startDepth(); + m_depth_image = cvCreateImage(cvSize(FREENECT_FRAME_W, FREENECT_FRAME_H), IPL_DEPTH_8U, 1); + m_print_image = cvCreateImage(cvSize(FREENECT_FRAME_W, FREENECT_FRAME_H), IPL_DEPTH_8U, 3); + } + ~Kinect() { + cvReleaseImage(&m_depth_image); + cvReleaseImage(&m_print_image); + m_device.stopDepth(); + m_freenect.deleteDevice(0); + } + void process() { + std::vector<CvRect> boxes; + m_device.getDepth(m_depth_image); + cvFlip(m_depth_image, NULL, 1); + m_boxes.process(m_depth_image, boxes); + cvConvertImage(m_depth_image, m_print_image); + for(std::vector<CvRect>::const_iterator it = boxes.begin(); it != boxes.end() ; ++it) { + std::cout << "Rectangle: " << (*it).x << "," << (*it).y << " (" << (*it).width << "x" << (*it).height << ")" << std::endl; + // draw the cross + cvLine(m_print_image, cvPoint((*it).x, (*it).y), cvPoint((*it).x+(*it).width, (*it).y+(*it).height), cvScalar(0,0,255)); + cvLine(m_print_image, cvPoint((*it).x+(*it).width, (*it).y), cvPoint((*it).x, (*it).y+(*it).height), cvScalar(0,0,255)); + // draw the box + cvRectangleR(m_print_image, *it, cvScalar(255,0,0)); + //return 0; + } + m_new_image = true; + // generate drumkit events + generateEvents(); + } + void render() { + if(m_new_image) { + m_surface.load(m_print_image->width, m_print_image->height, pix::BGR, (const unsigned char*)m_print_image->imageData); + m_new_image = false; + } + m_surface.draw(); + } + private: + void generateEvents() { + } + Freenect::Freenect<MyFreenectDevice> m_freenect; + MyFreenectDevice& m_device; + BoundingBoxes m_boxes; + IplImage* m_depth_image; + IplImage* m_print_image; + bool m_new_image; + Surface m_surface; + public: + static bool enabled() { + #ifdef USE_KINECT + return true; + #else + return false; + #endif + } +}; + +#endif |