diff --git a/libsrc/jsonserver/JsonSchemas.qrc b/libsrc/jsonserver/JsonSchemas.qrc
index 1e5c00eb..c9575da5 100644
--- a/libsrc/jsonserver/JsonSchemas.qrc
+++ b/libsrc/jsonserver/JsonSchemas.qrc
@@ -7,8 +7,6 @@
schema/schema-clear.json
schema/schema-clearall.json
schema/schema-transform.json
- schema/schema-correction.json
- schema/schema-temperature.json
schema/schema-adjustment.json
schema/schema-effect.json
schema/schema-create-effect.json
diff --git a/libsrc/jsonserver/schema/schema-correction.json b/libsrc/jsonserver/schema/schema-correction.json
deleted file mode 100644
index b3f92e40..00000000
--- a/libsrc/jsonserver/schema/schema-correction.json
+++ /dev/null
@@ -1,37 +0,0 @@
-{
- "type":"object",
- "required":true,
- "properties":{
- "command": {
- "type" : "string",
- "required" : true,
- "enum" : ["correction"]
- },
- "tan" : {
- "type" : "integer"
- },
- "correction": {
- "type": "object",
- "required": true,
- "properties": {
- "id" : {
- "type" : "string",
- "required" : false
- },
- "correctionValues" : {
- "type": "array",
- "required": false,
- "items" : {
- "type": "integer",
- "minimum": 0,
- "maximum": 255
- },
- "minItems": 3,
- "maxItems": 3
- }
- },
- "additionalProperties": false
- }
- },
- "additionalProperties": false
-}
diff --git a/libsrc/jsonserver/schema/schema-temperature.json b/libsrc/jsonserver/schema/schema-temperature.json
deleted file mode 100644
index 8af7f6d7..00000000
--- a/libsrc/jsonserver/schema/schema-temperature.json
+++ /dev/null
@@ -1,37 +0,0 @@
-{
- "type":"object",
- "required":true,
- "properties":{
- "command": {
- "type" : "string",
- "required" : true,
- "enum" : ["temperature"]
- },
- "tan" : {
- "type" : "integer"
- },
- "temperature": {
- "type": "object",
- "required": true,
- "properties": {
- "id" : {
- "type" : "string",
- "required" : false
- },
- "correctionValues" : {
- "type": "array",
- "required": false,
- "items" : {
- "type": "integer",
- "minimum": 0,
- "maximum": 255
- },
- "minItems": 3,
- "maxItems": 3
- }
- },
- "additionalProperties": false
- }
- },
- "additionalProperties": false
-}
diff --git a/libsrc/jsonserver/schema/schema.json b/libsrc/jsonserver/schema/schema.json
index 740f34e7..fdeb9f93 100644
--- a/libsrc/jsonserver/schema/schema.json
+++ b/libsrc/jsonserver/schema/schema.json
@@ -5,7 +5,7 @@
"command": {
"type" : "string",
"required" : true,
- "enum" : ["color", "image", "effect", "create-effect", "delete-effect", "serverinfo", "clear", "clearall", "transform", "correction", "temperature", "adjustment", "sourceselect", "config", "componentstate", "ledcolors", "logging"]
+ "enum" : ["color", "image", "effect", "create-effect", "delete-effect", "serverinfo", "clear", "clearall", "transform", "adjustment", "sourceselect", "config", "componentstate", "ledcolors", "logging"]
}
}
}
diff --git a/libsrc/utils/HslTransform.cpp b/libsrc/utils/HslTransform.cpp
index 535e1676..33af7561 100644
--- a/libsrc/utils/HslTransform.cpp
+++ b/libsrc/utils/HslTransform.cpp
@@ -2,10 +2,10 @@
#include
#include
-HslTransform::HslTransform() :
- _saturationGain(1.0),
- _luminanceGain(1.0),
- _luminanceMinimum(0.0)
+HslTransform::HslTransform()
+ : _saturationGain(1.0)
+ , _luminanceGain(1.0)
+ , _luminanceMinimum(0.0)
{
}
@@ -57,12 +57,9 @@ void HslTransform::transform(uint8_t & red, uint8_t & green, uint8_t & blue) con
uint16_t hue;
float saturation, luminance;
rgb2hsl(red, green, blue, hue, saturation, luminance);
-
+
float s = saturation * _saturationGain;
- if (s > 1.0f)
- saturation = 1.0f;
- else
- saturation = s;
+ saturation = std::min(s, 1.0f);
float l = luminance * _luminanceGain;
if (l < _luminanceMinimum)
@@ -70,39 +67,36 @@ void HslTransform::transform(uint8_t & red, uint8_t & green, uint8_t & blue) con
saturation = 0;
l = _luminanceMinimum;
}
- if (l > 1.0f)
- luminance = 1.0f;
- else
- luminance = l;
-
+ luminance = std::min(l, 1.0f);
+
hsl2rgb(hue, saturation, luminance, red, green, blue);
}
}
void HslTransform::rgb2hsl(uint8_t red, uint8_t green, uint8_t blue, uint16_t & hue, float & saturation, float & luminance)
{
- float r = red / 255.0f;
- float g = green / 255.0f;
- float b = blue / 255.0f;
+ float r = (float)red / 255.0f;
+ float g = (float)green / 255.0f;
+ float b = (float)blue / 255.0f;
- float rgbMin = r < g ? (r < b ? r : b) : (g < b ? g : b);
- float rgbMax = r > g ? (r > b ? r : b) : (g > b ? g : b);
+ float rgbMin = std::min(r,std::min(g,b));
+ float rgbMax = std::max(r,std::max(g,b));
float diff = rgbMax - rgbMin;
//luminance
luminance = (rgbMin + rgbMax) / 2.0f;
- if (diff == 0.0f) {
+ if (diff == 0.0f)
+ {
saturation = 0.0f;
- hue = 0;
+ hue = 0;
return;
- }
+ }
//saturation
- if (luminance < 0.5f)
- saturation = diff / (rgbMin + rgbMax);
- else
- saturation = diff / (2.0f - rgbMin - rgbMax);
+ saturation = (luminance < 0.5f)
+ ? (diff / (rgbMin + rgbMax))
+ : (diff / (2.0f - rgbMin - rgbMax));
if (rgbMax == r)
{
@@ -125,30 +119,29 @@ void HslTransform::rgb2hsl(uint8_t red, uint8_t green, uint8_t blue, uint16_t &
void HslTransform::hsl2rgb(uint16_t hue, float saturation, float luminance, uint8_t & red, uint8_t & green, uint8_t & blue)
{
- if (saturation == 0.0f){
- red = (uint8_t)(luminance * 255.0f);
+ if (saturation == 0.0f)
+ {
+ red = (uint8_t)(luminance * 255.0f);
green = (uint8_t)(luminance * 255.0f);
- blue = (uint8_t)(luminance * 255.0f);
+ blue = (uint8_t)(luminance * 255.0f);
return;
}
-
- float q;
-
- if (luminance < 0.5f)
- q = luminance * (1.0f + saturation);
- else
- q = (luminance + saturation) - (luminance * saturation);
-
+
+ float q = (luminance < 0.5f)
+ ? luminance * (1.0f + saturation)
+ : (luminance + saturation) - (luminance * saturation);
+
float p = (2.0f * luminance) - q;
float h = hue / 360.0f;
-
+
float t[3];
t[0] = h + (1.0f / 3.0f);
t[1] = h;
t[2] = h - (1.0f / 3.0f);
- for (int i = 0; i < 3; i++) {
+ for (int i = 0; i < 3; i++)
+ {
if (t[i] < 0.0f)
t[i] += 1.0f;
if (t[i] > 1.0f)
@@ -157,7 +150,8 @@ void HslTransform::hsl2rgb(uint16_t hue, float saturation, float luminance, uint
float out[3];
- for (int i = 0; i < 3; i++) {
+ for (int i = 0; i < 3; i++)
+ {
if (t[i] * 6.0f < 1.0f)
out[i] = p + (q - p) * 6.0f * t[i];
else if (t[i] * 2.0f < 1.0f)
@@ -168,8 +162,8 @@ void HslTransform::hsl2rgb(uint16_t hue, float saturation, float luminance, uint
}
//convert back to 0...255 range
- red = (uint8_t)(out[0] * 255.0f);
+ red = (uint8_t)(out[0] * 255.0f);
green = (uint8_t)(out[1] * 255.0f);
- blue = (uint8_t)(out[2] * 255.0f);
+ blue = (uint8_t)(out[2] * 255.0f);
}
diff --git a/libsrc/utils/HsvTransform.cpp b/libsrc/utils/HsvTransform.cpp
index 14554fa9..8ff2ae7b 100644
--- a/libsrc/utils/HsvTransform.cpp
+++ b/libsrc/utils/HsvTransform.cpp
@@ -1,9 +1,9 @@
#include
#include
-HsvTransform::HsvTransform() :
- _saturationGain(1.0),
- _valueGain(1.0)
+HsvTransform::HsvTransform()
+ : _saturationGain(1.0)
+ , _valueGain(1.0)
{
}
diff --git a/src/hyperion-v4l2/ScreenshotHandler.cpp b/src/hyperion-v4l2/ScreenshotHandler.cpp
index e006fca9..d12f9479 100644
--- a/src/hyperion-v4l2/ScreenshotHandler.cpp
+++ b/src/hyperion-v4l2/ScreenshotHandler.cpp
@@ -1,6 +1,8 @@
// Qt includes
#include
#include
+#include
+#include
// hyperion-v4l2 includes
#include "ScreenshotHandler.h"
@@ -17,41 +19,7 @@ ScreenshotHandler::~ScreenshotHandler()
void ScreenshotHandler::receiveImage(const Image & image)
{
- double x_frac_min = _signalDetectionOffset.x();
- double y_frac_min = _signalDetectionOffset.y();
- double x_frac_max = _signalDetectionOffset.width();
- double y_frac_max = _signalDetectionOffset.height();
-
- int xOffset = image.width() * x_frac_min;
- int yOffset = image.height() * y_frac_min;
- int xMax = image.width() * x_frac_max;
- int yMax = image.height() * y_frac_max;
-
- std::cout << std::endl << "Screenshot details"
- << std::endl << "=================="
- << std::endl << "dimension after decimation: " << image.width() << " x " << image.height()
- << std::endl << "signal detection area : " << xOffset << "," << yOffset << " x " << xMax << "," << yMax << std::endl;
-
- ColorRgb noSignalThresholdColor = {0,0,0};
-
- for (unsigned x = 0; x < (image.width()>>1); ++x)
- {
- int xImage = (image.width()>>2) + x;
-
- for (unsigned y = 0; y < (image.height()>>1); ++y)
- {
- int yImage = (image.height()>>2) + y;
-
- ColorRgb rgb = image(xImage, yImage);
- if (rgb > noSignalThresholdColor)
- {
- noSignalThresholdColor = rgb;
- }
- }
- }
- std::cout << "signal threshold color : " << noSignalThresholdColor << std::endl;
- std::cout << "signal threshold values: " << (float)noSignalThresholdColor.red/255.0f << ", "<< (float)noSignalThresholdColor.green/255.0f << ", " << (float)noSignalThresholdColor.blue/255.0f << std::endl;
-
+ findNoSignalSettings(image);
// store as PNG
QImage pngImage((const uint8_t *) image.memptr(), image.width(), image.height(), 3*image.width(), QImage::Format_RGB888);
pngImage.save(_filename);
@@ -59,3 +27,220 @@ void ScreenshotHandler::receiveImage(const Image & image)
// Quit the application after the first image
QCoreApplication::quit();
}
+
+bool ScreenshotHandler::findNoSignalSettings(const Image & image)
+{
+ double x_frac_min = _signalDetectionOffset.x();
+ double y_frac_min = _signalDetectionOffset.y();
+ double x_frac_max = _signalDetectionOffset.width();
+ double y_frac_max = _signalDetectionOffset.height();
+
+ unsigned xOffset = image.width() * x_frac_min;
+ unsigned yOffset = image.height() * y_frac_min;
+ unsigned xMax = image.width() * x_frac_max;
+ unsigned yMax = image.height() * y_frac_max;
+
+ ColorRgb noSignalThresholdColor = {0,0,0};
+
+ unsigned yMid = (yMax+yOffset) / 2;
+ ColorRgb redThresoldColor = {255,75,75};
+ ColorRgb greenThresoldColor = {75,255,75};
+ ColorRgb blueThresoldColor = {75,75,255};
+
+ QVector redOffsets;
+ QVector redCounts;
+ QVector greenOffsets;
+ QVector greenCounts;
+ QVector blueOffsets;
+ QVector blueCounts;
+
+ unsigned currentColor = 255;
+ for (unsigned x = xOffset; x < xMax; ++x)
+ {
+ ColorRgb rgb = image(x, yMid);
+ if (rgb <= redThresoldColor)
+ {
+ if ( currentColor != 0)
+ {
+ redOffsets.append(x);
+ redCounts.append(1);
+ }
+ else
+ {
+ redCounts[redCounts.size()-1]++;
+ }
+ currentColor = 0;
+ }
+ if (rgb <= greenThresoldColor){
+ if ( currentColor != 1)
+ {
+ greenOffsets.append(x);
+ greenCounts.append(1);
+ }
+ else
+ {
+ greenCounts[greenCounts.size()-1]++;
+ }
+ currentColor = 1;
+ }
+ if (rgb <= blueThresoldColor)
+ {
+ if ( currentColor != 2)
+ {
+ blueOffsets.append(x);
+ blueCounts.append(1);
+ }
+ else
+ {
+ blueCounts[blueCounts.size()-1]++;
+ }
+ currentColor = 2;
+ }
+ }
+
+ auto itR = std::max_element(std::begin(redCounts), std::end(redCounts));
+ auto itG = std::max_element(std::begin(greenCounts), std::end(greenCounts));
+ auto itB = std::max_element(std::begin(blueCounts), std::end(blueCounts));
+
+ //std::cout << *itR << " " << *itG << " " << *itB << std::endl;
+ double xOffsetSuggested = xOffset;
+ double yOffsetSuggested = yOffset;
+ double xMaxSuggested = xMax;
+ double yMaxSuggested = yMax;
+ bool noSignalBlack = false;
+
+ noSignalThresholdColor = {0,0,0};
+ if (*itR >= *itG && *itR >= *itB && *itR > 1)
+ {
+ xOffsetSuggested = redOffsets[redCounts.indexOf(*itR)];
+ xMaxSuggested = xOffsetSuggested + *itR;
+ noSignalThresholdColor = redThresoldColor;
+ }
+ else if (*itG >= *itR && *itG >= *itB && *itG > 1 )
+ {
+ xOffsetSuggested = greenOffsets[greenCounts.indexOf(*itG)];
+ xMaxSuggested = xOffsetSuggested + *itG;
+ noSignalThresholdColor = greenThresoldColor;
+ }
+ else if ( *itB > 1 )
+ {
+ xOffsetSuggested = blueOffsets[blueCounts.indexOf(*itB)];
+ xMaxSuggested = xOffsetSuggested + *itB;
+ noSignalThresholdColor = blueThresoldColor;
+ }
+ else
+ {
+ noSignalThresholdColor = {75,75,75};
+ noSignalBlack = true;
+ }
+
+ // serach vertical max
+ if (!noSignalBlack)
+ {
+ unsigned xMid = (xMaxSuggested + xOffsetSuggested) / 2;
+ for (unsigned y = yMid; y >= yOffset && yOffsetSuggested != y; --y)
+ {
+ ColorRgb rgb = image(xMid, y);
+ if (rgb <= noSignalThresholdColor)
+ {
+ yOffsetSuggested = y;
+ }
+ }
+
+ for (unsigned y = yMid; y <= yMax && yMaxSuggested != y; ++y)
+ {
+ ColorRgb rgb = image(xMid, y);
+ if (rgb <= noSignalThresholdColor)
+ {
+ yMaxSuggested = y;
+ }
+ }
+ }
+
+ // optimize thresold color
+ noSignalThresholdColor = {0,0,0};
+ for (unsigned x = xOffsetSuggested; x < xMaxSuggested; ++x)
+ {
+ for (unsigned y = yOffsetSuggested; y < yMaxSuggested; ++y)
+ {
+ ColorRgb rgb = image(x, y);
+ if (rgb >= noSignalThresholdColor)
+ {
+ noSignalThresholdColor = rgb;
+ }
+ }
+ }
+
+ // calculate fractional values
+ xOffsetSuggested = (int)(((float)xOffsetSuggested/image.width())*100+0.5)/100.0;
+ xMaxSuggested = (int)(((float)xMaxSuggested/image.width())*100)/100.0;
+ yOffsetSuggested = (int)(((float)yOffsetSuggested/image.height())*100+0.5)/100.0;
+ yMaxSuggested = (int)(((float)yMaxSuggested/image.height())*100)/100.0;
+ double thresholdRed = (int)(((float)noSignalThresholdColor.red/255.0f)*100+0.5)/100.0;
+ double thresholdGreen = (int)(((float)noSignalThresholdColor.green/255.0f)*100+0.5)/100.0;
+ double thresholdBlue = (int)(((float)noSignalThresholdColor.blue/255.0f)*100+0.5)/100.0;
+ thresholdRed = (thresholdRed<0.1f) ?0.1f : thresholdRed;
+ thresholdGreen = (thresholdGreen<0.1f)?0.1f : thresholdGreen;
+ thresholdBlue = (thresholdBlue<0.1f) ?0.1f : thresholdBlue;
+
+ std::cout << std::endl << "Signal detection informations"
+ << std::endl << "============================="
+ << std::endl << "dimension after decimation: " << image.width() << " x " << image.height()
+ << std::endl << "signal detection area : " << xOffset << "," << yOffset << " x " << xMax << "," << yMax << std::endl << std::endl;
+
+ // check if values make sense
+ if (thresholdRed < 0.5 && thresholdGreen < 0.5 && thresholdBlue < 0.5 && thresholdRed > 0.15 && thresholdGreen > 0.15 && thresholdBlue > 0.15)
+ {
+ std::cout << "WARNING \"no signal image\" is to dark, signal detection is not relaiable." << std::endl;
+ }
+
+ if (thresholdRed > 0.5 && thresholdGreen > 0.5 && thresholdBlue > 0.5)
+ {
+ std::cout << "WARNING \"no signal image\" is to bright, signal detection is not relaiable." << std::endl;
+ }
+
+ if (thresholdRed > thresholdGreen && thresholdRed > thresholdBlue && ((thresholdRed-thresholdGreen) <= 0.5 || (thresholdRed-thresholdBlue) <= 0.5))
+ {
+ std::cout << "WARNING difference between threshold color and the other color components is to small, signal detection might have problems." << std::endl;
+ }
+
+ if (thresholdGreen > thresholdRed && thresholdGreen > thresholdBlue && ((thresholdGreen-thresholdRed) <= 0.5 || (thresholdGreen-thresholdBlue) <= 0.5))
+ {
+ std::cout << "WARNING difference between threshold color and the other color components is to small, signal detection might have problems." << std::endl;
+ }
+
+ if (thresholdBlue > thresholdGreen && thresholdBlue > thresholdRed && ((thresholdBlue-thresholdGreen) <= 0.5 || (thresholdBlue-thresholdRed) <= 0.5))
+ {
+ std::cout << "WARNING difference between threshold color and the other color components is to small, signal detection might have problems." << std::endl;
+ }
+
+ if (noSignalBlack)
+ {
+ std::cout << "WARNING no red, green or blue \"no signal area\" detected, signal detection might have problems." << std::endl;
+ }
+
+ if (xOffsetSuggested >= xMaxSuggested || (xMaxSuggested - xOffsetSuggested) < 0.029 )
+ {
+ std::cout << "WARNING horizontal values of signal detection are invalid or detection area is to small, signal detection is not relaiable." << std::endl;
+ }
+
+ if (yOffsetSuggested >= yMaxSuggested || (yMaxSuggested - yOffsetSuggested) < 0.029 )
+ {
+ std::cout << "WARNING horizontal values of signal detection are invalid or detection area is to small, signal detection is not relaiable." << std::endl;
+ }
+
+ std::cout << std::endl
+ << "suggested config values for signal detection:" << std::endl
+ << "\t\"redSignalThreshold\" : " << thresholdRed << "," << std::endl
+ << "\t\"greenSignalThreshold\" : " << thresholdGreen << "," << std::endl
+ << "\t\"blueSignalThreshold\" : " << thresholdBlue << "," << std::endl
+ << "\t\"signalDetectionHorizontalOffsetMin\" : " << xOffsetSuggested << "," << std::endl
+ << "\t\"signalDetectionVerticalOffsetMin\" : " << yOffsetSuggested << "," << std::endl
+ << "\t\"signalDetectionHorizontalOffsetMax\" : " << xMaxSuggested << "," << std::endl
+ << "\t\"signalDetectionVerticalOffsetMax\" : " << yMaxSuggested << std::endl;
+
+ return true;
+}
+
+
+
diff --git a/src/hyperion-v4l2/ScreenshotHandler.h b/src/hyperion-v4l2/ScreenshotHandler.h
index 5c447027..9db02756 100644
--- a/src/hyperion-v4l2/ScreenshotHandler.h
+++ b/src/hyperion-v4l2/ScreenshotHandler.h
@@ -21,6 +21,8 @@ public slots:
void receiveImage(const Image & image);
private:
+ bool findNoSignalSettings(const Image & image);
+
const QString _filename;
const QRectF _signalDetectionOffset;
};
diff --git a/src/hyperion-v4l2/hyperion-v4l2.cpp b/src/hyperion-v4l2/hyperion-v4l2.cpp
index ad8a4d3d..e5d5578f 100644
--- a/src/hyperion-v4l2/hyperion-v4l2.cpp
+++ b/src/hyperion-v4l2/hyperion-v4l2.cpp
@@ -35,6 +35,8 @@ void saveScreenshot(QString filename, const Image & image)
int main(int argc, char** argv)
{
Logger *log = Logger::getInstance("V4L2GRABBER");
+ Logger::setLogLevel(Logger::WARNING);
+
std::cout
<< "hyperion-v4l2:" << std::endl
<< "\tVersion : " << HYPERION_VERSION << " (" << HYPERION_BUILD_ID << ")" << std::endl