43#include <visp3/core/vpConfig.h>
44#include <visp3/core/vpColVector.h>
45#include <visp3/core/vpMath.h>
46#include <visp3/core/vpRGBa.h>
48#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
52template<
typename T,
bool = true>
55template <
typename T,
bool useFullScale>
58#ifndef VISP_PYTHON_PREPROCESSOR_RUNNING
69template <
typename T,
bool otherUseFullScale,
typename EnableIf =
void>
70struct UniformLawVariance;
80template <
typename T,
bool useFullScale>
81struct UniformLawVariance<T, useFullScale, typename std::enable_if<std::is_floating_point<T>::value>::type>
85 static constexpr float hueVariance = 1.f/12.f;
86 static constexpr float otherChannelsVariance = 1.f/12.f;
94struct UniformLawVariance<unsigned char, true>
98 static constexpr float hueVariance = (256.f * 256.f - 1.f)/12.f;
99 static constexpr float otherChannelsVariance = (256.f * 256.f - 1.f)/12.f;
108struct UniformLawVariance<unsigned char, false>
113 static constexpr float hueVariance = (180.f * 180.f - 1.f)/12.f;
114 static constexpr float otherChannelsVariance = (256.f * 256.f - 1.f)/12.f;
133template<
typename T,
bool useFullScale>
145 explicit vpHSV(
const double &H_ = 0.,
const double &S_ = 0.,
const double &V_ = 0.)
146 :
H(static_cast<T>(H_))
147 ,
S(static_cast<T>(S_))
148 ,
V(static_cast<T>(V_))
167#ifndef VISP_PYTHON_PREPROCESSOR_RUNNING
178 template<typename U = T, typename V, typename std::enable_if<std::is_same<T, unsigned char>::value &&std::is_floating_point<V>::value &&useFullScale, U>::type = 0 >
194 template<typename U = T, typename V, typename std::enable_if<std::is_same<T, unsigned char>::value &&std::is_floating_point<V>::value && !useFullScale, U>::type = 0 >
209 template<typename U = T, bool otherUseFullScale, typename std::enable_if<std::is_floating_point<U>::value>::type...>
229#if (VISP_CXX_STANDARD > VISP_CXX_STANDARD_98)
253 template<
typename V,
bool otherUseFullScale>
254 typename std::enable_if<std::is_same<T, unsigned char>::value &&std::is_floating_point<V>::value &&useFullScale,
vpHSV<T, useFullScale> &>::type
257 H =
static_cast<T
>(other.
H * 255.);
258 S =
static_cast<T
>(other.
S * 255.);
259 this->
V =
static_cast<T
>(other.
V * 255.);
273 template<
typename U = T,
typename V,
bool otherUseFullScale>
274 typename std::enable_if<std::is_same<U, unsigned char>::value &&std::is_floating_point<V>::value && !useFullScale,
vpHSV<T, useFullScale> &>::type
278 S =
static_cast<T
>(other.
S * 255.);
279 this->
V =
static_cast<T
>(other.
V * 255.);
293 template<
typename U = T,
bool otherUseFullScale>
297 if (otherUseFullScale) {
298 H =
static_cast<T
>(other.
H) /
static_cast<T
>(255.);
303 S =
static_cast<T
>(other.
S) /
static_cast<T
>(255.);
304 V =
static_cast<T
>(other.
V) /
static_cast<T
>(255.);
321 template<
typename U = T,
typename V,
bool otherUseFullScale>
322 typename std::enable_if<std::is_floating_point<U>::value &&std::is_floating_point<V>::value && !std::is_same<T, V>::value,
vpHSV<T, useFullScale> &>::type
325 H =
static_cast<T
>(other.
H);
326 S =
static_cast<T
>(other.
S);
327 this->
V =
static_cast<T
>(other.
V);
339 double red, green, blue;
343 red = rgba.
R / 255.0;
344 green = rgba.
G / 255.0;
345 blue = rgba.
B / 255.0;
348 max = std::max<double>(red, blue);
349 min = std::min<double>(green, blue);
352 max = std::max<double>(green, blue);
353 min = std::min<double>(red, blue);
358 if (!
vpMath::equal(max, 0.0, std::numeric_limits<double>::epsilon())) {
359 s = (max - min) / max;
365 if (
vpMath::equal(s, 0.0, std::numeric_limits<double>::epsilon())) {
369 double delta = max - min;
371 if (
vpMath::equal(red, max, std::numeric_limits<double>::epsilon())) {
372 h = (green - blue) / delta;
374 else if (
vpMath::equal(green, max, std::numeric_limits<double>::epsilon())) {
375 h = 2.0 + ((blue - red) / delta);
378 h = 4.0 + ((red - green) / delta);
406 template <
typename ArithmeticType>
409 static const ArithmeticType invHueVariance = 1.f / UniformLawVariance<T, useFullScale>::hueVariance;
410 static const ArithmeticType invOtherChannelsVariance = 1.f / UniformLawVariance<T, useFullScale>::otherChannelsVariance;
415 ArithmeticType distance = diff[0] * diff[0] * invHueVariance + invOtherChannelsVariance * (diff[1] * diff[1] + diff[2] * diff[2]);
427 template <
typename ArithmeticType>
442 template <
typename ArithmeticType>
457 template <
typename ArithmeticType>
482 return !(*
this == v);
507 result[0] =
H + v[0];
508 result[1] =
S + v[1];
509 result[2] =
V + v[2];
532 virtual std::string
toString()
const;
561 template<
typename Tp = T>
563 typename std::enable_if<std::is_floating_point<Tp>::value,
void>::type set(
const vpColVector &v)
581 template<
typename Tp = T>
583 typename std::enable_if<std::is_same<Tp, unsigned char>::value,
void>::type set(
const vpColVector &v)
597 H =
static_cast<T
>(v[0]);
602 S =
static_cast<T
>(v[1]);
607 V =
static_cast<T
>(v[2]);
611template <
typename T,
bool useFullScale>
614 std::stringstream ss;
616 using CastType =
typename std::conditional<std::is_integral<T>::value, int, T>::type;
617 if (std::is_same<T, unsigned char>::value) {
620 else if (std::is_same<T, double>::value) {
628 std::cout <<
", full";
631 std::cout <<
", partial";
633 ss <<
" scale> (H, S, V): (" << (CastType)
H <<
" , " << (CastType)
S <<
" , " << (CastType)
V <<
")";
637template <
typename T,
bool useFullScale>
Implementation of column vector and the associated operations.
void resize(unsigned int i, bool flagNullify=true)
Class implementing the HSV pixel format.
bool operator==(const vpHSV< T, useFullScale > &v) const
vpHSV< T, useFullScale > & operator=(const vpColVector &v)
std::enable_if< std::is_floating_point< U >::value, vpHSV< T, useFullScale > & >::type buildFrom(const vpHSV< unsigned char, otherUseFullScale > &other)
Convert a vpHSV that uses unsigned char for its channels into a vpHSV that uses floating point for it...
vpHSV(const vpRGBa &rgba)
Construct a new vpHSV object from a vpRGBa object.
vpHSV< T, useFullScale > operator+(const vpHSV< T, useFullScale > &v) const
vpColVector operator-(const vpColVector &v) const
virtual std::string toString() const
Cast a vpHSV into a string, for display purpose.
std::enable_if< std::is_same< T, unsignedchar >::value &&std::is_floating_point< V >::value &&useFullScale, vpHSV< T, useFullScale > & >::type buildFrom(const vpHSV< V, otherUseFullScale > &other)
Convert a floating point HSV into a unsigned char HSV using the full range [0; 255].
vpColVector toColVector() const
Cast a vpHSV into a vpColVector.
vpHSV(const double &H_=0., const double &S_=0., const double &V_=0.)
Construct a new vpHSV object using floating point channels.
std::enable_if< std::is_floating_point< U >::value &&std::is_floating_point< V >::value &&!std::is_same< T, V >::value, vpHSV< T, useFullScale > & >::type buildFrom(const vpHSV< V, otherUseFullScale > &other)
Convert a floating point HSV into another floating point type HSV.
static ArithmeticType mahalanobisDistance(const vpHSV< T, useFullScale > &a, const vpHSV< T, useFullScale > &b, vpColVector &diff)
Compute the Mahalanobis distance between two HSV pixels. It is assumed that the channels are independ...
bool operator!=(const vpHSV< T, useFullScale > &v) const
static ArithmeticType squaredMahalanobisDistance(const vpHSV< T, useFullScale > &a, const vpHSV< T, useFullScale > &b, vpColVector &diff)
Compute the square of the Mahalanobis distance between two HSV pixels. It is assumed that the channel...
static vpColVector computeNormalizedHSV(const vpRGBa &rgba)
Compute the normalized HSV values (i.e. in the range [0; 1]) that correspond to a vpRGBa object.
static ArithmeticType squaredMahalanobisDistance(const vpHSV< T, useFullScale > &a, const vpHSV< T, useFullScale > &b)
Compute the square of the Mahalanobis distance between two HSV pixels. It is assumed that the channel...
vpHSV(const vpHSV< unsigned char, otherUseFullScale > &other)
Construct a new floating point vpHSV object from an unsigned char vpHSV object.
static ArithmeticType mahalanobisDistance(const vpHSV< T, useFullScale > &a, const vpHSV< T, useFullScale > &b)
Compute the Mahalanobis distance between two HSV pixels. It is assumed that the channels are independ...
static constexpr unsigned char nbChannels
Number of channels a HSV pixel is made of.
vpColVector operator-(const vpHSV< T, useFullScale > &v) const
vpHSV(const vpHSV< V > &other)
Construct a new vpHSV object using unsigned char channels and the full range [0; 255] from a vpHSV ob...
friend std::ostream & operator<<(std::ostream &os, const vpHSV< T, useFullScale > &hsv)
std::enable_if< std::is_same< U, unsignedchar >::value &&std::is_floating_point< V >::value &&!useFullScale, vpHSV< T, useFullScale > & >::type buildFrom(const vpHSV< V, otherUseFullScale > &other)
Convert a floating point HSV into a unsigned char HSV using the limited range [0; maxHueUsingLimitedR...
vpHSV(const vpColVector &v)
Construct a new vpHSV object from a vpColVector.
vpHSV(const vpHSV< T, useFullScale > &)=default
Default copy constructor.
static constexpr unsigned char maxHueUsingLimitedRange
Maximum value of the Hue channel when using unsigned char and the limited range.
vpColVector operator+(const vpColVector &v) const
vpHSV< T, useFullScale > & operator=(vpHSV< T, useFullScale > &&)=default
vpHSV< T, useFullScale > & operator=(const vpHSV< T, useFullScale > &)=default
vpHSV< T, useFullScale > & buildFrom(const vpRGBa &rgba)
Modify the object to be the result of the conversion of the vpRGBa object into HSV format.
static bool equal(double x, double y, double threshold=0.001)
unsigned char B
Blue component.
unsigned char R
Red component.
unsigned char G
Green component.