0

我正在尝试通过出现在其中的主色来过滤图像。完成了,现在我想知道获得的颜色是否在定义的颜色范围内。在这种特殊情况下,我想知道它是否在橙色范围内。

我看到了“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;
}

出了点问题,因为没有像我预期的那样过滤。谁能帮我?谢谢!

4

2 回答 2

1

我将采用稍微不同的方法。除了定义所有预定义颜色的范围间隔之外,您还可以:

  1. 定义您的预定义颜色。这将是您可能的颜色的调色板
  2. 给定您要检查的颜色,计算与调色板中所有颜色的距离,并保留最近的调色板颜色。
  3. 检查找到的调色板颜色是否足够接近。

在这个小样本中,我使用了 BGR 颜色空间,因为欧几里德距离(norm两种颜色的)表现良好。

您可以使用其他颜色空间,例如 HSV,但您需要找到合适的距离。您不能只使用 H 值,因为您会错过黑色/白色/灰色(如@MSalters 所述)。

因此,例如,给定您的颜色几乎为 orange 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;
}
于 2016-04-06T09:49:52.907 回答
0

ORANGE_MINORANGE_MAX和转换color为 HSL (HSV) 颜色模型并检查色调是否在所需范围内。有关数学,请参见例如http://www.niwa.nu/2013/05/math-behind-colorspace-conversions-rgb-hsl/

更新

还应根据某些范围检查饱和度和亮度,请参阅下面的评论。感谢MSalters指出这一点。

于 2016-04-06T08:25:37.267 回答