Configurable blackborder threshold added

Former-commit-id: 95b77dee2869b41bf556e0e374bea3c5e4534e61
This commit is contained in:
johan 2014-01-20 20:46:38 +01:00
parent af08b9b5d0
commit a7110ec64c
15 changed files with 121 additions and 49 deletions

View File

@ -56,21 +56,21 @@
"red" : "red" :
{ {
"threshold" : 0.0000, "threshold" : 0.0000,
"gamma" : 2.0000, "gamma" : 1.0000,
"blacklevel" : 0.0000, "blacklevel" : 0.0000,
"whitelevel" : 1.0000 "whitelevel" : 1.0000
}, },
"green" : "green" :
{ {
"threshold" : 0.0000, "threshold" : 0.0000,
"gamma" : 2.0000, "gamma" : 1.0000,
"blacklevel" : 0.0000, "blacklevel" : 0.0000,
"whitelevel" : 1.0000 "whitelevel" : 1.0000
}, },
"blue" : "blue" :
{ {
"threshold" : 0.0000, "threshold" : 0.0000,
"gamma" : 2.0000, "gamma" : 1.0000,
"blacklevel" : 0.0000, "blacklevel" : 0.0000,
"whitelevel" : 1.0000 "whitelevel" : 1.0000
} }
@ -348,10 +348,12 @@
], ],
/// The black border configuration, contains the following items: /// The black border configuration, contains the following items:
/// * enable : true if the detector should be activated /// * 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" : "blackborderdetector" :
{ {
"enable" : true "enable" : true,
"threshold" : 0.01
}, },
/// The configuration of the effect engine, contains the following items: /// The configuration of the effect engine, contains the following items:

View File

@ -13,9 +13,9 @@
"device" : "device" :
{ {
"name" : "MyPi", "name" : "MyPi",
"type" : "test", "type" : "adalight",
"output" : "~/hyperion.test.out", "output" : "/dev/ttyUSB0",
"rate" : 250000, "rate" : 115200,
"colorOrder" : "rgb" "colorOrder" : "rgb"
}, },
@ -348,10 +348,12 @@
], ],
/// The black border configuration, contains the following items: /// The black border configuration, contains the following items:
/// * enable : true if the detector should be activated /// * 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" : "blackborderdetector" :
{ {
"enable" : true "enable" : true,
"threshold" : 0.01
}, },
/// The configuration of the effect engine, contains the following items: /// The configuration of the effect engine, contains the following items:
@ -371,6 +373,38 @@
"duration_ms" : 3000 "duration_ms" : 3000
}, },
/// The configuration for the frame-grabber, contains the following items:
/// * width : The width of the grabbed frames [pixels]
/// * height : The height of the grabbed frames [pixels]
/// * frequency_Hz : The frequency of the frame grab [Hz]
// "framegrabber" :
// {
// "width" : 64,
// "height" : 64,
// "frequency_Hz" : 10.0
// },
/// The configuration of the XBMC connection used to enable and disable the frame-grabber. Contains the following fields:
/// * xbmcAddress : The IP address of the XBMC-host
/// * xbmcTcpPort : The TCP-port of the XBMC-server
/// * grabVideo : Flag indicating that the frame-grabber is on(true) during video playback
/// * grabPictures : Flag indicating that the frame-grabber is on(true) during picture show
/// * grabAudio : Flag indicating that the frame-grabber is on(true) during audio playback
/// * grabMenu : Flag indicating that the frame-grabber is on(true) in the XBMC menu
/// * grabScreensaver : Flag indicating that the frame-grabber is on(true) when XBMC is on screensaver
/// * enable3DDetection : Flag indicating that the frame-grabber should switch to a 3D compatible modus if a 3D video is playing
// "xbmcVideoChecker" :
// {
// "xbmcAddress" : "127.0.0.1",
// "xbmcTcpPort" : 9090,
// "grabVideo" : true,
// "grabPictures" : true,
// "grabAudio" : true,
// "grabMenu" : false,
// "grabScreensaver" : true,
// "enable3DDetection" : true
// },
/// The configuration of the Json server which enables the json remote interface /// The configuration of the Json server which enables the json remote interface
/// * port : Port at which the json server is started /// * port : Port at which the json server is started
"jsonServer" : "jsonServer" :

View File

@ -1 +1 @@
96b8f6c7e0241930c944a7358af473dabecf1dae 2ad39031528c40c14e352cbc84784f48564cc59b

View File

@ -48,8 +48,9 @@ namespace hyperion
public: public:
/// ///
/// Constructs a black-border detector /// Constructs a black-border detector
/// @param[in] blackborderThreshold The threshold which the blackborder detector should use
/// ///
BlackBorderDetector(); BlackBorderDetector(uint8_t blackborderThreshold);
/// ///
/// Performs the actual black-border detection on the given image /// Performs the actual black-border detection on the given image
@ -125,7 +126,11 @@ namespace hyperion
inline bool isBlack(const Pixel_T & color) inline bool isBlack(const Pixel_T & color)
{ {
// Return the simple compare of the color against black // Return the simple compare of the color against black
return color.red < 3 && color.green < 3 && color.green < 3; return color.red < _blackborderThreshold && color.green < _blackborderThreshold && color.green < _blackborderThreshold;
} }
private:
/// Threshold for the blackborder detector [0 .. 255]
const uint8_t _blackborderThreshold;
}; };
} // end namespace hyperion } // end namespace hyperion

View File

@ -21,11 +21,13 @@ namespace hyperion
/// horizontal border becomes the current border /// horizontal border becomes the current border
/// @param blurRemoveCnt The size to add to a horizontal or vertical border (because the /// @param blurRemoveCnt The size to add to a horizontal or vertical border (because the
/// outer pixels is blurred (black and color combined due to image scaling)) /// outer pixels is blurred (black and color combined due to image scaling))
/// @param[in] blackborderThreshold The threshold which the blackborder detector should use
/// ///
BlackBorderProcessor( BlackBorderProcessor(
const unsigned unknownFrameCnt, const unsigned unknownFrameCnt,
const unsigned borderFrameCnt, const unsigned borderFrameCnt,
const unsigned blurRemoveCnt); const unsigned blurRemoveCnt,
uint8_t blackborderThreshold);
/// ///
/// Return the current (detected) border /// Return the current (detected) border

View File

@ -53,7 +53,7 @@ public:
verifyBorder(image); verifyBorder(image);
// Create a result vector and call the 'in place' functionl // Create a result vector and call the 'in place' functionl
std::vector<ColorRgb> colors = mImageToLeds->getMeanLedColor(image); std::vector<ColorRgb> colors = _imageToLeds->getMeanLedColor(image);
// return the computed colors // return the computed colors
return colors; return colors;
@ -75,7 +75,7 @@ public:
verifyBorder(image); verifyBorder(image);
// Determine the mean-colors of each led (using the existing mapping) // Determine the mean-colors of each led (using the existing mapping)
mImageToLeds->getMeanLedColor(image, ledColors); _imageToLeds->getMeanLedColor(image, ledColors);
} }
/// ///
@ -98,8 +98,10 @@ private:
/// given led-string specification /// given led-string specification
/// ///
/// @param[in] ledString The led-string specification /// @param[in] ledString The led-string specification
/// @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); ImageProcessor(const LedString &ledString, bool enableBlackBorderDetector, uint8_t blackborderThreshold);
/// ///
/// Performs black-border detection (if enabled) on the given image /// Performs black-border detection (if enabled) on the given image
@ -116,17 +118,17 @@ private:
const hyperion::BlackBorder border = _borderProcessor->getCurrentBorder(); const hyperion::BlackBorder border = _borderProcessor->getCurrentBorder();
// Clean up the old mapping // Clean up the old mapping
delete mImageToLeds; delete _imageToLeds;
if (border.unknown) if (border.unknown)
{ {
// Construct a new buffer and mapping // Construct a new buffer and mapping
mImageToLeds = new hyperion::ImageToLedsMap(image.width(), image.height(), 0, 0, mLedString.leds()); _imageToLeds = new hyperion::ImageToLedsMap(image.width(), image.height(), 0, 0, _ledString.leds());
} }
else else
{ {
// Construct a new buffer and mapping // Construct a new buffer and mapping
mImageToLeds = new hyperion::ImageToLedsMap(image.width(), image.height(), border.horizontalSize, border.verticalSize, mLedString.leds()); _imageToLeds = new hyperion::ImageToLedsMap(image.width(), image.height(), border.horizontalSize, border.verticalSize, _ledString.leds());
} }
std::cout << "CURRENT BORDER TYPE: unknown=" << border.unknown << " hor.size=" << border.horizontalSize << " vert.size=" << border.verticalSize << std::endl; std::cout << "CURRENT BORDER TYPE: unknown=" << border.unknown << " hor.size=" << border.horizontalSize << " vert.size=" << border.verticalSize << std::endl;
@ -135,14 +137,14 @@ private:
private: private:
/// The Led-string specification /// The Led-string specification
const LedString mLedString; const LedString _ledString;
/// Flag the enables(true)/disabled(false) blackborder detector /// Flag the enables(true)/disabled(false) blackborder detector
bool _enableBlackBorderRemoval; const bool _enableBlackBorderRemoval;
/// The processor for black border detection /// The processor for black border detection
hyperion::BlackBorderProcessor * _borderProcessor; hyperion::BlackBorderProcessor * _borderProcessor;
/// The mapping of image-pixels to leds /// The mapping of image-pixels to leds
hyperion::ImageToLedsMap* mImageToLeds; hyperion::ImageToLedsMap* _imageToLeds;
}; };

View File

@ -30,8 +30,10 @@ public:
/// Initialises this factory with the given led-configuration /// Initialises this factory with the given led-configuration
/// ///
/// @param[in] ledString The led configuration /// @param[in] ledString The led configuration
/// @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); void init(const LedString& ledString, bool enableBlackBorderDetector, double blackborderThreshold);
/// ///
/// Creates a new ImageProcessor. The onwership of the processor is transferred to the caller. /// Creates a new ImageProcessor. The onwership of the processor is transferred to the caller.
@ -46,4 +48,7 @@ private:
/// Flag indicating if the black border detector should be used /// Flag indicating if the black border detector should be used
bool _enableBlackBorderDetector; bool _enableBlackBorderDetector;
/// Threshold for the blackborder detector [0 .. 255]
uint8_t _blackborderThreshold;
}; };

View File

@ -4,7 +4,8 @@
using namespace hyperion; using namespace hyperion;
BlackBorderDetector::BlackBorderDetector() BlackBorderDetector::BlackBorderDetector(uint8_t blackborderThreshold) :
_blackborderThreshold(blackborderThreshold)
{ {
// empty // empty
} }

View File

@ -4,14 +4,14 @@
using namespace hyperion; using namespace hyperion;
BlackBorderProcessor::BlackBorderProcessor( BlackBorderProcessor::BlackBorderProcessor(const unsigned unknownFrameCnt,
const unsigned unknownFrameCnt,
const unsigned borderFrameCnt, const unsigned borderFrameCnt,
const unsigned blurRemoveCnt) : const unsigned blurRemoveCnt,
uint8_t blackborderThreshold) :
_unknownSwitchCnt(unknownFrameCnt), _unknownSwitchCnt(unknownFrameCnt),
_borderSwitchCnt(borderFrameCnt), _borderSwitchCnt(borderFrameCnt),
_blurRemoveCnt(blurRemoveCnt), _blurRemoveCnt(blurRemoveCnt),
_detector(), _detector(blackborderThreshold),
_currentBorder({true, -1, -1}), _currentBorder({true, -1, -1}),
_previousDetectedBorder({true, -1, -1}), _previousDetectedBorder({true, -1, -1}),
_consistentCnt(0) _consistentCnt(0)

View File

@ -270,7 +270,10 @@ Hyperion::Hyperion(const Json::Value &jsonConfig) :
throw std::runtime_error("Color transformation incorrectly set"); throw std::runtime_error("Color transformation incorrectly set");
} }
// initialize the image processor factory // initialize the image processor factory
ImageProcessorFactory::getInstance().init(_ledString, jsonConfig["blackborderdetector"].get("enable", true).asBool()); ImageProcessorFactory::getInstance().init(
_ledString,
jsonConfig["blackborderdetector"].get("enable", true).asBool(),
jsonConfig["blackborderdetector"].get("threshold", 0.01).asDouble());
// initialize the color smoothing filter // initialize the color smoothing filter
_device = createColorSmoothing(jsonConfig["color"]["smoothing"], _device); _device = createColorSmoothing(jsonConfig["color"]["smoothing"], _device);

View File

@ -6,46 +6,46 @@
using namespace hyperion; using namespace hyperion;
ImageProcessor::ImageProcessor(const LedString& ledString, bool enableBlackBorderDetector) : ImageProcessor::ImageProcessor(const LedString& ledString, bool enableBlackBorderDetector, uint8_t blackborderThreshold) :
mLedString(ledString), _ledString(ledString),
_enableBlackBorderRemoval(enableBlackBorderDetector), _enableBlackBorderRemoval(enableBlackBorderDetector),
_borderProcessor(new BlackBorderProcessor(600, 50, 1)), _borderProcessor(new BlackBorderProcessor(600, 50, 1, blackborderThreshold)),
mImageToLeds(nullptr) _imageToLeds(nullptr)
{ {
// empty // empty
} }
ImageProcessor::~ImageProcessor() ImageProcessor::~ImageProcessor()
{ {
delete mImageToLeds; delete _imageToLeds;
delete _borderProcessor; delete _borderProcessor;
} }
unsigned ImageProcessor::getLedCount() const unsigned ImageProcessor::getLedCount() const
{ {
return mLedString.leds().size(); return _ledString.leds().size();
} }
void ImageProcessor::setSize(const unsigned width, const unsigned height) void ImageProcessor::setSize(const unsigned width, const unsigned height)
{ {
// Check if the existing buffer-image is already the correct dimensions // Check if the existing buffer-image is already the correct dimensions
if (mImageToLeds && mImageToLeds->width() == width && mImageToLeds->height() == height) if (_imageToLeds && _imageToLeds->width() == width && _imageToLeds->height() == height)
{ {
return; return;
} }
// Clean up the old buffer and mapping // Clean up the old buffer and mapping
delete mImageToLeds; delete _imageToLeds;
// Construct a new buffer and mapping // Construct a new buffer and mapping
mImageToLeds = new ImageToLedsMap(width, height, 0, 0, mLedString.leds()); _imageToLeds = new ImageToLedsMap(width, height, 0, 0, _ledString.leds());
} }
bool ImageProcessor::getScanParameters(size_t led, double &hscanBegin, double &hscanEnd, double &vscanBegin, double &vscanEnd) const bool ImageProcessor::getScanParameters(size_t led, double &hscanBegin, double &hscanEnd, double &vscanBegin, double &vscanEnd) const
{ {
if (led < mLedString.leds().size()) if (led < _ledString.leds().size())
{ {
const Led & l = mLedString.leds()[led]; const Led & l = _ledString.leds()[led];
hscanBegin = l.minX_frac; hscanBegin = l.minX_frac;
hscanEnd = l.maxX_frac; hscanEnd = l.maxX_frac;
vscanBegin = l.minY_frac; vscanBegin = l.minY_frac;

View File

@ -10,13 +10,25 @@ ImageProcessorFactory& ImageProcessorFactory::getInstance()
return instance; return instance;
} }
void ImageProcessorFactory::init(const LedString& ledString, bool enableBlackBorderDetector) void ImageProcessorFactory::init(const LedString& ledString, bool enableBlackBorderDetector, double blackborderThreshold)
{ {
_ledString = ledString; _ledString = ledString;
_enableBlackBorderDetector = enableBlackBorderDetector; _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;
}
} }
ImageProcessor* ImageProcessorFactory::newImageProcessor() const ImageProcessor* ImageProcessorFactory::newImageProcessor() const
{ {
return new ImageProcessor(_ledString, _enableBlackBorderDetector); return new ImageProcessor(_ledString, _enableBlackBorderDetector, _blackborderThreshold);
} }

View File

@ -223,6 +223,12 @@
"enable" : { "enable" : {
"type" : "boolean", "type" : "boolean",
"required" : true "required" : true
},
"threshold" : {
"type" : "number",
"required" : false,
"minimum" : 0.0,
"maximum" : 1.0
} }
}, },
"additionalProperties" : false "additionalProperties" : false

View File

@ -41,7 +41,7 @@ int TC_NO_BORDER()
{ {
int result = 0; int result = 0;
BlackBorderDetector detector; BlackBorderDetector detector(3);
{ {
Image<ColorRgb> image = createImage(64, 64, 0, 0); Image<ColorRgb> image = createImage(64, 64, 0, 0);
@ -60,7 +60,7 @@ int TC_TOP_BORDER()
{ {
int result = 0; int result = 0;
BlackBorderDetector detector; BlackBorderDetector detector(3);
{ {
Image<ColorRgb> image = createImage(64, 64, 12, 0); Image<ColorRgb> image = createImage(64, 64, 12, 0);
@ -79,7 +79,7 @@ int TC_LEFT_BORDER()
{ {
int result = 0; int result = 0;
BlackBorderDetector detector; BlackBorderDetector detector(3);
{ {
Image<ColorRgb> image = createImage(64, 64, 0, 12); Image<ColorRgb> image = createImage(64, 64, 0, 12);
@ -98,7 +98,7 @@ int TC_DUAL_BORDER()
{ {
int result = 0; int result = 0;
BlackBorderDetector detector; BlackBorderDetector detector(3);
{ {
Image<ColorRgb> image = createImage(64, 64, 12, 12); Image<ColorRgb> image = createImage(64, 64, 12, 12);
@ -116,7 +116,7 @@ int TC_UNKNOWN_BORDER()
{ {
int result = 0; int result = 0;
BlackBorderDetector detector; BlackBorderDetector detector(3);
{ {
Image<ColorRgb> image = createImage(64, 64, 30, 30); Image<ColorRgb> image = createImage(64, 64, 30, 30);

View File

@ -48,7 +48,7 @@ int main()
unsigned borderCnt = 50; unsigned borderCnt = 50;
unsigned blurCnt = 0; unsigned blurCnt = 0;
BlackBorderProcessor processor(unknownCnt, borderCnt, blurCnt); BlackBorderProcessor processor(unknownCnt, borderCnt, blurCnt, 3);
// Start with 'no border' detection // Start with 'no border' detection
Image<ColorRgb> noBorderImage = createImage(64, 64, 0, 0); Image<ColorRgb> noBorderImage = createImage(64, 64, 0, 0);