Skip to content
This repository has been archived by the owner on May 6, 2021. It is now read-only.

Commit

Permalink
Add frame grabber using OpenCV
Browse files Browse the repository at this point in the history
  • Loading branch information
maximkulkin committed Jun 16, 2019
1 parent 8aff3cb commit d08d63e
Show file tree
Hide file tree
Showing 10 changed files with 319 additions and 0 deletions.
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ message(STATUS "ENABLE_TINKERFORGE = " ${ENABLE_TINKERFORGE})
option(ENABLE_V4L2 "Enable the V4L2 grabber" ON)
message(STATUS "ENABLE_V4L2 = " ${ENABLE_V4L2})

option(ENABLE_OPENCV "Enable the OpenCV grabber" ON)
message(STATUS "ENABLE_OPENCV = " ${ENABLE_OPENCV})

option(ENABLE_WS2812BPWM "Enable the WS2812b-PWM device" ${DEFAULT_WS2812BPWM} )
message(STATUS "ENABLE_WS2812BPWM = " ${ENABLE_WS2812BPWM})

Expand Down
3 changes: 3 additions & 0 deletions HyperionConfig.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
// Define to enable the osx grabber
#cmakedefine ENABLE_OSX

// Define to enable the opencv grabber
#cmakedefine ENABLE_OPENCV

// Define to enable the bonjour/zeroconf publishing
#cmakedefine ENABLE_ZEROCONF

Expand Down
27 changes: 27 additions & 0 deletions include/grabber/OpenCVGrabber.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#pragma once

// Qt includes
#include <QObject>

// util includes
#include <utils/Image.h>
#include <utils/ColorRgb.h>

// grabber includes
#include <opencv2/opencv.hpp>

/// Capture class for OpenCV
class OpenCVGrabber : public QObject
{
Q_OBJECT

public:
OpenCVGrabber(int input, int width, int height);
virtual ~OpenCVGrabber();

public slots:
void grabFrame(Image<ColorRgb> & image);

private:
cv::VideoCapture _capture;
};
65 changes: 65 additions & 0 deletions include/grabber/OpenCVWrapper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#pragma once

// Qt includes
#include <QTimer>

// Hyperion includes
#include <hyperion/Hyperion.h>
#include <hyperion/ImageProcessor.h>

// Grabber includes
#include <grabber/OpenCVGrabber.h>

class OpenCVWrapper : public QObject
{
Q_OBJECT

public:
OpenCVWrapper(int input,
int width,
int height,
int frequency,
int hyperionPriority,
Hyperion * hyperion);
virtual ~OpenCVWrapper();

public slots:
void start();

void stop();

signals:
void emitColors(int priority, const std::vector<ColorRgb> &ledColors, const int timeout_ms);
void emitImage(int priority, const Image<ColorRgb> & image, const int timeout_ms);

private slots:
void grabFrame();
void checkSources();

private:
/// The timeout of the led colors [ms]
const int _timeout_ms;

/// The priority of the led colors
const int _priority;

/// Grab frequency [Hz]
const int _frequency;

/// The OpenCV grabber
OpenCVGrabber _grabber;

/// The processor for transforming images to led colors
ImageProcessor * _processor;

/// The Hyperion instance
Hyperion * _hyperion;

/// The list with computed led colors
std::vector<ColorRgb> _ledColors;

/// Timer which tests if a higher priority source is active
QTimer _priority_check_timer;

QTimer _grab_timer;
};
4 changes: 4 additions & 0 deletions libsrc/grabber/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ if (ENABLE_V4L2)
add_subdirectory(v4l2)
endif (ENABLE_V4L2)

if (ENABLE_OPENCV)
add_subdirectory(opencv)
endif (ENABLE_OPENCV)

if (ENABLE_X11)
add_subdirectory(x11)
endif()
38 changes: 38 additions & 0 deletions libsrc/grabber/opencv/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
find_package(OpenCV REQUIRED)

# Define the current source locations
SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/grabber)
SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/opencv)

SET(OPENCV_GRABBER_QT_HEADERS
${CURRENT_HEADER_DIR}/OpenCVGrabber.h
${CURRENT_HEADER_DIR}/OpenCVWrapper.h
)

SET(OPENCV_GRABBER_SOURCES
${CURRENT_SOURCE_DIR}/OpenCVGrabber.cpp
${CURRENT_SOURCE_DIR}/OpenCVWrapper.cpp
)

if(ENABLE_QT5)
QT5_WRAP_CPP(OPENCV_GRABBER_HEADERS_MOC ${OPENCV_GRABBER_QT_HEADERS})
else()
QT4_WRAP_CPP(OPENCV_GRABBER_HEADERS_MOC ${OPENCV_GRABBER_QT_HEADERS})
endif()

add_library(opencv-grabber
${OPENCV_GRABBER_HEADERS}
${OPENCV_GRABBER_SOURCES}
${OPENCV_GRABBER_QT_HEADERS}
${OPENCV_GRABBER_HEADERS_MOC}
)

if(ENABLE_QT5)
qt5_use_modules(opencv-grabber Widgets)
endif(ENABLE_QT5)

target_link_libraries(opencv-grabber
hyperion
${QT_LIBRARIES}
${OpenCV_LIBS}
)
34 changes: 34 additions & 0 deletions libsrc/grabber/opencv/OpenCVGrabber.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <opencv2/opencv.hpp>

#include "grabber/OpenCVGrabber.h"


OpenCVGrabber::OpenCVGrabber(int input, int width, int height)
: _capture(input)
{
if (width && height) {
_capture.set(CV_CAP_PROP_FRAME_WIDTH, width);
_capture.set(CV_CAP_PROP_FRAME_HEIGHT, height);
}
}

OpenCVGrabber::~OpenCVGrabber()
{
}

void OpenCVGrabber::grabFrame(Image<ColorRgb> & image)
{
cv::Mat frame;
_capture >> frame;

const int width = frame.cols, height = frame.rows;

cv::Mat rgbFrame(width, height, CV_8UC3);
cvtColor(frame, rgbFrame, cv::COLOR_BGR2RGB);

image.resize(width, height);
memcpy(image.memptr(), rgbFrame.ptr(), width * height * 3);
}
102 changes: 102 additions & 0 deletions libsrc/grabber/opencv/OpenCVWrapper.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#include <QMetaType>

#include <grabber/OpenCVWrapper.h>

#include <hyperion/ImageProcessorFactory.h>

OpenCVWrapper::OpenCVWrapper(
int input,
int width,
int height,
int frequency,
int hyperionPriority,
Hyperion *hyperion) :
_timeout_ms(1000),
_priority(hyperionPriority),
_frequency(frequency),
_grabber(input, width, height),
_processor(ImageProcessorFactory::getInstance().newImageProcessor()),
_hyperion(hyperion),
_ledColors(hyperion->getLedCount(), ColorRgb{0,0,0}),
_priority_check_timer(),
_grab_timer()
{
// register the image type
qRegisterMetaType<Image<ColorRgb>>("Image<ColorRgb>");
qRegisterMetaType<std::vector<ColorRgb>>("std::vector<ColorRgb>");

// send color data to Hyperion using a queued connection to handle the data over to the main event loop
QObject::connect(
this, SIGNAL(emitColors(int,std::vector<ColorRgb>,int)),
_hyperion, SLOT(setColors(int,std::vector<ColorRgb>,int)),
Qt::QueuedConnection);

// setup the higher prio source checker
// this will disable the grabber when a source with hisher priority is active
_priority_check_timer.setInterval(500);
_priority_check_timer.setSingleShot(false);
QObject::connect(&_priority_check_timer, SIGNAL(timeout()), this, SLOT(checkSources()));
_priority_check_timer.start();

_grab_timer.setInterval(1000 / _frequency);
_grab_timer.setSingleShot(false);

QObject::connect(&_grab_timer, SIGNAL(timeout()), this, SLOT(grabFrame()));
}

OpenCVWrapper::~OpenCVWrapper()
{
delete _processor;
}

void OpenCVWrapper::start()
{
if (_grab_timer.isActive())
return;

_grab_timer.start();
std::cout << "OPENCVGRABBER INFO: started" << std::endl;
}

void OpenCVWrapper::stop()
{
if (!_grab_timer.isActive())
return;

_grab_timer.stop();
std::cout << "OPENCVGRABBER INFO: stopped" << std::endl;
}

void OpenCVWrapper::grabFrame()
{
Image<ColorRgb> image;

_grabber.grabFrame(image);

// process the new image
_processor->process(image, _ledColors);

// forward to other hyperions
emit emitImage(_priority, image, _timeout_ms);

// send colors to Hyperion
emit emitColors(_priority, _ledColors, _timeout_ms);
}

void OpenCVWrapper::checkSources()
{
QList<int> activePriorities = _hyperion->getActivePriorities();

for (int x : activePriorities)
{
if (x < _priority)
{
// found a higher priority source: grabber should be disabled
stop();
return;
}
}

// no higher priority source was found: grabber should be enabled
start();
}
4 changes: 4 additions & 0 deletions src/hyperiond/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ if (ENABLE_V4L2)
target_link_libraries(hyperiond v4l2-grabber)
endif ()

if (ENABLE_OPENCV)
target_link_libraries(hyperiond opencv-grabber)
endif ()

if (ENABLE_AMLOGIC)
target_link_libraries(hyperiond amlogic-grabber)
endif ()
Expand Down
39 changes: 39 additions & 0 deletions src/hyperiond/hyperiond.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@
#include <grabber/OsxWrapper.h>
#endif

#ifdef ENABLE_OPENCV
// OpenCV grabber
#include <grabber/OpenCVWrapper.h>
#endif

// XBMC Video checker includes
#include <xbmcvideochecker/XBMCVideoChecker.h>

Expand Down Expand Up @@ -428,6 +433,30 @@ void startGrabberOsx(const Json::Value &config, Hyperion &hyperion, ProtoServer*
}
#endif

#ifdef ENABLE_OPENCV
void startGrabberOpenCV(const Json::Value &config, Hyperion &hyperion, ProtoServer* &protoServer, OpenCVWrapper* &opencvGrabber)
{
// Construct and start the OpenCV grabber if the configuration is present
if (config.isMember("opencvgrabber"))
{
const Json::Value & grabberConfig = config["opencvgrabber"];
opencvGrabber = new OpenCVWrapper(
grabberConfig.get("input", 0).asUInt(),
grabberConfig.get("width", 0).asUInt(),
grabberConfig.get("height", 0).asUInt(),
grabberConfig.get("frequency_Hz", 10).asUInt(),
grabberConfig.get("priority", 900).asInt(),
&hyperion);

QObject::connect(opencvGrabber, SIGNAL(emitImage(int, const Image<ColorRgb>&, const int)), protoServer, SLOT(sendImageToProtoSlaves(int, const Image<ColorRgb>&, const int)) );

opencvGrabber->start();
std::cout << "INFO: OpenCV grabber created and started" << std::endl;
}
}
#endif


int main(int argc, char** argv)
{
std::cout
Expand Down Expand Up @@ -584,6 +613,16 @@ int main(int argc, char** argv)
#endif
#endif

#ifdef ENABLE_OPENCV
OpenCVWrapper * opencvGrabber = nullptr;
startGrabberOpenCV(config, hyperion, protoServer, opencvGrabber);
#else
if (config.isMember("opencvgrabber"))
{
std::cerr << "ERROR: The OpenCV grabber can not be instantiated, because it has been left out from the build" << std::endl;
}
#endif


// run the application
int rc = app.exec();
Expand Down

0 comments on commit d08d63e

Please sign in to comment.