mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2023-10-10 13:36:59 +02:00
6cf9dfaa68
Co-authored-by: brindosch <edeltraud70@gmx.de>
247 lines
8.2 KiB
C++
247 lines
8.2 KiB
C++
// Qt includes
|
|
#include <QImage>
|
|
#include <QCoreApplication>
|
|
#include <QVector>
|
|
#include <algorithm>
|
|
|
|
// hyperion-v4l2 includes
|
|
#include "ScreenshotHandler.h"
|
|
|
|
ScreenshotHandler::ScreenshotHandler(const QString & filename, const QRectF & signalDetectionOffset)
|
|
: _filename(filename)
|
|
, _signalDetectionOffset(signalDetectionOffset)
|
|
{
|
|
}
|
|
|
|
ScreenshotHandler::~ScreenshotHandler()
|
|
{
|
|
}
|
|
|
|
void ScreenshotHandler::receiveImage(const Image<ColorRgb> & image)
|
|
{
|
|
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);
|
|
|
|
// Quit the application after the first image
|
|
QCoreApplication::quit();
|
|
}
|
|
|
|
bool ScreenshotHandler::findNoSignalSettings(const Image<ColorRgb> & 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<unsigned> redOffsets;
|
|
QVector<unsigned> redCounts;
|
|
QVector<unsigned> greenOffsets;
|
|
QVector<unsigned> greenCounts;
|
|
QVector<unsigned> blueOffsets;
|
|
QVector<unsigned> 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;
|
|
}
|
|
|
|
|
|
|