Карта - поиск ближайшего значения?

Я пытаюсь найти ближайшее значение RGB в QMap (я знаю, что это, вероятно, должно быть HSV, но это не проблема). Вот что я получил до сих пор:

        it = images_map.find(current_rgb);

        if(it != images_map.begin()){
            mi = images_map.lowerBound(current_rgb).value();
        }
        else{
            mi = images_map.upperBound(current_rgb).value();
        }

Моя карта выглядит следующим образом:

images_map[ 4283914078 ] 
images_map[ 4284046165 ] 
images_map[ 4284902241 ] 
images_map[ 4289239953 ] 
images_map[ 4282200377 ] 
images_map[ 4289440688 ] 

Когда мой current_rgb, например, 4285046165, все в порядке, но если какое-то значение больше, чем наибольший индекс, программа вылетает. Что я делаю не так?


person Lord Vader    schedule 18.07.2011    source источник
comment
Используете ли вы пользовательское сравнение на своей карте?   -  person MSalters    schedule 18.07.2011
comment
нет, в любом случае это QMap из библиотеки QT.   -  person Lord Vader    schedule 18.07.2011
comment
Хорошо, удален тег STL (QMap из библиотеки Qt, а не STL)   -  person MSalters    schedule 18.07.2011


Ответы (3)


Возможно, потому что .value() пытается отменить ссылку на несуществующий элемент?

Это похоже на вашу собственную реализацию пользовательской карты (или оболочку), но ваша логика кажется неверной.

  1. Вы звоните lowerBound каждый раз, кроме случаев, когда искомый предмет стоит первым на карте
  2. Если он первый на карте, вы делаете поиск снова???
  3. Если это не так, вы ищете снова (который, если он уже найден, повторяет операцию снова), иначе, если он не найден, ищет ближайший (что нормально), однако вы обрабатываете случай, когда его нет (т.е. в lowerBound)?

Логика должна быть примерно такой:

it = images_map.find(current_rgb);

if(it == images_map.end())
{
  it = images_map.lowerBound(current_rgb);
  if (it == images_map.begin())
  {
    it = images_map.upperBound(current_rgb);
    if (it == images_map.end()) 
      // throw error
  }
  // now you know you have a valid iterator - de-reference
  mi = *it.value();
}
person Nim    schedule 18.07.2011
comment
Спасибо, теперь лучше, но в каком состоянии могла произойти ошибка? - person Lord Vader; 18.07.2011
comment
скорее всего из-за следующего, find() возвращает end(), и поэтому вы в конечном итоге делаете upperBound(), который также возвращает end(), который разыменован (.value()), вызывая проблему. - person Nim; 18.07.2011
comment
но я спросил о вашем коде, вы делаете только lowerBound, так что, может быть, нам следует проверить begin()? - person Lord Vader; 18.07.2011
comment
да - я не полностью написал это... Я думаю, вы поняли идею? Если нет, я могу исправить пример... - person Nim; 18.07.2011

Вызов

images_map.upperBound(current_rgb) 

Может вернуться

images_map.end()

В этом случае вам не следует звонить value().

person SKi    schedule 18.07.2011

Вы можете решить проблему с итератором вне диапазона, добавив контрольные значения 0x000000 и 0xFFFFFF (один раз). Таким образом, у вас всегда будет допустимая нижняя и верхняя границы. Конечно, это может повлиять на результат вашего алгоритма. Например. если ваш «самый маленький» реальный цвет был чистым синим (0x0000FF), то темно-синий (0x00007F) теперь будет находить черный, а не чистый синий. Конечно, это легко исправить двумя сравнениями.

Когда часовые расставлены, позвоните QMap::lower_bound. Вам нужно проверить, действительно ли вы нашли точное совпадение: если *lower_bound — это значение, которое вы хотите, верните его. В противном случае lower_bound указывает на первый элемент, который больше вашего ввода. Следовательно, --lowerbound указывает на последний элемент, который меньше вашего ввода. Проверьте, какой из двух ближе.

Обратите внимание, что единственный способ, которым lower_bound может указывать на begin, это когда вы вводите именно 0x000000 (страж), и в этом случае вы не доберетесь до --lower_bound. Ошибки диапазона нет. По той же логике, конечный часовой 0xFFFFFF означает, что вы всегда найдете lower_bound.

person MSalters    schedule 18.07.2011