hyperion.ng/include/blackborder/BlackBorderDetector.h

132 lines
3.5 KiB
C
Raw Normal View History

#pragma once
// Utils includes
#include <utils/Image.h>
namespace hyperion
{
///
/// Result structure of the detected blackborder.
///
struct BlackBorder
{
/// Falg indicating if the border is unknown
bool unknown;
/// The size of the detected horizontal border
int horizontalSize;
/// The size of the detected vertical border
int verticalSize;
///
/// Compares this BlackBorder to the given other BlackBorder
///
/// @param[in] other The other BlackBorder
///
/// @return True if this is the same border as other
///
inline bool operator== (const BlackBorder& other) const
{
if (unknown)
{
return other.unknown;
}
return other.unknown==false && horizontalSize==other.horizontalSize && verticalSize==other.verticalSize;
}
};
///
/// The BlackBorderDetector performs detection of black-borders on a single image.
/// The detector will search for the upper left corner of the picture in the frame.
/// Based on detected black pixels it will give an estimate of the black-border.
///
class BlackBorderDetector
{
public:
///
/// Constructs a black-border detector
/// @param[in] blackborderThreshold The threshold which the blackborder detector should use
///
BlackBorderDetector(uint8_t blackborderThreshold);
///
/// Performs the actual black-border detection on the given image
///
/// @param[in] image The image on which detection is performed
///
/// @return The detected (or not detected) black border info
///
template <typename Pixel_T>
BlackBorder process(const Image<Pixel_T> & image)
{
// test center and 1/3, 2/3 of width/heigth
int width = image.width() / 3;
int height = image.height() / 3;
int width2 = width * 2;
int height2 = height * 2;
int xCenter = image.width() / 2;
int yCenter = image.height() / 2;
int firstNonBlackXPixelIndex = -1;
int firstNonBlackYPixelIndex = -1;
// find first X pixel of the image
for (int x = 0; x < width; ++x)
{
const Pixel_T & color1 = image(x, yCenter);
const Pixel_T & color2 = image(x, height);
const Pixel_T & color3 = image(x, height2);
if (!isBlack(color1) || !isBlack(color2) || !isBlack(color3))
{
firstNonBlackXPixelIndex = x;
break;
}
}
// find first Y pixel of the image
for (int y = 0; y < height; ++y)
{
const Pixel_T & color1 = image(xCenter, y);
const Pixel_T & color2 = image(width, y);
const Pixel_T & color3 = image(width2, y);
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:
///
/// Checks if a given color is considered black and therefor could be part of the border.
///
/// @param[in] color The color to check
///
/// @return True if the color is considered black else false
///
template <typename Pixel_T>
inline bool isBlack(const Pixel_T & color)
{
// Return the simple compare of the color against black
return color.red < _blackborderThreshold && color.green < _blackborderThreshold && color.blue < _blackborderThreshold;
}
private:
/// Threshold for the blackborder detector [0 .. 255]
const uint8_t _blackborderThreshold;
};
} // end namespace hyperion