mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2023-10-10 13:36:59 +02:00
Added config-schema of Hyperion as resource.
Added constructor to Hyperion using filename. Added config-filename as commandline parameter for hyperiond. Added implementation of blackborder detector. Added test for blackborder detector.
This commit is contained in:
parent
5010b9ce8e
commit
240b118ce9
@ -40,7 +40,6 @@ link_directories(${CMAKE_FIND_ROOT_PATH}/lib/arm-linux-gnueabihf)
|
||||
|
||||
configure_file(bin/install_hyperion.sh ${LIBRARY_OUTPUT_PATH} @ONLY)
|
||||
configure_file(config/hyperion.config.json ${LIBRARY_OUTPUT_PATH} @ONLY)
|
||||
configure_file(config/hyperion.schema.json ${LIBRARY_OUTPUT_PATH} @ONLY)
|
||||
|
||||
# Add the source/lib directories
|
||||
add_subdirectory(dependencies)
|
||||
|
@ -23,6 +23,9 @@ class Hyperion : public QObject
|
||||
public:
|
||||
static LedString createLedString(const Json::Value& ledsConfig);
|
||||
|
||||
static Json::Value loadConfig(const std::string& configFile);
|
||||
|
||||
Hyperion(const std::string& configFile);
|
||||
Hyperion(const Json::Value& jsonConfig);
|
||||
|
||||
~Hyperion();
|
||||
|
110
libsrc/hyperion/BlackBorderDetector.cpp
Normal file
110
libsrc/hyperion/BlackBorderDetector.cpp
Normal file
@ -0,0 +1,110 @@
|
||||
#include "BlackBorderDetector.h"
|
||||
|
||||
BlackBorderDetector::BlackBorderDetector()
|
||||
{
|
||||
}
|
||||
|
||||
BlackBorder BlackBorderDetector::process(const RgbImage& image)
|
||||
{
|
||||
int firstNonBlackPixelTop = -1;
|
||||
int firstNonBlackPixelLeft = -1;
|
||||
|
||||
for (unsigned x=0; x<image.width(); ++x)
|
||||
{
|
||||
const RgbColor& color = image(x, 0);
|
||||
if (!isBlack(color))
|
||||
{
|
||||
firstNonBlackPixelTop = x;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (unsigned y=0; y<image.height(); ++y)
|
||||
{
|
||||
const RgbColor& color = image(0, y);
|
||||
if (!isBlack(color))
|
||||
{
|
||||
firstNonBlackPixelLeft = y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
BlackBorder detectedBorder;
|
||||
detectedBorder.type = BlackBorder::unknown;
|
||||
|
||||
if (firstNonBlackPixelTop == 0 /*&& firstNonBlackPixelLeft == 0*/)
|
||||
{
|
||||
// No black border
|
||||
// C-?-?-? ...
|
||||
// ? +----
|
||||
// ? |
|
||||
// ? |
|
||||
// :
|
||||
|
||||
detectedBorder.type = BlackBorder::none;
|
||||
detectedBorder.size = -1;
|
||||
}
|
||||
else if (firstNonBlackPixelTop < 0)
|
||||
{
|
||||
if (firstNonBlackPixelLeft < 0 || firstNonBlackPixelLeft > (int)(image.height()/2) )
|
||||
{
|
||||
// We don't know
|
||||
// B-B-B-B ... B-B-B-B
|
||||
// B +---- ... ----- ?
|
||||
// B |
|
||||
// B |
|
||||
// :
|
||||
// B |
|
||||
// B |
|
||||
// B |
|
||||
// B ?
|
||||
|
||||
detectedBorder.type = BlackBorder::unknown;
|
||||
detectedBorder.size = -1;
|
||||
}
|
||||
else //(firstNonBlackPixelLeft > 0 && firstNonBlackPixelLeft < image.height()/2)
|
||||
{
|
||||
// Border at top of screen
|
||||
// B-B-B-B ... B-B-B-B
|
||||
// B +---- ... ----- ?
|
||||
// C |
|
||||
// ? |
|
||||
// :
|
||||
|
||||
detectedBorder.type = BlackBorder::horizontal;
|
||||
detectedBorder.size = firstNonBlackPixelLeft;
|
||||
}
|
||||
}
|
||||
else // (firstNonBlackPixelTop > 0)
|
||||
{
|
||||
if (firstNonBlackPixelTop < int(image.width()/2) && firstNonBlackPixelLeft < 0)
|
||||
{
|
||||
// Border at left of screen
|
||||
// B-B-C-? ...
|
||||
// B +---- ... ----- ?
|
||||
// B |
|
||||
// B |
|
||||
// :
|
||||
// B |
|
||||
// B |
|
||||
// B |
|
||||
// B ?
|
||||
|
||||
detectedBorder.type = BlackBorder::vertical;
|
||||
detectedBorder.size = firstNonBlackPixelTop;
|
||||
}
|
||||
else //(firstNonBlackPixelTop > int(mage.width()/2) || firstNonBlackPixelLeft > 0)
|
||||
{
|
||||
// No black border
|
||||
// B-B-C-? ...
|
||||
// B +----
|
||||
// C |
|
||||
// ? |
|
||||
// :
|
||||
|
||||
detectedBorder.type = BlackBorder::none;
|
||||
detectedBorder.size = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return detectedBorder;
|
||||
}
|
38
libsrc/hyperion/BlackBorderDetector.h
Normal file
38
libsrc/hyperion/BlackBorderDetector.h
Normal file
@ -0,0 +1,38 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
// Utils includes
|
||||
#include <utils/RgbImage.h>
|
||||
|
||||
struct BlackBorder
|
||||
{
|
||||
enum Type
|
||||
{
|
||||
none,
|
||||
horizontal,
|
||||
vertical,
|
||||
unknown
|
||||
};
|
||||
|
||||
Type type;
|
||||
int size;
|
||||
|
||||
};
|
||||
|
||||
class BlackBorderDetector
|
||||
{
|
||||
public:
|
||||
BlackBorderDetector();
|
||||
|
||||
BlackBorder process(const RgbImage& image);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
inline bool isBlack(const RgbColor& color)
|
||||
{
|
||||
return RgbColor::BLACK == color;
|
||||
}
|
||||
|
||||
|
||||
};
|
@ -18,6 +18,7 @@ SET(Hyperion_HEADERS
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceWs2801.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceTest.h
|
||||
${CURRENT_SOURCE_DIR}/ImageToLedsMap.h
|
||||
${CURRENT_SOURCE_DIR}/BlackBorderDetector.h
|
||||
${CURRENT_SOURCE_DIR}/ColorTransform.h
|
||||
)
|
||||
|
||||
@ -31,16 +32,24 @@ SET(Hyperion_SOURCES
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceWs2801.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceTest.cpp
|
||||
${CURRENT_SOURCE_DIR}/ImageToLedsMap.cpp
|
||||
${CURRENT_SOURCE_DIR}/BlackBorderDetector.cpp
|
||||
${CURRENT_SOURCE_DIR}/ColorTransform.cpp
|
||||
)
|
||||
|
||||
set(Hyperion_RESOURCES
|
||||
${CURRENT_SOURCE_DIR}/resource.qrc
|
||||
)
|
||||
|
||||
QT4_WRAP_CPP(Hyperion_HEADERS_MOC ${Hyperion_QT_HEADERS})
|
||||
|
||||
qt4_add_resources(Hyperion_RESOURCES_RCC ${Hyperion_RESOURCES} OPTIONS "-no-compress")
|
||||
|
||||
add_library(hyperion
|
||||
${Hyperion_HEADERS}
|
||||
${Hyperion_QT_HEADERS}
|
||||
${Hyperion_HEADERS_MOC}
|
||||
${Hyperion_SOURCES}
|
||||
${Hyperion_RESOURCES_RCC}
|
||||
)
|
||||
|
||||
target_link_libraries(hyperion
|
||||
|
@ -1,8 +1,7 @@
|
||||
|
||||
// Syslog include
|
||||
#include <syslog.h>
|
||||
|
||||
// QT includes
|
||||
#include <QDateTime>
|
||||
#include <QResource>
|
||||
|
||||
// JsonSchema include
|
||||
#include <utils/jsonschema/JsonFactory.h>
|
||||
@ -75,6 +74,33 @@ LedString Hyperion::createLedString(const Json::Value& ledsConfig)
|
||||
return ledString;
|
||||
}
|
||||
|
||||
Json::Value Hyperion::loadConfig(const std::string& configFile)
|
||||
{
|
||||
// read the json schema from the resource
|
||||
QResource schemaData(":/hyperion.schema.json");
|
||||
assert(schemaData.isValid());
|
||||
|
||||
Json::Reader jsonReader;
|
||||
Json::Value schemaJson;
|
||||
if (!jsonReader.parse(reinterpret_cast<const char *>(schemaData.data()), reinterpret_cast<const char *>(schemaData.data()) + schemaData.size(), schemaJson, false))
|
||||
{
|
||||
throw std::runtime_error("Schema error: " + jsonReader.getFormattedErrorMessages()) ;
|
||||
}
|
||||
JsonSchemaChecker schemaChecker;
|
||||
schemaChecker.setSchema(schemaJson);
|
||||
|
||||
const Json::Value jsonConfig = JsonFactory::readJson(configFile);
|
||||
schemaChecker.validate(jsonConfig);
|
||||
|
||||
return jsonConfig;
|
||||
}
|
||||
|
||||
Hyperion::Hyperion(const std::string& configFile) :
|
||||
Hyperion(loadConfig(configFile))
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
Hyperion::Hyperion(const Json::Value &jsonConfig) :
|
||||
mLedString(createLedString(jsonConfig["leds"])),
|
||||
mRedTransform( createColorTransform(jsonConfig["color"]["red"])),
|
||||
|
5
libsrc/hyperion/resource.qrc
Normal file
5
libsrc/hyperion/resource.qrc
Normal file
@ -0,0 +1,5 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>hyperion.schema.json</file>
|
||||
</qresource>
|
||||
</RCC>
|
@ -20,21 +20,17 @@ int main(int argc, char** argv)
|
||||
QCoreApplication app(argc, argv);
|
||||
std::cout << "QCoreApplication initialised" << std::endl;
|
||||
|
||||
// Select config and schema file
|
||||
//const std::string homeDir = getenv("RASPILIGHT_HOME");
|
||||
const std::string schemaFile = "hyperion.schema.json";
|
||||
const std::string configFile = "hyperion.config.json";
|
||||
|
||||
// Load configuration and check against the schema at the same time
|
||||
Json::Value config;
|
||||
if (JsonFactory::load(schemaFile, configFile, config) < 0)
|
||||
if (argc < 2)
|
||||
{
|
||||
std::cerr << "UNABLE TO LOAD CONFIGURATION" << std::endl;
|
||||
return -1;
|
||||
std::cout << "Missing required configuration file. Usage:" << std::endl;
|
||||
std::cout << "hyperiond [config.file]" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
std::cout << "Configuration loaded from: " << configFile << std::endl;
|
||||
|
||||
Hyperion hyperion(config);
|
||||
const std::string configFile = argv[2];
|
||||
std::cout << "Selected configuration file: " << configFile.c_str() << std::endl;
|
||||
|
||||
Hyperion hyperion(configFile);
|
||||
std::cout << "Hyperion created and initialised" << std::endl;
|
||||
|
||||
DispmanxWrapper dispmanx(64, 64, 10, &hyperion);
|
||||
|
@ -29,3 +29,8 @@ target_link_libraries(test_image2ledsmap
|
||||
hyperion)
|
||||
|
||||
add_subdirectory(dispmanx2png)
|
||||
|
||||
add_executable(test_blackborderdetector
|
||||
TestBlackBorderDetector.cpp)
|
||||
target_link_libraries(test_blackborderdetector
|
||||
hyperion)
|
||||
|
120
test/TestBlackBorderDetector.cpp
Normal file
120
test/TestBlackBorderDetector.cpp
Normal file
@ -0,0 +1,120 @@
|
||||
|
||||
// STL includes
|
||||
#include <random>
|
||||
|
||||
// Hyperion includes
|
||||
#include "hyperion/BlackBorderDetector.h"
|
||||
|
||||
RgbColor randomColor()
|
||||
{
|
||||
const uint8_t randomRedValue = uint8_t(rand() % (std::numeric_limits<uint8_t>::max() + 1));
|
||||
const uint8_t randomGreenValue = uint8_t(rand() % (std::numeric_limits<uint8_t>::max() + 1));
|
||||
const uint8_t randomBlueValue = uint8_t(rand() % (std::numeric_limits<uint8_t>::max() + 1));
|
||||
|
||||
return {randomRedValue, randomGreenValue, randomBlueValue};
|
||||
}
|
||||
|
||||
RgbImage createImage(unsigned width, unsigned height, unsigned topBorder, unsigned leftBorder)
|
||||
{
|
||||
RgbImage image(width, height);
|
||||
for (unsigned x=0; x<image.width(); ++x)
|
||||
{
|
||||
for (unsigned y=0; y<image.height(); ++y)
|
||||
{
|
||||
if (y < topBorder || x < leftBorder)
|
||||
{
|
||||
image(x,y) = RgbColor::BLACK;
|
||||
}
|
||||
else
|
||||
{
|
||||
image(x,y) = randomColor();
|
||||
}
|
||||
}
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
int TC_NO_BORDER()
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
BlackBorderDetector detector;
|
||||
|
||||
{
|
||||
RgbImage image = createImage(64, 64, 0, 0);
|
||||
BlackBorder border = detector.process(image);
|
||||
if (border.type != BlackBorder::none)
|
||||
{
|
||||
std::cerr << "Failed to correctly detect no border" << std::endl;
|
||||
result = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int TC_TOP_BORDER()
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
BlackBorderDetector detector;
|
||||
|
||||
{
|
||||
RgbImage image = createImage(64, 64, 12, 0);
|
||||
BlackBorder border = detector.process(image);
|
||||
if (border.type != BlackBorder::horizontal || border.size != 12)
|
||||
{
|
||||
std::cerr << "Failed to correctly detect horizontal border with correct size" << std::endl;
|
||||
result = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int TC_LEFT_BORDER()
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
BlackBorderDetector detector;
|
||||
|
||||
{
|
||||
RgbImage image = createImage(64, 64, 0, 12);
|
||||
BlackBorder border = detector.process(image);
|
||||
if (border.type != BlackBorder::vertical || border.size != 12)
|
||||
{
|
||||
std::cerr << "Failed to detected vertical border with correct size" << std::endl;
|
||||
result = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int TC_UNKNOWN_BORDER()
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
BlackBorderDetector detector;
|
||||
|
||||
{
|
||||
RgbImage image = createImage(64, 64, 12, 12);
|
||||
BlackBorder border = detector.process(image);
|
||||
if (border.type != BlackBorder::unknown)
|
||||
{
|
||||
std::cerr << "Failed to detected unknown border" << std::endl;
|
||||
result = -1;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
TC_NO_BORDER();
|
||||
TC_TOP_BORDER();
|
||||
TC_LEFT_BORDER();
|
||||
TC_UNKNOWN_BORDER();
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user