Как определить, находится ли цвет в диапазоне

Я пытаюсь отфильтровать изображения по доминирующему цвету, который появляется в нем. Это сделано, теперь я хочу знать, находится ли полученный цвет в диапазоне от определенного диапазона цветов. В этом конкретном случае я хочу знать, находится ли внутри оранжевый диапазон цветов.

Я видел функцию «inrange», но я не думаю, что этот случай поможет мне. По этому я сделал следующий код:

Scalar ORANGE_MIN = Scalar(18, 40, 90);
Scalar ORANGE_MAX = Scalar(27, 255, 255);

bool in_range(Scalar color, Scalar orange_min, Scalar orange_max)
{
bool result = false;
if ((color.val[0] > orange_min.val[0] && color.val[0] < orange_max.val[0]) &&
(color.val[1] > orange_min.val[1] && color.val[1] < orange_max.val[1]) &&
(color.val[2] > orange_min.val[2] && color.val[2] < orange_max.val[2]))
{
result = true;
}
return result;
}

Что-то не так, потому что нет фильтра, как я ожидал.
Может кто-нибудь мне помочь?
Спасибо!

0

Решение

Я буду следовать немного другому подходу. Вместо определения интервалов диапазона для всех предопределенный цвета, вы можете:

  1. Определите свой предопределенный цвета. Это было бы палитра из ваших возможных цветов
  2. Учитывая цвет, который вы хотите проверить, вычислите расстояние от всех цветов в вашей палитре и оставьте ближайший палитра цвет.
  3. Проверьте, найден ли палитра Цвет достаточно близко.

В этом небольшом примере я использовал цветовое пространство BGR, так как евклидово расстояние (norm из двух цветов) хорошо ведет себя.

Вы можете использовать другое цветовое пространство, например HSV, но вам нужно найти подходящее расстояние. Вы не можете использовать только значение H, так как вы пропустите черный / белый / серый цвета (как упомянуто @MSalters).

Итак, учитывая, например, ваш цвет почти оранжевый 20, 130, 250с соответствующей палитрой вы получите что-то вроде:

[20, 130, 250] is similar to orange
Distance with nearest color [0, 127, 255] is 20.8327

Код:

#include <opencv2/opencv.hpp>
#include <vector>
#include <map>
#include <string>
using namespace cv;
using namespace std;

// Needed to put Vec3b into a std::map
struct lessVec3b
{
bool operator()(const Vec3b& lhs, const Vec3b& rhs) {
return (lhs[0] != rhs[0]) ? (lhs[0] < rhs[0]) : ((lhs[1] != rhs[1]) ? (lhs[1] < rhs[1]) : (lhs[2] < rhs[2]));
}
};int main()
{
// Define a set of predefined BGR colors
map<Vec3b, string, lessVec3b> palette;
palette[Vec3b(0, 0, 0)] = "black";
palette[Vec3b(0, 0, 255)] = "red";
palette[Vec3b(0, 255, 0)] = "green";
palette[Vec3b(255, 0, 0)] = "blue";
palette[Vec3b(0, 127, 255)] = "orange";

// Your color
Vec3b my_color(20, 130, 250); // almost orange

// Look for nearest color in palette
Vec3b nearest_color;
string color_name;
float min_distance = FLT_MAX;
for (const auto& pal : palette)
{
float dist = norm(pal.first, my_color);
if (dist < min_distance)
{
nearest_color = pal.first;
color_name = pal.second;
min_distance = dist;
}
}

// Define a distance. This will behave like your ranges
float th_distance = 1000.f;

if (min_distance < th_distance)
{
cout << my_color << " is similar to " << color_name <<  endl;
}
else
{
cout << my_color << " is not in the palette" << endl;
}
cout << "Distance with nearest color " << nearest_color << " is " << min_distance << endl;

return 0;
}
1

Другие решения

Перерабатывать ORANGE_MIN, ORANGE_MAX, а также color модели HSL (HSV) и убедитесь, что оттенок находится в требуемом диапазоне. Смотрите, например, http://www.niwa.nu/2013/05/math-behind-colorspace-conversions-rgb-hsl/ для математики.

ОБНОВИТЬ

Насыщенность и яркость следует проверять по некоторым диапазонам, см. Комментарии ниже. Спасибо MSalters за указание на это.

0

По вопросам рекламы [email protected]