mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2023-10-10 13:36:59 +02:00
bugfix, config enhancement and 3 detection modes
Former-commit-id: edfc3e7ccf7b7d727e73a8563acb521045026d5b
This commit is contained in:
parent
6b052081f7
commit
2b703de669
@ -355,10 +355,21 @@
|
||||
/// The black border configuration, contains the following items:
|
||||
/// * enable : true if the detector should be activated
|
||||
/// * threshold : Value below which a pixel is regarded as black (value between 0.0 and 1.0)
|
||||
"blackborderdetector" :
|
||||
/// * unknownFrameCnt : Number of frames without any detection before the border is set to 0 (default 600) - optional
|
||||
/// * borderFrameCnt : Number of frames before a consistent detected border gets set (default 50) - optional
|
||||
/// * maxInconsistentCnt : Number of inconsistent frames that are ignored before a new border gets a chance to proof consistency - optional
|
||||
/// * blurRemoveCnt : Number of pixels that get removed from the detected border to cut away blur (default 1) - optional
|
||||
/// * mode : Border detection mode (values "default","classic","osd") - optional
|
||||
|
||||
"blackborderdetector" :
|
||||
{
|
||||
"enable" : true,
|
||||
"threshold" : 0.01
|
||||
"threshold" : 0.01,
|
||||
"unknownFrameCnt": 600,
|
||||
"borderFrameCnt" : 50,
|
||||
"maxInconsistentCnt" : 10,
|
||||
"blurRemoveCnt": 1,
|
||||
"mode" : "default"
|
||||
},
|
||||
|
||||
/// The configuration of the effect engine, contains the following items:
|
||||
|
@ -49,7 +49,7 @@ namespace hyperion
|
||||
/// Constructs a black-border detector
|
||||
/// @param[in] blackborderThreshold The threshold which the blackborder detector should use
|
||||
///
|
||||
BlackBorderDetector(uint8_t blackborderThreshold);
|
||||
BlackBorderDetector(double threshold);
|
||||
|
||||
///
|
||||
/// Performs the actual black-border detection on the given image
|
||||
@ -58,13 +58,17 @@ namespace hyperion
|
||||
///
|
||||
/// @return The detected (or not detected) black border info
|
||||
///
|
||||
|
||||
uint8_t calculateThreshold(double blackborderThreshold);
|
||||
|
||||
///
|
||||
/// default detection mode (3lines 4side detection)
|
||||
template <typename Pixel_T>
|
||||
BlackBorder process(const Image<Pixel_T> & image)
|
||||
{
|
||||
|
||||
// test center and 33%, 66% of width/heigth
|
||||
// 33 and 66 will check left and top
|
||||
// center ill check right and bottom sids
|
||||
// center will check right and bottom sids
|
||||
int width = image.width();
|
||||
int height = image.height();
|
||||
int width33percent = width / 3;
|
||||
@ -79,9 +83,9 @@ namespace hyperion
|
||||
int firstNonBlackYPixelIndex = -1;
|
||||
|
||||
// find first X pixel of the image
|
||||
for (int x = 0; x < width; ++x)
|
||||
for (int x = 0; x < width33percent; ++x)
|
||||
{
|
||||
const Pixel_T & color1 = image( (width - x), yCenter); // right side center line check
|
||||
const Pixel_T & color1 = image( (width - 1 - x), yCenter); // right side center line check
|
||||
const Pixel_T & color2 = image(x, height33percent);
|
||||
const Pixel_T & color3 = image(x, height66percent);
|
||||
if (!isBlack(color1) || !isBlack(color2) || !isBlack(color3))
|
||||
@ -92,9 +96,9 @@ namespace hyperion
|
||||
}
|
||||
|
||||
// find first Y pixel of the image
|
||||
for (int y = 0; y < height; ++y)
|
||||
for (int y = 0; y < height33percent; ++y)
|
||||
{
|
||||
const Pixel_T & color1 = image(xCenter, (height - y)); // bottom center line check
|
||||
const Pixel_T & color1 = image(xCenter, (height - 1 - y)); // bottom center line check
|
||||
const Pixel_T & color2 = image(width33percent, y );
|
||||
const Pixel_T & color3 = image(width66percent, y);
|
||||
if (!isBlack(color1) || !isBlack(color2) || !isBlack(color3))
|
||||
@ -112,6 +116,120 @@ namespace hyperion
|
||||
return detectedBorder;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// classic detection mode (topleft single line mode)
|
||||
template <typename Pixel_T>
|
||||
BlackBorder process_classic(const Image<Pixel_T> & image)
|
||||
{
|
||||
// only test the topleft third of the image
|
||||
int width = image.width() /3;
|
||||
int height = image.height() / 3;
|
||||
int maxSize = std::max(width, height);
|
||||
|
||||
int firstNonBlackXPixelIndex = -1;
|
||||
int firstNonBlackYPixelIndex = -1;
|
||||
|
||||
// find some pixel of the image
|
||||
for (int i = 0; i < maxSize; ++i)
|
||||
{
|
||||
int x = std::min(i, width);
|
||||
int y = std::min(i, height);
|
||||
|
||||
const Pixel_T & color = image(x, y);
|
||||
if (!isBlack(color))
|
||||
{
|
||||
firstNonBlackXPixelIndex = x;
|
||||
firstNonBlackYPixelIndex = y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// expand image to the left
|
||||
for(; firstNonBlackXPixelIndex > 0; --firstNonBlackXPixelIndex)
|
||||
{
|
||||
const Pixel_T & color = image(firstNonBlackXPixelIndex-1, firstNonBlackYPixelIndex);
|
||||
if (isBlack(color))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// expand image to the top
|
||||
for(; firstNonBlackYPixelIndex > 0; --firstNonBlackYPixelIndex)
|
||||
{
|
||||
const Pixel_T & color = image(firstNonBlackXPixelIndex, firstNonBlackYPixelIndex-1);
|
||||
if (isBlack(color))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Construct result
|
||||
BlackBorder detectedBorder;
|
||||
detectedBorder.unknown = firstNonBlackXPixelIndex == -1 || firstNonBlackYPixelIndex == -1;
|
||||
detectedBorder.horizontalSize = firstNonBlackYPixelIndex;
|
||||
detectedBorder.verticalSize = firstNonBlackXPixelIndex;
|
||||
return detectedBorder;
|
||||
}
|
||||
|
||||
|
||||
// osd detection mode (find x then y at detected x to avoid changes by osd overlays)
|
||||
template <typename Pixel_T>
|
||||
BlackBorder process_osd(const Image<Pixel_T> & image)
|
||||
{
|
||||
// find X position at height33 and height66 we check from the left side, Ycenter will check from right side
|
||||
// then we try to find a pixel at this X position from top and bottom and right side from top
|
||||
int width = image.width();
|
||||
int height = image.height();
|
||||
int width33percent = width / 3;
|
||||
int height33percent = height / 3;
|
||||
// int width66percent = width33percent * 2;
|
||||
int height66percent = height33percent * 2;
|
||||
// int xCenter = width / 2;
|
||||
int yCenter = height / 2;
|
||||
|
||||
|
||||
int firstNonBlackXPixelIndex = -1;
|
||||
int firstNonBlackYPixelIndex = -1;
|
||||
|
||||
// find first X pixel of the image
|
||||
int x;
|
||||
for (x = 0; x < width33percent; ++x)
|
||||
{
|
||||
const Pixel_T & color1 = image( (width - 1 - x), yCenter); // right side center line check
|
||||
const Pixel_T & color2 = image(x, height33percent);
|
||||
const Pixel_T & color3 = image(x, height66percent);
|
||||
if (!isBlack(color1) || !isBlack(color2) || !isBlack(color3))
|
||||
{
|
||||
firstNonBlackXPixelIndex = x;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// find first Y pixel of the image
|
||||
for (int y = 0; y < height33percent; ++y)
|
||||
{
|
||||
const Pixel_T & color1 = image(x, (height - 1 - y)); // left side bottom check
|
||||
const Pixel_T & color2 = image(x, y );// left side top check
|
||||
const Pixel_T & color3 = image( (width - 1 - x), y); // right side top check
|
||||
if (!isBlack(color1) || !isBlack(color2) || !isBlack(color3))
|
||||
{
|
||||
firstNonBlackYPixelIndex = y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Construct result
|
||||
BlackBorder detectedBorder;
|
||||
detectedBorder.unknown = firstNonBlackXPixelIndex == -1 || firstNonBlackYPixelIndex == -1;
|
||||
detectedBorder.horizontalSize = firstNonBlackYPixelIndex;
|
||||
detectedBorder.verticalSize = firstNonBlackXPixelIndex;
|
||||
return detectedBorder;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
///
|
||||
@ -131,5 +249,6 @@ namespace hyperion
|
||||
private:
|
||||
/// Threshold for the blackborder detector [0 .. 255]
|
||||
const uint8_t _blackborderThreshold;
|
||||
|
||||
};
|
||||
} // end namespace hyperion
|
||||
|
@ -1,6 +1,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
// Jsoncpp includes
|
||||
#include <json/json.h>
|
||||
// Local Hyperion includes
|
||||
#include "BlackBorderDetector.h"
|
||||
|
||||
@ -23,11 +25,7 @@ namespace hyperion
|
||||
/// outer pixels is blurred (black and color combined due to image scaling))
|
||||
/// @param[in] blackborderThreshold The threshold which the blackborder detector should use
|
||||
///
|
||||
BlackBorderProcessor(
|
||||
const unsigned unknownFrameCnt,
|
||||
const unsigned borderFrameCnt,
|
||||
const unsigned blurRemoveCnt,
|
||||
uint8_t blackborderThreshold);
|
||||
BlackBorderProcessor(const Json::Value &blackborderConfig);
|
||||
|
||||
///
|
||||
/// Return the current (detected) border
|
||||
@ -48,7 +46,14 @@ namespace hyperion
|
||||
bool process(const Image<Pixel_T> & image)
|
||||
{
|
||||
// get the border for the single image
|
||||
BlackBorder imageBorder = _detector.process(image);
|
||||
BlackBorder imageBorder;
|
||||
if (_detectionMode == "default") {
|
||||
imageBorder = _detector.process(image);
|
||||
} else if (_detectionMode == "classic") {
|
||||
imageBorder = _detector.process_classic(image);
|
||||
} else if (_detectionMode == "osd") {
|
||||
imageBorder = _detector.process_osd(image);
|
||||
}
|
||||
// add blur to the border
|
||||
if (imageBorder.horizontalSize > 0)
|
||||
{
|
||||
@ -80,9 +85,15 @@ namespace hyperion
|
||||
/// The number of horizontal/vertical borders detected before it becomes the current border
|
||||
const unsigned _borderSwitchCnt;
|
||||
|
||||
// The number of frames that are "ignored" before a new border gets set as _previousDetectedBorder
|
||||
const unsigned _maxInconsistentCnt;
|
||||
|
||||
/// The number of pixels to increase a detected border for removing blury pixels
|
||||
unsigned _blurRemoveCnt;
|
||||
|
||||
/// The border detection mode
|
||||
const std::string _detectionMode;
|
||||
|
||||
/// The blackborder detector
|
||||
BlackBorderDetector _detector;
|
||||
|
||||
@ -96,5 +107,6 @@ namespace hyperion
|
||||
unsigned _consistentCnt;
|
||||
/// The number of frame the previous detected border NOT matched the incomming border
|
||||
unsigned _inconsistentCnt;
|
||||
|
||||
};
|
||||
} // end namespace hyperion
|
||||
|
@ -106,7 +106,7 @@ private:
|
||||
/// @param[in] enableBlackBorderDetector Flag indicating if the blacborder detector should be enabled
|
||||
/// @param[in] blackborderThreshold The threshold which the blackborder detector should use
|
||||
///
|
||||
ImageProcessor(const LedString &ledString, bool enableBlackBorderDetector, uint8_t blackborderThreshold);
|
||||
ImageProcessor(const LedString &ledString, const Json::Value &blackborderConfig);
|
||||
|
||||
///
|
||||
/// Performs black-border detection (if enabled) on the given image
|
||||
|
@ -33,7 +33,7 @@ public:
|
||||
/// @param[in] enableBlackBorderDetector Flag indicating if the blacborder detector should be enabled
|
||||
/// @param[in] blackborderThreshold The threshold which the blackborder detector should use
|
||||
///
|
||||
void init(const LedString& ledString, bool enableBlackBorderDetector, double blackborderThreshold);
|
||||
void init(const LedString& ledString, const Json::Value &blackborderConfig);
|
||||
|
||||
///
|
||||
/// Creates a new ImageProcessor. The onwership of the processor is transferred to the caller.
|
||||
@ -46,9 +46,6 @@ private:
|
||||
/// The Led-string specification
|
||||
LedString _ledString;
|
||||
|
||||
/// Flag indicating if the black border detector should be used
|
||||
bool _enableBlackBorderDetector;
|
||||
|
||||
/// Threshold for the blackborder detector [0 .. 255]
|
||||
uint8_t _blackborderThreshold;
|
||||
// Reference to the blackborder json configuration values
|
||||
Json::Value _blackborderConfig;
|
||||
};
|
||||
|
@ -1,11 +1,26 @@
|
||||
|
||||
#include <iostream>
|
||||
// BlackBorders includes
|
||||
#include <blackborder/BlackBorderDetector.h>
|
||||
|
||||
using namespace hyperion;
|
||||
|
||||
BlackBorderDetector::BlackBorderDetector(uint8_t blackborderThreshold) :
|
||||
_blackborderThreshold(blackborderThreshold)
|
||||
BlackBorderDetector::BlackBorderDetector(double threshold) :
|
||||
_blackborderThreshold(calculateThreshold(threshold))
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
uint8_t BlackBorderDetector::calculateThreshold(double threshold)
|
||||
{
|
||||
int rgbThreshold = int(std::ceil(threshold * 255));
|
||||
if (rgbThreshold < 0)
|
||||
rgbThreshold = 0;
|
||||
else if (rgbThreshold > 255)
|
||||
rgbThreshold = 255;
|
||||
|
||||
uint8_t blackborderThreshold = uint8_t(rgbThreshold);
|
||||
|
||||
std::cout << "Black border threshold set to " << threshold << " (" << int(blackborderThreshold) << ")" << std::endl;
|
||||
|
||||
return blackborderThreshold;
|
||||
}
|
||||
|
@ -1,23 +1,31 @@
|
||||
//#include <iostream>
|
||||
|
||||
//*
|
||||
#include <iostream>
|
||||
/*
|
||||
#include <iomanip>
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
using std::setw;
|
||||
using std::left;
|
||||
//*/
|
||||
// Blackborder includes
|
||||
#include <blackborder/BlackBorderProcessor.h>
|
||||
|
||||
|
||||
using namespace hyperion;
|
||||
|
||||
BlackBorderProcessor::BlackBorderProcessor(const unsigned unknownFrameCnt,
|
||||
const unsigned borderFrameCnt,
|
||||
const unsigned blurRemoveCnt,
|
||||
uint8_t blackborderThreshold) :
|
||||
_unknownSwitchCnt(unknownFrameCnt),
|
||||
_borderSwitchCnt(borderFrameCnt),
|
||||
_blurRemoveCnt(blurRemoveCnt),
|
||||
_detector(blackborderThreshold),
|
||||
BlackBorderProcessor::BlackBorderProcessor(const Json::Value &blackborderConfig) :
|
||||
_unknownSwitchCnt(blackborderConfig.get("unknownFrameCnt", 600).asUInt()),
|
||||
_borderSwitchCnt(blackborderConfig.get("borderFrameCnt", 50).asUInt()),
|
||||
_maxInconsistentCnt(blackborderConfig.get("maxInconsistentCnt", 10).asUInt()),
|
||||
_blurRemoveCnt(blackborderConfig.get("blurRemoveCnt", 1).asUInt()),
|
||||
_detectionMode(blackborderConfig.get("mode", "default").asString()),
|
||||
_detector(blackborderConfig.get("threshold", 0.01).asDouble()),
|
||||
_currentBorder({true, -1, -1}),
|
||||
_previousDetectedBorder({true, -1, -1}),
|
||||
_consistentCnt(0),
|
||||
_inconsistentCnt(10)
|
||||
{
|
||||
std::cout << "DETECTION MODE:" << _detectionMode << std::endl;
|
||||
// empty
|
||||
}
|
||||
|
||||
@ -39,7 +47,7 @@ bool BlackBorderProcessor::updateBorder(const BlackBorder & newDetectedBorder)
|
||||
// makes it look like the border detectionn is not working - since the new 3 line detection algorithm is more precise this became a problem specialy in dark scenes
|
||||
// wisc
|
||||
|
||||
// std::cout << "cur: " << _currentBorder.verticalSize << " " << _currentBorder.horizontalSize << " new: " << newDetectedBorder.verticalSize << " " << newDetectedBorder.horizontalSize << " c:i " << _consistentCnt << ":" << _inconsistentCnt << std::endl;
|
||||
// std::cout << "c: " << setw(2) << _currentBorder.verticalSize << " " << setw(2) << _currentBorder.horizontalSize << " p: " << setw(2) << _previousDetectedBorder.verticalSize << " " << setw(2) << _previousDetectedBorder.horizontalSize << " n: " << setw(2) << newDetectedBorder.verticalSize << " " << setw(2) << newDetectedBorder.horizontalSize << " c:i " << setw(2) << _consistentCnt << ":" << setw(2) << _inconsistentCnt << std::endl;
|
||||
|
||||
// set the consistency counter
|
||||
if (newDetectedBorder == _previousDetectedBorder)
|
||||
@ -50,7 +58,7 @@ bool BlackBorderProcessor::updateBorder(const BlackBorder & newDetectedBorder)
|
||||
else
|
||||
{
|
||||
++_inconsistentCnt;
|
||||
if (_inconsistentCnt <= 10)// few inconsistent frames
|
||||
if (_inconsistentCnt <= _maxInconsistentCnt)// only few inconsistent frames
|
||||
{
|
||||
//discard the newDetectedBorder -> keep the consistent count for previousDetectedBorder
|
||||
return false;
|
||||
|
@ -282,8 +282,8 @@ Hyperion::Hyperion(const Json::Value &jsonConfig) :
|
||||
// initialize the image processor factory
|
||||
ImageProcessorFactory::getInstance().init(
|
||||
_ledString,
|
||||
jsonConfig["blackborderdetector"].get("enable", true).asBool(),
|
||||
jsonConfig["blackborderdetector"].get("threshold", 0.01).asDouble());
|
||||
jsonConfig["blackborderdetector"]
|
||||
);
|
||||
|
||||
// initialize the color smoothing filter
|
||||
_device = createColorSmoothing(jsonConfig["color"]["smoothing"], _device);
|
||||
|
@ -8,10 +8,11 @@
|
||||
|
||||
using namespace hyperion;
|
||||
|
||||
ImageProcessor::ImageProcessor(const LedString& ledString, bool enableBlackBorderDetector, uint8_t blackborderThreshold) :
|
||||
//ImageProcessor::ImageProcessor(const LedString& ledString, bool enableBlackBorderDetector, uint8_t blackborderThreshold) :
|
||||
ImageProcessor::ImageProcessor(const LedString& ledString, const Json::Value & blackborderConfig) :
|
||||
_ledString(ledString),
|
||||
_enableBlackBorderRemoval(enableBlackBorderDetector),
|
||||
_borderProcessor(new BlackBorderProcessor(600, 50, 1, blackborderThreshold)),
|
||||
_enableBlackBorderRemoval(blackborderConfig.get("enable", true).asBool()),
|
||||
_borderProcessor(new BlackBorderProcessor(blackborderConfig) ),
|
||||
_imageToLeds(nullptr)
|
||||
{
|
||||
// empty
|
||||
|
@ -13,25 +13,13 @@ ImageProcessorFactory& ImageProcessorFactory::getInstance()
|
||||
return instance;
|
||||
}
|
||||
|
||||
void ImageProcessorFactory::init(const LedString& ledString, bool enableBlackBorderDetector, double blackborderThreshold)
|
||||
void ImageProcessorFactory::init(const LedString& ledString, const Json::Value & blackborderConfig)
|
||||
{
|
||||
_ledString = ledString;
|
||||
_enableBlackBorderDetector = enableBlackBorderDetector;
|
||||
|
||||
int threshold = int(std::ceil(blackborderThreshold * 255));
|
||||
if (threshold < 0)
|
||||
threshold = 0;
|
||||
else if (threshold > 255)
|
||||
threshold = 255;
|
||||
_blackborderThreshold = uint8_t(threshold);
|
||||
|
||||
if (_enableBlackBorderDetector)
|
||||
{
|
||||
std::cout << "Black border threshold set to " << blackborderThreshold << " (" << int(_blackborderThreshold) << ")" << std::endl;
|
||||
}
|
||||
_blackborderConfig = blackborderConfig;
|
||||
}
|
||||
|
||||
ImageProcessor* ImageProcessorFactory::newImageProcessor() const
|
||||
{
|
||||
return new ImageProcessor(_ledString, _enableBlackBorderDetector, _blackborderThreshold);
|
||||
return new ImageProcessor(_ledString, _blackborderConfig);
|
||||
}
|
||||
|
@ -44,11 +44,13 @@ Image<ColorRgb> createImage(unsigned width, unsigned height, unsigned topBorder,
|
||||
|
||||
int main()
|
||||
{
|
||||
unsigned unknownCnt = 600;
|
||||
// unsigned unknownCnt = 600;
|
||||
unsigned borderCnt = 50;
|
||||
unsigned blurCnt = 0;
|
||||
// unsigned blurCnt = 0;
|
||||
Json::Value config;
|
||||
|
||||
BlackBorderProcessor processor(unknownCnt, borderCnt, blurCnt, 3);
|
||||
// BlackBorderProcessor processor(unknownCnt, borderCnt, blurCnt, 3, config);
|
||||
BlackBorderProcessor processor(config);
|
||||
|
||||
// Start with 'no border' detection
|
||||
Image<ColorRgb> noBorderImage = createImage(64, 64, 0, 0);
|
||||
|
Loading…
Reference in New Issue
Block a user