如何确定颜色是否在范围内

时间:2016-04-06 07:54:59

标签: c++ opencv bgr

我试图按照其中出现的主色来过滤图像。多数民众赞成,现在我想知道所获得的颜色是否在一定范围的颜色范围内。在这种特殊情况下,我想知道它是否在橙色范围内。

我看到了函数' 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;
}

有些错误,因为不像我预期的那样过滤。 谁能帮我? 谢谢!

2 个答案:

答案 0 :(得分:1)

我会采用略微不同的方法。您可以:

,而不是为所有预定义颜色定义范围间隔
  1. 定义预定义的颜色。这将是您可能的颜色的调色板
  2. 根据您要检查的颜色,计算调色板中所有颜色的距离,并保留最近的调色板颜色。
  3. 检查找到的调色板颜色是否足够接近。
  4. 在这个小样本中我使用了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 :(得分:0)

ORANGE_MINORANGE_MAXcolor转换为HSL(HSV)颜色模型,并检查色调是否在要求的范围内。例如,参见http://www.niwa.nu/2013/05/math-behind-colorspace-conversions-rgb-hsl/数学。

<强>更新

还应针对某些范围检查饱和度和亮度,请参阅下面的注释。感谢 MSalters 指出这一点。