mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2023-10-10 13:36:59 +02:00
Merge remote-tracking branch 'upstream/master'
Former-commit-id: 9b4da8b8c5f61f9507b4775d0f28e187a0246605
This commit is contained in:
commit
aaba90209f
@ -355,15 +355,30 @@
|
|||||||
/// 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)
|
/// * threshold : Value below which a pixel is regarded as black (value between 0.0 and 1.0)
|
||||||
|
/// * 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" :
|
"blackborderdetector" :
|
||||||
{
|
{
|
||||||
"enable" : true,
|
"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:
|
/// The configuration of the effect engine, contains the following items:
|
||||||
/// * paths : An array with absolute location(s) of directories with effects
|
/// * paths : An array with absolute location(s) of directories with effects
|
||||||
/// * bootsequence : The effect selected as 'boot sequence'
|
/// * bootsequence : The effect selected as 'boot sequence'
|
||||||
|
/// * effect : name of the effect you want to start. Set to empty if no effect wanted
|
||||||
|
/// * color : switch to static color after effect is done
|
||||||
|
/// * duration_ms : duration of boot effect in ms. 0 means effect stays forever
|
||||||
|
/// * priority : priority of boot effect and static color
|
||||||
"effects" :
|
"effects" :
|
||||||
{
|
{
|
||||||
"paths" :
|
"paths" :
|
||||||
@ -374,8 +389,10 @@
|
|||||||
|
|
||||||
"bootsequence" :
|
"bootsequence" :
|
||||||
{
|
{
|
||||||
"effect" : "Rainbow swirl fast",
|
"color" : [0,0,0],
|
||||||
"duration_ms" : 3000
|
"effect" : "Rainbow swirl fast",
|
||||||
|
"duration_ms" : 3000,
|
||||||
|
"priority" : 0
|
||||||
},
|
},
|
||||||
|
|
||||||
/// The configuration for the frame-grabber, contains the following items:
|
/// The configuration for the frame-grabber, contains the following items:
|
||||||
|
@ -359,6 +359,10 @@
|
|||||||
/// The configuration of the effect engine, contains the following items:
|
/// The configuration of the effect engine, contains the following items:
|
||||||
/// * paths : An array with absolute location(s) of directories with effects
|
/// * paths : An array with absolute location(s) of directories with effects
|
||||||
/// * bootsequence : The effect selected as 'boot sequence'
|
/// * bootsequence : The effect selected as 'boot sequence'
|
||||||
|
/// * effect : name of the effect you want to start. Set to empty if no effect wanted
|
||||||
|
/// * color : switch to static color after effect is done
|
||||||
|
/// * duration_ms : duration of boot effect in ms. 0 means effect stays forever
|
||||||
|
/// * priority : priority of boot effect and static color
|
||||||
"effects" :
|
"effects" :
|
||||||
{
|
{
|
||||||
"paths" :
|
"paths" :
|
||||||
@ -369,8 +373,10 @@
|
|||||||
|
|
||||||
"bootsequence" :
|
"bootsequence" :
|
||||||
{
|
{
|
||||||
"effect" : "Rainbow swirl fast",
|
"color" : [0,0,0],
|
||||||
"duration_ms" : 3000
|
"effect" : "Rainbow swirl fast",
|
||||||
|
"duration_ms" : 3000,
|
||||||
|
"priority" : 900
|
||||||
},
|
},
|
||||||
|
|
||||||
/// The configuration for the frame-grabber, contains the following items:
|
/// The configuration for the frame-grabber, contains the following items:
|
||||||
|
79
doc/datasheets/fadecandy_opc_protocol.md
Normal file
79
doc/datasheets/fadecandy_opc_protocol.md
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
Fadecandy: Open Pixel Control Protocol
|
||||||
|
======================================
|
||||||
|
|
||||||
|
The Fadecandy Server (`fcserver`) operates as a bridge between LED controllers attached over USB, and visual effects that communicate via a TCP socket.
|
||||||
|
|
||||||
|
The primary protocol supported by `fcserver` is [Open Pixel Control](http://openpixelcontrol.org), a super simple way to send RGB values over a socket. We support the standard Open Pixel Control commands, as well as some Fadecandy extensions.
|
||||||
|
|
||||||
|
Socket
|
||||||
|
------
|
||||||
|
|
||||||
|
Open Pixel Control uses a TCP socket, by default on port 7890. For the best performance, remember to set TCP_NODELAY socket option.
|
||||||
|
|
||||||
|
Command Format
|
||||||
|
--------------
|
||||||
|
|
||||||
|
All OPC commands follow the same general format. All multi-byte values in Open Pixel Control are in network byte order, high byte followed by low byte.
|
||||||
|
|
||||||
|
Channel | Command | Length (N) | Data
|
||||||
|
---------- | --------- | ---------- | --------------------------
|
||||||
|
1 byte | 1 byte | 2 bytes | N bytes of message data
|
||||||
|
|
||||||
|
Set Pixel Colors
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Video data arrives in a **Set Pixel Colors** command:
|
||||||
|
|
||||||
|
Byte | **Set Pixel Colors** command
|
||||||
|
------ | --------------------------------
|
||||||
|
0 | Channel Number
|
||||||
|
1 | Command (0x00)
|
||||||
|
2 - 3 | Data length
|
||||||
|
4 | Pixel #0, Red
|
||||||
|
5 | Pixel #0, Green
|
||||||
|
6 | Pixel #0, Blue
|
||||||
|
7 | Pixel #1, Red
|
||||||
|
8 | Pixel #1, Green
|
||||||
|
9 | Pixel #1, Blue
|
||||||
|
… | …
|
||||||
|
|
||||||
|
As soon as a complete Set Pixel Colors command is received, a new frame of video will be broadcast simultaneously to all attached Fadecandy devices.
|
||||||
|
|
||||||
|
Set Global Color Correction
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
The color correction data (from the 'color' configuration key) can also be changed at runtime, by sending a new blob of JSON text in a Fadecandy-specific command. Fadecandy's 16-bit System ID for Open Pixel Control's System Exclusive (0xFF) command is **0x0001**.
|
||||||
|
|
||||||
|
Byte | **Set Global Color Correction** command
|
||||||
|
------ | ------------------------------------------
|
||||||
|
0 | Channel Number (0x00, reserved)
|
||||||
|
1 | Command (0xFF, System Exclusive)
|
||||||
|
2 - 3 | Data length (JSON Length + 4)
|
||||||
|
4 - 5 | System ID (0x0001, Fadecandy)
|
||||||
|
6 - 7 | SysEx ID (0x0001, Set Global Color Correction)
|
||||||
|
8 - … | JSON Text
|
||||||
|
|
||||||
|
Set Firmware Configuration
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
The firmware supports some runtime configuration options. Any OPC client can send a new firmware configuration packet using this command. If the supplied data is shorter than the firmware's configuration buffer, only the provided bytes will be changed.
|
||||||
|
|
||||||
|
Byte | **Set Firmware Configuration** command
|
||||||
|
------ | ------------------------------------------
|
||||||
|
0 | Channel Number (0x00, reserved)
|
||||||
|
1 | Command (0xFF, System Exclusive)
|
||||||
|
2 - 3 | Data length (Configuration Length + 4)
|
||||||
|
4 - 5 | System ID (0x0001, Fadecandy)
|
||||||
|
6 - 7 | SysEx ID (0x0002, Set Firmware Configuration)
|
||||||
|
8 - … | Configuration Data
|
||||||
|
|
||||||
|
Current firmwares support the following configuration options:
|
||||||
|
|
||||||
|
Byte Offset | Bits | Description
|
||||||
|
----------- | ------ | ------------
|
||||||
|
0 | 7 … 4 | (reserved)
|
||||||
|
0 | 3 | Manual LED control bit
|
||||||
|
0 | 2 | 0 = LED shows USB activity, 1 = LED under manual control
|
||||||
|
0 | 1 | Disable keyframe interpolation
|
||||||
|
0 | 0 | Disable dithering
|
||||||
|
1 … 62 | 7 … 0 | (reserved)
|
@ -49,7 +49,7 @@ namespace hyperion
|
|||||||
/// Constructs a black-border detector
|
/// Constructs a black-border detector
|
||||||
/// @param[in] blackborderThreshold The threshold which the blackborder detector should use
|
/// @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
|
/// 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
|
/// @return The detected (or not detected) black border info
|
||||||
///
|
///
|
||||||
|
|
||||||
|
uint8_t calculateThreshold(double blackborderThreshold);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// default detection mode (3lines 4side detection)
|
||||||
template <typename Pixel_T>
|
template <typename Pixel_T>
|
||||||
BlackBorder process(const Image<Pixel_T> & image)
|
BlackBorder process(const Image<Pixel_T> & image)
|
||||||
{
|
{
|
||||||
|
|
||||||
// test center and 33%, 66% of width/heigth
|
// test center and 33%, 66% of width/heigth
|
||||||
// 33 and 66 will check left and top
|
// 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 width = image.width();
|
||||||
int height = image.height();
|
int height = image.height();
|
||||||
int width33percent = width / 3;
|
int width33percent = width / 3;
|
||||||
@ -79,9 +83,9 @@ namespace hyperion
|
|||||||
int firstNonBlackYPixelIndex = -1;
|
int firstNonBlackYPixelIndex = -1;
|
||||||
|
|
||||||
// find first X pixel of the image
|
// 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 & color2 = image(x, height33percent);
|
||||||
const Pixel_T & color3 = image(x, height66percent);
|
const Pixel_T & color3 = image(x, height66percent);
|
||||||
if (!isBlack(color1) || !isBlack(color2) || !isBlack(color3))
|
if (!isBlack(color1) || !isBlack(color2) || !isBlack(color3))
|
||||||
@ -92,9 +96,9 @@ namespace hyperion
|
|||||||
}
|
}
|
||||||
|
|
||||||
// find first Y pixel of the image
|
// 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 & color2 = image(width33percent, y );
|
||||||
const Pixel_T & color3 = image(width66percent, y);
|
const Pixel_T & color3 = image(width66percent, y);
|
||||||
if (!isBlack(color1) || !isBlack(color2) || !isBlack(color3))
|
if (!isBlack(color1) || !isBlack(color2) || !isBlack(color3))
|
||||||
@ -112,6 +116,120 @@ namespace hyperion
|
|||||||
return detectedBorder;
|
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:
|
private:
|
||||||
|
|
||||||
///
|
///
|
||||||
@ -131,5 +249,6 @@ namespace hyperion
|
|||||||
private:
|
private:
|
||||||
/// Threshold for the blackborder detector [0 .. 255]
|
/// Threshold for the blackborder detector [0 .. 255]
|
||||||
const uint8_t _blackborderThreshold;
|
const uint8_t _blackborderThreshold;
|
||||||
|
|
||||||
};
|
};
|
||||||
} // end namespace hyperion
|
} // end namespace hyperion
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
// Jsoncpp includes
|
||||||
|
#include <json/json.h>
|
||||||
// Local Hyperion includes
|
// Local Hyperion includes
|
||||||
#include "BlackBorderDetector.h"
|
#include "BlackBorderDetector.h"
|
||||||
|
|
||||||
@ -23,11 +25,7 @@ namespace hyperion
|
|||||||
/// 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
|
/// @param[in] blackborderThreshold The threshold which the blackborder detector should use
|
||||||
///
|
///
|
||||||
BlackBorderProcessor(
|
BlackBorderProcessor(const Json::Value &blackborderConfig);
|
||||||
const unsigned unknownFrameCnt,
|
|
||||||
const unsigned borderFrameCnt,
|
|
||||||
const unsigned blurRemoveCnt,
|
|
||||||
uint8_t blackborderThreshold);
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Return the current (detected) border
|
/// Return the current (detected) border
|
||||||
@ -48,7 +46,14 @@ namespace hyperion
|
|||||||
bool process(const Image<Pixel_T> & image)
|
bool process(const Image<Pixel_T> & image)
|
||||||
{
|
{
|
||||||
// get the border for the single 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
|
// add blur to the border
|
||||||
if (imageBorder.horizontalSize > 0)
|
if (imageBorder.horizontalSize > 0)
|
||||||
{
|
{
|
||||||
@ -80,9 +85,15 @@ namespace hyperion
|
|||||||
/// The number of horizontal/vertical borders detected before it becomes the current border
|
/// The number of horizontal/vertical borders detected before it becomes the current border
|
||||||
const unsigned _borderSwitchCnt;
|
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
|
/// The number of pixels to increase a detected border for removing blury pixels
|
||||||
unsigned _blurRemoveCnt;
|
unsigned _blurRemoveCnt;
|
||||||
|
|
||||||
|
/// The border detection mode
|
||||||
|
const std::string _detectionMode;
|
||||||
|
|
||||||
/// The blackborder detector
|
/// The blackborder detector
|
||||||
BlackBorderDetector _detector;
|
BlackBorderDetector _detector;
|
||||||
|
|
||||||
@ -96,5 +107,6 @@ namespace hyperion
|
|||||||
unsigned _consistentCnt;
|
unsigned _consistentCnt;
|
||||||
/// The number of frame the previous detected border NOT matched the incomming border
|
/// The number of frame the previous detected border NOT matched the incomming border
|
||||||
unsigned _inconsistentCnt;
|
unsigned _inconsistentCnt;
|
||||||
|
|
||||||
};
|
};
|
||||||
} // end namespace hyperion
|
} // end namespace hyperion
|
||||||
|
@ -106,7 +106,7 @@ private:
|
|||||||
/// @param[in] enableBlackBorderDetector Flag indicating if the blacborder detector should be enabled
|
/// @param[in] enableBlackBorderDetector Flag indicating if the blacborder detector should be enabled
|
||||||
/// @param[in] blackborderThreshold The threshold which the blackborder detector should use
|
/// @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
|
/// 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] enableBlackBorderDetector Flag indicating if the blacborder detector should be enabled
|
||||||
/// @param[in] blackborderThreshold The threshold which the blackborder detector should use
|
/// @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.
|
/// Creates a new ImageProcessor. The onwership of the processor is transferred to the caller.
|
||||||
@ -46,9 +46,6 @@ private:
|
|||||||
/// The Led-string specification
|
/// The Led-string specification
|
||||||
LedString _ledString;
|
LedString _ledString;
|
||||||
|
|
||||||
/// Flag indicating if the black border detector should be used
|
// Reference to the blackborder json configuration values
|
||||||
bool _enableBlackBorderDetector;
|
Json::Value _blackborderConfig;
|
||||||
|
|
||||||
/// Threshold for the blackborder detector [0 .. 255]
|
|
||||||
uint8_t _blackborderThreshold;
|
|
||||||
};
|
};
|
||||||
|
@ -1,11 +1,26 @@
|
|||||||
|
#include <iostream>
|
||||||
// BlackBorders includes
|
// BlackBorders includes
|
||||||
#include <blackborder/BlackBorderDetector.h>
|
#include <blackborder/BlackBorderDetector.h>
|
||||||
|
|
||||||
using namespace hyperion;
|
using namespace hyperion;
|
||||||
|
|
||||||
BlackBorderDetector::BlackBorderDetector(uint8_t blackborderThreshold) :
|
BlackBorderDetector::BlackBorderDetector(double threshold) :
|
||||||
_blackborderThreshold(blackborderThreshold)
|
_blackborderThreshold(calculateThreshold(threshold))
|
||||||
{
|
{
|
||||||
// empty
|
// 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
|
// Blackborder includes
|
||||||
#include <blackborder/BlackBorderProcessor.h>
|
#include <blackborder/BlackBorderProcessor.h>
|
||||||
|
|
||||||
|
|
||||||
using namespace hyperion;
|
using namespace hyperion;
|
||||||
|
|
||||||
BlackBorderProcessor::BlackBorderProcessor(const unsigned unknownFrameCnt,
|
BlackBorderProcessor::BlackBorderProcessor(const Json::Value &blackborderConfig) :
|
||||||
const unsigned borderFrameCnt,
|
_unknownSwitchCnt(blackborderConfig.get("unknownFrameCnt", 600).asUInt()),
|
||||||
const unsigned blurRemoveCnt,
|
_borderSwitchCnt(blackborderConfig.get("borderFrameCnt", 50).asUInt()),
|
||||||
uint8_t blackborderThreshold) :
|
_maxInconsistentCnt(blackborderConfig.get("maxInconsistentCnt", 10).asUInt()),
|
||||||
_unknownSwitchCnt(unknownFrameCnt),
|
_blurRemoveCnt(blackborderConfig.get("blurRemoveCnt", 1).asUInt()),
|
||||||
_borderSwitchCnt(borderFrameCnt),
|
_detectionMode(blackborderConfig.get("mode", "default").asString()),
|
||||||
_blurRemoveCnt(blurRemoveCnt),
|
_detector(blackborderConfig.get("threshold", 0.01).asDouble()),
|
||||||
_detector(blackborderThreshold),
|
|
||||||
_currentBorder({true, -1, -1}),
|
_currentBorder({true, -1, -1}),
|
||||||
_previousDetectedBorder({true, -1, -1}),
|
_previousDetectedBorder({true, -1, -1}),
|
||||||
_consistentCnt(0),
|
_consistentCnt(0),
|
||||||
_inconsistentCnt(10)
|
_inconsistentCnt(10)
|
||||||
{
|
{
|
||||||
|
std::cout << "DETECTION MODE:" << _detectionMode << std::endl;
|
||||||
// empty
|
// 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
|
// 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
|
// 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
|
// set the consistency counter
|
||||||
if (newDetectedBorder == _previousDetectedBorder)
|
if (newDetectedBorder == _previousDetectedBorder)
|
||||||
@ -50,7 +58,7 @@ bool BlackBorderProcessor::updateBorder(const BlackBorder & newDetectedBorder)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
++_inconsistentCnt;
|
++_inconsistentCnt;
|
||||||
if (_inconsistentCnt <= 10)// few inconsistent frames
|
if (_inconsistentCnt <= _maxInconsistentCnt)// only few inconsistent frames
|
||||||
{
|
{
|
||||||
//discard the newDetectedBorder -> keep the consistent count for previousDetectedBorder
|
//discard the newDetectedBorder -> keep the consistent count for previousDetectedBorder
|
||||||
return false;
|
return false;
|
||||||
|
@ -282,8 +282,8 @@ Hyperion::Hyperion(const Json::Value &jsonConfig) :
|
|||||||
// initialize the image processor factory
|
// initialize the image processor factory
|
||||||
ImageProcessorFactory::getInstance().init(
|
ImageProcessorFactory::getInstance().init(
|
||||||
_ledString,
|
_ledString,
|
||||||
jsonConfig["blackborderdetector"].get("enable", true).asBool(),
|
jsonConfig["blackborderdetector"]
|
||||||
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);
|
||||||
|
@ -8,10 +8,11 @@
|
|||||||
|
|
||||||
using namespace hyperion;
|
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),
|
_ledString(ledString),
|
||||||
_enableBlackBorderRemoval(enableBlackBorderDetector),
|
_enableBlackBorderRemoval(blackborderConfig.get("enable", true).asBool()),
|
||||||
_borderProcessor(new BlackBorderProcessor(600, 50, 1, blackborderThreshold)),
|
_borderProcessor(new BlackBorderProcessor(blackborderConfig) ),
|
||||||
_imageToLeds(nullptr)
|
_imageToLeds(nullptr)
|
||||||
{
|
{
|
||||||
// empty
|
// empty
|
||||||
|
@ -13,25 +13,13 @@ ImageProcessorFactory& ImageProcessorFactory::getInstance()
|
|||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageProcessorFactory::init(const LedString& ledString, bool enableBlackBorderDetector, double blackborderThreshold)
|
void ImageProcessorFactory::init(const LedString& ledString, const Json::Value & blackborderConfig)
|
||||||
{
|
{
|
||||||
_ledString = ledString;
|
_ledString = ledString;
|
||||||
_enableBlackBorderDetector = enableBlackBorderDetector;
|
_blackborderConfig = blackborderConfig;
|
||||||
|
|
||||||
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, _blackborderThreshold);
|
return new ImageProcessor(_ledString, _blackborderConfig);
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
|
|
||||||
// STL includes
|
// STL includes
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
// Linux includes
|
// Linux includes
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@ -19,27 +17,46 @@ LedDeviceAPA102::LedDeviceAPA102(const std::string& outputDevice, const unsigned
|
|||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define MIN(a,b) ((a)<(b)?(a):(b))
|
||||||
|
#define MAX(a,b) ((a)>(b)?(a):(b))
|
||||||
|
|
||||||
|
#define APA102_START_FRAME_BYTES 4
|
||||||
|
#define APA102_LED_BYTES 4
|
||||||
|
#define APA102_END_FRAME_BITS_MIN 32
|
||||||
|
#define APA102_END_FRAME_BITS(leds) MAX((((leds-1)/2)+1),APA102_END_FRAME_BITS_MIN)
|
||||||
|
#define APA102_END_FRAME_BYTES(leds) (((APA102_END_FRAME_BITS(leds)-1)/8)+1)
|
||||||
|
#define APA102_LED_HEADER 0xe0
|
||||||
|
#define APA102_LED_MAX_INTENSITY 0x1f
|
||||||
|
|
||||||
int LedDeviceAPA102::write(const std::vector<ColorRgb> &ledValues)
|
int LedDeviceAPA102::write(const std::vector<ColorRgb> &ledValues)
|
||||||
{
|
{
|
||||||
const unsigned int startFrameSize = 4;
|
const unsigned int startFrameSize = APA102_START_FRAME_BYTES;
|
||||||
const unsigned int endFrameSize = std::max<unsigned int>(((ledValues.size() + 15) / 16), 4);
|
const unsigned int ledsCount = ledValues.size() ;
|
||||||
const unsigned int mLedCount = (ledValues.size() * 4) + startFrameSize + endFrameSize;
|
const unsigned int ledsSize = ledsCount * APA102_LED_BYTES ;
|
||||||
if(_ledBuffer.size() != mLedCount){
|
const unsigned int endFrameBits = APA102_END_FRAME_BITS(ledsCount) ;
|
||||||
_ledBuffer.resize(mLedCount, 0xFF);
|
const unsigned int endFrameSize = APA102_END_FRAME_BYTES(ledsCount) ;
|
||||||
_ledBuffer[0] = 0x00;
|
const unsigned int transferSize = startFrameSize + ledsSize + endFrameSize ;
|
||||||
_ledBuffer[1] = 0x00;
|
|
||||||
_ledBuffer[2] = 0x00;
|
if(_ledBuffer.size() != transferSize){
|
||||||
_ledBuffer[3] = 0x00;
|
_ledBuffer.resize(transferSize, 0x00);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned iLed=1; iLed<=ledValues.size(); ++iLed) {
|
unsigned idx = 0, i;
|
||||||
const ColorRgb& rgb = ledValues[iLed-1];
|
for (i=0; i<APA102_START_FRAME_BYTES; i++) {
|
||||||
_ledBuffer[iLed*4] = 0xFF;
|
_ledBuffer[idx++] = 0x00 ;
|
||||||
_ledBuffer[iLed*4+1] = rgb.red;
|
|
||||||
_ledBuffer[iLed*4+2] = rgb.green;
|
|
||||||
_ledBuffer[iLed*4+3] = rgb.blue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i=0; i<ledsCount; i++) {
|
||||||
|
const ColorRgb& rgb = ledValues[i];
|
||||||
|
|
||||||
|
_ledBuffer[idx++] = APA102_LED_HEADER + APA102_LED_MAX_INTENSITY;
|
||||||
|
_ledBuffer[idx++] = rgb.red;
|
||||||
|
_ledBuffer[idx++] = rgb.green;
|
||||||
|
_ledBuffer[idx++] = rgb.blue;
|
||||||
|
}
|
||||||
|
for(i=0; i<endFrameSize; i++)
|
||||||
|
_ledBuffer[idx++] = 0x00 ;
|
||||||
|
|
||||||
return writeBytes(_ledBuffer.size(), _ledBuffer.data());
|
return writeBytes(_ledBuffer.size(), _ledBuffer.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,9 +246,10 @@ LedDevice * LedDeviceFactory::construct(const Json::Value & deviceConfig)
|
|||||||
}
|
}
|
||||||
else if (type == "fadecandy")
|
else if (type == "fadecandy")
|
||||||
{
|
{
|
||||||
const std::string host = deviceConfig.get("output", "127.0.0.1").asString();
|
const std::string host = deviceConfig.get("output", "127.0.0.1").asString();
|
||||||
const uint16_t port = deviceConfig.get("port", 7890).asInt();
|
const uint16_t port = deviceConfig.get("port", 7890).asInt();
|
||||||
device = new LedDeviceFadeCandy(host,port);
|
const uint16_t channel = deviceConfig.get("channel", 0).asInt();
|
||||||
|
device = new LedDeviceFadeCandy(host, port, channel);
|
||||||
}
|
}
|
||||||
else if (type == "tpm2")
|
else if (type == "tpm2")
|
||||||
{
|
{
|
||||||
|
@ -1,16 +1,15 @@
|
|||||||
#include "LedDeviceFadeCandy.h"
|
#include "LedDeviceFadeCandy.h"
|
||||||
|
|
||||||
static const unsigned MAX_NUM_LEDS = 512;
|
static const unsigned MAX_NUM_LEDS = 10000; // OPC can handle 21845 leds - in theory, fadecandy device should handle 10000 leds
|
||||||
static const unsigned OPC_BROADCAST = 0; // OPC broadcast channel
|
static const unsigned OPC_SET_PIXELS = 0; // OPC command codes
|
||||||
static const unsigned OPC_SET_PIXELS = 0; // OPC command codes
|
static const unsigned OPC_HEADER_SIZE = 4; // OPC header size
|
||||||
static const unsigned OPC_HEADER_SIZE = 4; // OPC header size
|
|
||||||
|
|
||||||
|
|
||||||
LedDeviceFadeCandy::LedDeviceFadeCandy(const std::string& host, const uint16_t port) :
|
LedDeviceFadeCandy::LedDeviceFadeCandy(const std::string& host, const uint16_t port, const unsigned channel) :
|
||||||
_host(host), _port(port)
|
_host(host), _port(port), _channel(channel)
|
||||||
{
|
{
|
||||||
_opc_data.resize( OPC_HEADER_SIZE );
|
_opc_data.resize( OPC_HEADER_SIZE );
|
||||||
_opc_data[0] = OPC_BROADCAST;
|
_opc_data[0] = channel;
|
||||||
_opc_data[1] = OPC_SET_PIXELS;
|
_opc_data[1] = OPC_SET_PIXELS;
|
||||||
_opc_data[2] = 0;
|
_opc_data[2] = 0;
|
||||||
_opc_data[3] = 0;
|
_opc_data[3] = 0;
|
||||||
@ -32,11 +31,9 @@ bool LedDeviceFadeCandy::isConnected()
|
|||||||
bool LedDeviceFadeCandy::tryConnect()
|
bool LedDeviceFadeCandy::tryConnect()
|
||||||
{
|
{
|
||||||
if ( _client.state() == QAbstractSocket::UnconnectedState ) {
|
if ( _client.state() == QAbstractSocket::UnconnectedState ) {
|
||||||
qDebug("connecting to %s %i",_host.c_str(),_port);
|
|
||||||
|
|
||||||
_client.connectToHost( _host.c_str(), _port);
|
_client.connectToHost( _host.c_str(), _port);
|
||||||
if ( _client.waitForConnected(1000) )
|
if ( _client.waitForConnected(1000) )
|
||||||
qDebug("connected");
|
qDebug("fadecandy/opc: connected to %s:%i on channel %i", _host.c_str(), _port, _channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
return isConnected();
|
return isConnected();
|
||||||
@ -51,7 +48,7 @@ int LedDeviceFadeCandy::write( const std::vector<ColorRgb> & ledValues )
|
|||||||
|
|
||||||
if (nrLedValues > MAX_NUM_LEDS)
|
if (nrLedValues > MAX_NUM_LEDS)
|
||||||
{
|
{
|
||||||
std::cerr << "Invalid attempt to write led values. Not more than " << MAX_NUM_LEDS << " leds are allowed." << std::endl;
|
std::cerr << "fadecandy/opc: Invalid attempt to write led values. Not more than " << MAX_NUM_LEDS << " leds are allowed." << std::endl;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ public:
|
|||||||
/// @param host The ip address/host name of fadecandy/opc server
|
/// @param host The ip address/host name of fadecandy/opc server
|
||||||
/// @param port The port to use (fadecandy default is 7890)
|
/// @param port The port to use (fadecandy default is 7890)
|
||||||
///
|
///
|
||||||
LedDeviceFadeCandy(const std::string& host, const uint16_t port);
|
LedDeviceFadeCandy(const std::string& host, const uint16_t port, const unsigned channel);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Destructor of the LedDevice; closes the tcp client
|
/// Destructor of the LedDevice; closes the tcp client
|
||||||
@ -46,6 +46,7 @@ private:
|
|||||||
QTcpSocket _client;
|
QTcpSocket _client;
|
||||||
const std::string _host;
|
const std::string _host;
|
||||||
const uint16_t _port;
|
const uint16_t _port;
|
||||||
|
const unsigned _channel;
|
||||||
QByteArray _opc_data;
|
QByteArray _opc_data;
|
||||||
|
|
||||||
/// try to establish connection to opc server, if not connected yet
|
/// try to establish connection to opc server, if not connected yet
|
||||||
|
@ -218,7 +218,7 @@ void LedDevicePhilipsHue::put(QString route, QString content) {
|
|||||||
QString url = QString("http://%1/api/%2/%3").arg(host).arg(username).arg(route);
|
QString url = QString("http://%1/api/%2/%3").arg(host).arg(username).arg(route);
|
||||||
// Perfrom request
|
// Perfrom request
|
||||||
QNetworkRequest request(url);
|
QNetworkRequest request(url);
|
||||||
QNetworkReply* reply = manager->put(request, content.toAscii());
|
QNetworkReply* reply = manager->put(request, content.toLatin1());
|
||||||
// Connect finished signal to quit slot of the loop.
|
// Connect finished signal to quit slot of the loop.
|
||||||
QEventLoop loop;
|
QEventLoop loop;
|
||||||
loop.connect(reply, SIGNAL(finished()), SLOT(quit()));
|
loop.connect(reply, SIGNAL(finished()), SLOT(quit()));
|
||||||
|
@ -126,20 +126,34 @@ int main(int argc, char** argv)
|
|||||||
// Get the parameters for the bootsequence
|
// Get the parameters for the bootsequence
|
||||||
const std::string effectName = effectConfig["effect"].asString();
|
const std::string effectName = effectConfig["effect"].asString();
|
||||||
const unsigned duration_ms = effectConfig["duration_ms"].asUInt();
|
const unsigned duration_ms = effectConfig["duration_ms"].asUInt();
|
||||||
const int priority = 0;
|
const int priority = effectConfig["priority"].asUInt();
|
||||||
|
const int bootcolor_priority = (priority > 990) ? priority+1 : 990;
|
||||||
|
|
||||||
hyperion.setColor(priority+1, ColorRgb::BLACK, duration_ms, false);
|
if ( ! effectConfig["color"].isNull() && effectConfig["color"].isArray() && effectConfig["color"].size() == 3 )
|
||||||
|
{
|
||||||
|
ColorRgb boot_color = {
|
||||||
|
(uint8_t)effectConfig["color"][0].asUInt(),
|
||||||
|
(uint8_t)effectConfig["color"][1].asUInt(),
|
||||||
|
(uint8_t)effectConfig["color"][2].asUInt()
|
||||||
|
};
|
||||||
|
|
||||||
|
hyperion.setColor(bootcolor_priority, boot_color, 0, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hyperion.setColor(bootcolor_priority, ColorRgb::BLACK, duration_ms, false);
|
||||||
|
}
|
||||||
|
|
||||||
if (effectConfig.isMember("args"))
|
if (effectConfig.isMember("args"))
|
||||||
{
|
{
|
||||||
const Json::Value effectConfigArgs = effectConfig["args"];
|
const Json::Value effectConfigArgs = effectConfig["args"];
|
||||||
if (hyperion.setEffect(effectName, effectConfigArgs, priority, duration_ms) == 0)
|
if (hyperion.setEffect(effectName, effectConfigArgs, priority, duration_ms) == 0)
|
||||||
{
|
{
|
||||||
std::cout << "Boot sequence(" << effectName << ") with user-defined arguments created and started" << std::endl;
|
std::cout << "Boot sequence(" << effectName << ") with user-defined arguments created and started" << std::endl;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::cout << "Failed to start boot sequence: " << effectName << " with user-defined arguments" << std::endl;
|
std::cout << "Failed to start boot sequence: " << effectName << " with user-defined arguments" << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -44,11 +44,13 @@ Image<ColorRgb> createImage(unsigned width, unsigned height, unsigned topBorder,
|
|||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
unsigned unknownCnt = 600;
|
// unsigned unknownCnt = 600;
|
||||||
unsigned borderCnt = 50;
|
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
|
// Start with 'no border' detection
|
||||||
Image<ColorRgb> noBorderImage = createImage(64, 64, 0, 0);
|
Image<ColorRgb> noBorderImage = createImage(64, 64, 0, 0);
|
||||||
|
Loading…
Reference in New Issue
Block a user