Skip to content

Commit 1ae37d1

Browse files
authored
Dominant Color support (#1569)
* Dominant Color and Mean Color Squared * Workaround - Suppress empty LED updates * Add missing text * Dominant Colors advanced * Test with fixed initial colors * Test with fixed initial colors * Support new processing values via API * ImageToLED - Add reduced pixel processing, make dominant color advanced configurable * Updates on Grabber fps setting * ImageToLedMap - Remove maptype and update test * Update dynamic cluster array allocation
1 parent 093361d commit 1ae37d1

File tree

16 files changed

+1041
-148
lines changed

16 files changed

+1041
-148
lines changed

assets/webconfig/i18n/en.json

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,8 @@
253253
"edt_conf_bb_unknownFrameCnt_title": "Unknown frames",
254254
"edt_conf_bge_heading_title": "Background Effect/Color",
255255
"edt_conf_bobls_heading_title": "Boblight Server",
256+
"edt_conf_color_accuracyLevel_expl": "Level how accurate dominat colors are evaluated. A higher level creates more accurate results, but also requries more processing power. Should to be combined with reduced pixel processing.",
257+
"edt_conf_color_accuracyLevel_title": "Accuracy level",
256258
"edt_conf_color_backlightColored_expl": "Add some color to your backlight.",
257259
"edt_conf_color_backlightColored_title": "Colored backlight",
258260
"edt_conf_color_backlightThreshold_expl": "The minimum amount of brightness (backlight). Disabled during effects, colors and in status \"Off\"",
@@ -281,7 +283,7 @@
281283
"edt_conf_color_heading_title": "Color Calibration",
282284
"edt_conf_color_id_expl": "User given name",
283285
"edt_conf_color_id_title": "ID",
284-
"edt_conf_color_imageToLedMappingType_expl": "Overwrites the LED area assignment of your LED layout if it's not \"multicolor\"",
286+
"edt_conf_color_imageToLedMappingType_expl": "Overwrites the LED area assignment of your LED layout if it's not \"Mean Color Simple\"",
285287
"edt_conf_color_imageToLedMappingType_title": "LED area assignment",
286288
"edt_conf_color_leds_expl": "Assign this adjustment to all LEDs (*) or just some (0-24).",
287289
"edt_conf_color_leds_title": "LED index",
@@ -293,6 +295,8 @@
293295
"edt_conf_color_saturationGain_title": "Saturation gain",
294296
"edt_conf_color_brightnessGain_expl": "Adjusts the brightness of colors. 1.0 means no change, over 1.0 increases brightness, under 1.0 decreases brightness.",
295297
"edt_conf_color_brightnessGain_title": "Brightness gain",
298+
"edt_conf_color_reducedPixelSetFactorFactor_expl": "Evaluate only a set of pixels per LED area defined, Low ~25%, Medium ~10%, High ~6%",
299+
"edt_conf_color_reducedPixelSetFactorFactor_title": "Reduced pixel processing",
296300
"edt_conf_color_white_expl": "The calibrated white value.",
297301
"edt_conf_color_white_title": "White",
298302
"edt_conf_color_yellow_expl": "The calibrated yellow value.",
@@ -322,6 +326,8 @@
322326
"edt_conf_enum_color": "Color",
323327
"edt_conf_enum_custom": "Custom",
324328
"edt_conf_enum_decay": "Decay",
329+
"edt_conf_enum_delay": "Delay only",
330+
"edt_conf_enum_disabled": "Disabled",
325331
"edt_conf_enum_dl_error": "Error",
326332
"edt_conf_enum_dl_informational": "Informational",
327333
"edt_conf_enum_dl_nodebug": "No Debug output",
@@ -330,17 +336,23 @@
330336
"edt_conf_enum_dl_verbose1": "Verbosity level 1",
331337
"edt_conf_enum_dl_verbose2": "Verbosity level 2",
332338
"edt_conf_enum_dl_verbose3": "Verbosity level 3",
339+
"edt_conf_enum_dominant_color": "Dominant Color - per LED",
340+
"edt_conf_enum_dominant_color_advanced": "Dominant Color Advanced - per LED",
333341
"edt_conf_enum_effect": "Effect",
334342
"edt_conf_enum_gbr": "GBR",
335343
"edt_conf_enum_grb": "GRB",
344+
"edt_conf_enum_high": "High",
336345
"edt_conf_enum_hsv": "HSV",
337346
"edt_conf_enum_left_right": "Left to right",
338347
"edt_conf_enum_linear": "Linear",
339348
"edt_conf_enum_logdebug": "Debug",
340349
"edt_conf_enum_logsilent": "Silent",
341350
"edt_conf_enum_logverbose": "Verbose",
342351
"edt_conf_enum_logwarn": "Warning",
343-
"edt_conf_enum_multicolor_mean": "Multicolor",
352+
"edt_conf_enum_low": "Low",
353+
"edt_conf_enum_medium": "Medium",
354+
"edt_conf_enum_multicolor_mean": "Mean Color Simple - per LED",
355+
"edt_conf_enum_multicolor_mean_squared": "Mean Color Squared - per LED",
344356
"edt_conf_enum_please_select": "Please Select",
345357
"edt_conf_enum_rbg": "RBG",
346358
"edt_conf_enum_rgb": "RGB",
@@ -350,7 +362,7 @@
350362
"edt_conf_enum_transeffect_sudden": "Sudden",
351363
"edt_conf_enum_udp_ddp": "DDP",
352364
"edt_conf_enum_udp_raw": "RAW",
353-
"edt_conf_enum_unicolor_mean": "Unicolor",
365+
"edt_conf_enum_unicolor_mean": "Mean Color Image - applied to all LEDs",
354366
"edt_conf_fbs_heading_title": "Flatbuffers Server",
355367
"edt_conf_fbs_timeout_expl": "If no data is received for the given period, the component will be (soft) disabled.",
356368
"edt_conf_fbs_timeout_title": "Timeout",
@@ -974,8 +986,11 @@
974986
"remote_losthint": "Note: All changes will be lost after a restart.",
975987
"remote_maptype_intro": "Usually the LED layout defines which LED covers a specific picture area. You can change it here: $1.",
976988
"remote_maptype_label": "Mapping type",
977-
"remote_maptype_label_multicolor_mean": "Multicolor",
978-
"remote_maptype_label_unicolor_mean": "Unicolor",
989+
"remote_maptype_label_dominant_color": "Dominant Color",
990+
"remote_maptype_label_dominant_color_advanced": "Dominant Color Advanced",
991+
"remote_maptype_label_multicolor_mean": "Mean Color Simple",
992+
"remote_maptype_label_multicolor_mean_squared": "Mean Color Squared",
993+
"remote_maptype_label_unicolor_mean": "Mean Color Image",
979994
"remote_optgroup_syseffets": "System Effects",
980995
"remote_optgroup_templates_custom": "User Templates",
981996
"remote_optgroup_templates_system": "System Templates",

include/hyperion/GrabberWrapper.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -147,10 +147,7 @@ private slots:
147147
void handleSourceRequest(hyperion::Components component, int hyperionInd, bool listen);
148148

149149
///
150-
/// @brief Update Update capture rate
151-
/// @param type interval between frames in milliseconds
152-
///
153-
void updateTimer(int interval);
150+
154151

155152
protected:
156153

@@ -168,6 +165,11 @@ private slots:
168165
///
169166
virtual bool close() { return true; }
170167

168+
/// @brief Update Update capture rate
169+
/// @param type interval between frames in milliseconds
170+
///
171+
void updateTimer(int interval);
172+
171173

172174
QString _grabberName;
173175

include/hyperion/ImageProcessor.h

Lines changed: 71 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#pragma once
22

33
#include <QString>
4+
#include <QSharedPointer>
45

56
// Utils includes
67
#include <utils/Image.h>
@@ -46,7 +47,7 @@ class ImageProcessor : public QObject
4647
/// @param[in] width The new width of the buffer-image
4748
/// @param[in] height The new height of the buffer-image
4849
///
49-
void setSize(unsigned width, unsigned height);
50+
void setSize(int width, int height);
5051

5152
///
5253
/// @brief Update the led string (eg on settings change)
@@ -56,6 +57,19 @@ class ImageProcessor : public QObject
5657
/// Returns state of black border detector
5758
bool blackBorderDetectorEnabled() const;
5859

60+
///
61+
/// Factor to reduce the number of pixels evaluated during processing
62+
///
63+
/// @param[in] count Use every "count" pixel
64+
void setReducedPixelSetFactorFactor(int count);
65+
66+
///
67+
/// Set the accuracy used during processing
68+
/// (only for selected types)
69+
///
70+
/// @param[in] level The accuracy level (0-4)
71+
void setAccuracyLevel(int level);
72+
5973
/// Returns the current _userMappingType, this may not be the current applied type!
6074
int getUserLedMappingType() const { return _userMappingType; }
6175

@@ -98,30 +112,45 @@ public slots:
98112
}
99113

100114
///
101-
/// Processes the image to a list of led colors. This will update the size of the buffer-image
102-
/// if required and call the image-to-leds mapping to determine the mean color per led.
115+
/// Processes the image to a list of LED colors. This will update the size of the buffer-image
116+
/// if required and call the image-to-LEDs mapping to determine the color per LED.
103117
///
104-
/// @param[in] image The image to translate to led values
118+
/// @param[in] image The image to translate to LED values
105119
///
106-
/// @return The color value per led
120+
/// @return The color value per LED
107121
///
108122
template <typename Pixel_T>
109123
std::vector<ColorRgb> process(const Image<Pixel_T>& image)
110124
{
111125
std::vector<ColorRgb> colors;
126+
112127
if (image.width()>0 && image.height()>0)
113128
{
114129
// Ensure that the buffer-image is the proper size
115130
setSize(image);
116131

132+
assert(!_imageToLedColors.isNull());
133+
117134
// Check black border detection
118135
verifyBorder(image);
119136

120137
// Create a result vector and call the 'in place' function
121138
switch (_mappingType)
122139
{
123-
case 1: colors = _imageToLeds->getUniLedColor(image); break;
124-
default: colors = _imageToLeds->getMeanLedColor(image);
140+
case 1:
141+
colors = _imageToLedColors->getUniLedColor(image);
142+
break;
143+
case 2:
144+
colors = _imageToLedColors->getMeanLedColorSqrt(image);
145+
break;
146+
case 3:
147+
colors = _imageToLedColors->getDominantLedColor(image);
148+
break;
149+
case 4:
150+
colors = _imageToLedColors->getDominantLedColorAdv(image);
151+
break;
152+
default:
153+
colors = _imageToLedColors->getMeanLedColor(image);
125154
}
126155
}
127156
else
@@ -136,8 +165,8 @@ public slots:
136165
///
137166
/// Determines the led colors of the image in the buffer.
138167
///
139-
/// @param[in] image The image to translate to led values
140-
/// @param[out] ledColors The color value per led
168+
/// @param[in] image The image to translate to LED values
169+
/// @param[out] ledColors The color value per LED
141170
///
142171
template <typename Pixel_T>
143172
void process(const Image<Pixel_T>& image, std::vector<ColorRgb>& ledColors)
@@ -153,8 +182,20 @@ public slots:
153182
// Determine the mean or uni colors of each led (using the existing mapping)
154183
switch (_mappingType)
155184
{
156-
case 1: _imageToLeds->getUniLedColor(image, ledColors); break;
157-
default: _imageToLeds->getMeanLedColor(image, ledColors);
185+
case 1:
186+
_imageToLedColors->getUniLedColor(image, ledColors);
187+
break;
188+
case 2:
189+
_imageToLedColors->getMeanLedColorSqrt(image, ledColors);
190+
break;
191+
case 3:
192+
_imageToLedColors->getDominantLedColor(image, ledColors);
193+
break;
194+
case 4:
195+
_imageToLedColors->getDominantLedColorAdv(image, ledColors);
196+
break;
197+
default:
198+
_imageToLedColors->getMeanLedColor(image, ledColors);
158199
}
159200
}
160201
else
@@ -164,9 +205,9 @@ public slots:
164205
}
165206

166207
///
167-
/// Get the hscan and vscan parameters for a single led
208+
/// Get the hscan and vscan parameters for a single LED
168209
///
169-
/// @param[in] led Index of the led
210+
/// @param[in] led Index of the LED
170211
/// @param[out] hscanBegin begin of the hscan
171212
/// @param[out] hscanEnd end of the hscan
172213
/// @param[out] vscanBegin begin of the hscan
@@ -175,6 +216,13 @@ public slots:
175216
bool getScanParameters(size_t led, double & hscanBegin, double & hscanEnd, double & vscanBegin, double & vscanEnd) const;
176217

177218
private:
219+
220+
void registerProcessingUnit(
221+
int width,
222+
int height,
223+
int horizontalBorder,
224+
int verticalBorder);
225+
178226
///
179227
/// Performs black-border detection (if enabled) on the given image
180228
///
@@ -183,41 +231,33 @@ public slots:
183231
template <typename Pixel_T>
184232
void verifyBorder(const Image<Pixel_T> & image)
185233
{
186-
if (!_borderProcessor->enabled() && ( _imageToLeds->horizontalBorder()!=0 || _imageToLeds->verticalBorder()!=0 ))
234+
if (!_borderProcessor->enabled() && ( _imageToLedColors->horizontalBorder()!=0 || _imageToLedColors->verticalBorder()!=0 ))
187235
{
188236
Debug(_log, "Reset border");
189237
_borderProcessor->process(image);
190-
delete _imageToLeds;
191-
_imageToLeds = new hyperion::ImageToLedsMap(image.width(), image.height(), 0, 0, _ledString.leds());
238+
registerProcessingUnit(image.width(), image.height(), 0, 0);
192239
}
193240

194241
if(_borderProcessor->enabled() && _borderProcessor->process(image))
195242
{
196243
const hyperion::BlackBorder border = _borderProcessor->getCurrentBorder();
197244

198-
// Clean up the old mapping
199-
delete _imageToLeds;
200-
201245
if (border.unknown)
202246
{
203-
// Construct a new buffer and mapping
204-
_imageToLeds = new hyperion::ImageToLedsMap(image.width(), image.height(), 0, 0, _ledString.leds());
247+
registerProcessingUnit(image.width(), image.height(), 0, 0);
205248
}
206249
else
207250
{
208-
// Construct a new buffer and mapping
209-
_imageToLeds = new hyperion::ImageToLedsMap(image.width(), image.height(), border.horizontalSize, border.verticalSize, _ledString.leds());
251+
registerProcessingUnit(image.width(), image.height(), border.horizontalSize, border.verticalSize);
210252
}
211-
212-
//Debug(Logger::getInstance("BLACKBORDER"), "CURRENT BORDER TYPE: unknown=%d hor.size=%d vert.size=%d",
213-
// border.unknown, border.horizontalSize, border.verticalSize );
214253
}
215254
}
216255

217256
private slots:
218257
void handleSettingsUpdate(settings::type type, const QJsonDocument& config);
219258

220259
private:
260+
221261
Logger * _log;
222262
/// The Led-string specification
223263
LedString _ledString;
@@ -226,15 +266,18 @@ private slots:
226266
hyperion::BlackBorderProcessor * _borderProcessor;
227267

228268
/// The mapping of image-pixels to LEDs
229-
hyperion::ImageToLedsMap* _imageToLeds;
269+
QSharedPointer<hyperion::ImageToLedsMap> _imageToLedColors;
230270

231-
/// Type of image 2 led mapping
271+
/// Type of image to LED mapping
232272
int _mappingType;
233273
/// Type of last requested user type
234274
int _userMappingType;
235275
/// Type of last requested hard type
236276
int _hardMappingType;
237277

278+
int _accuraryLevel;
279+
int _reducedPixelSetFactorFactor;
280+
238281
/// Hyperion instance pointer
239282
Hyperion* _hyperion;
240283
};

0 commit comments

Comments
 (0)