set <vec3b> </vec3b>的行为错误

时间:2013-05-12 04:37:32

标签: c++ opencv set containers std

我有一组Vec3b来保存可见的RGB像素值。

std::set<cv::Vec3b> used_colors;


但表现得很奇怪:

used_colors.insert(cv::Vec3b(100, 255, 255));

// this returns 1 although (100, 0, 0) is NOT in the set
used_colors.count(cv::Vec3b(100, 0, 0)); 


找到值(100,0,0),因为已经在集合中插入了以100开头的其他值。无法找到其他值,如(80,0,0)。这显然是错误的怪异行为。


我实施了&lt;像这样的比较运算符:

bool operator <(const cv::Vec3b &a, const cv::Vec3b &b) {
    if(a[0] < b[0])
        return true;

    if(a[0] > b[0]);
        return false;

    if(a[1] < b[1])
        return true;

    if(a[1] > b[1]);
        return false;

    if(a[2] < b[2])
        return true;

    if(a[2] > b[2]);
        return false;

    return false;
}

2 个答案:

答案 0 :(得分:4)

operator<个语句之后,由于错误的分号,您的if被破坏了。

考虑输入a = Vec3b(100, 255, 255)b = Vec3b(100, 0, 0)。由于两者的R值均为100,因此测试结果为

if(a[0] > b[0]);  // <-- notice the semicolon?

由于该尾随分号,该函数无条件地返回false。出于同样的原因,比较b < a也会返回false;并且set::count认为该元素已经存在。

删除尾随分号,比较运算符按预期工作。


不是手动编写所有这些比较来进行词法排序,而是使用std::tie

更容易,更不容易出错的方式
bool operator<(const cv::Vec3b &a, const cv::Vec3b &b)
{
  return std::tie(a[0], a[1], a[2]) < std::tie(b[0], b[1], b[2]);
}

答案 1 :(得分:3)

您的比较功能已被填充,可能是因为您在;个语句之后有if

即使这样,这也远比它需要的复杂得多。 std::tie使这成为一个单行:

bool operator <(const cv::Vec3b &a, const cv::Vec3b &b) 
{
    return std::tie(a[0], a[1], a[2]) < std::tie(b[0], b[1], b[2]); 
}