Сжатие точек GPS

У меня есть устройство, которое записывает данные GPS. Показания снимаются каждые 2-10 секунд. Для мероприятия, занимающего 2 часа, есть много точек GPS.

Кто-нибудь знает алгоритм сжатия набора данных путем удаления избыточных точек данных. т. е. если ряд точек данных находится на прямой линии, то требуются только начальная и конечная точки.


person BENBUN Coder    schedule 29.12.2009    source источник
comment
Одна запись местоположения занимает 4 числа с плавающей запятой или 16 байтов. Каждые две секунды в течение двух часов — 115 КБ. Для какой платформы это важно? Даже для мобильного телефона это ничего.   -  person Pavel Radzivilovsky    schedule 29.12.2009
comment
@Pavel: Зависит от того, сколько спутников используется (до 12). Предложение NMEA $GPGSA позволяет использовать до 12 спутников, а также все остальные вспомогательные данные.   -  person    schedule 29.12.2009
comment
У меня проблема не с памятью, а с дисплеем. Если я хочу отобразить маршрут на веб-сайте (через карты Google), я не хочу отображать 1000 точек данных.   -  person BENBUN Coder    schedule 29.12.2009
comment
@Pavel: это также зависит от данных, которые вам нужно использовать. GPS-приемники не передают не только долготу и широту, но и высоту, может быть, скорость, азимут, количество спутников и т. д.   -  person Joachim Kerschbaumer    schedule 30.12.2009


Ответы (5)


ознакомьтесь с алгоритмом Douglas Peucker, который используется упростить многоугольник. Я успешно использовал это, чтобы уменьшить количество путевых точек GPS при передаче клиентам для целей отображения.

person Joachim Kerschbaumer    schedule 29.12.2009
comment
Следует отметить, что в этом решении есть потеря точности. Кстати, выглядит хорошо, просто не подходит, если каждую точку нужно воссоздать. - person Paul Sasik; 29.12.2009
comment
@psasik: Фильтр Калмана должен исправить это. Распределение ошибок будет иметь место, но чем больше измерений будет выполнено с течением времени, тем выше будет точность. - person ; 29.12.2009
comment
psasik - спасибо за информацию - посмотрю на codeproject.com/KB/ cs/Дуглас-Пекер_Алгоритм.aspx - person BENBUN Coder; 29.12.2009
comment
взгляните на реализацию проекта NetTopologySuite на странице code.google.com/p/nettopologysuite проект. - person Joachim Kerschbaumer; 30.12.2009

Существует исследовательская работа по сжатию данных GPS на мобильных устройствах.

Кроме того, вы можете ознакомиться с этой статьей CodeProject о Написание приложений GPS. Я думаю, что проблема у вас будет не с прямыми точками, а с кривыми дорогами. Все зависит от того, насколько точным вы хотите, чтобы ваш путь был.

person Community    schedule 29.12.2009
comment
Спасибо Roboto - эта информация интересна, но это не совсем то, что я искал. Спасибо за информацию в любом случае. - person BENBUN Coder; 29.12.2009

Вы, вероятно, хотите аппроксимировать свой путь x (t), y (t) полиномиальным приближением. Вы ищете что-то вроде этого: http://www.youtube.com/watch?v=YtcZXlKbDJY ???

person Hamish Grubijan    schedule 29.12.2009

Вы можете удалить лишние точки, выполнив простейшее упрощение, основанное на вычислении наклона между последующими точками.

Вот небольшой, но не полный код C++, представляющий возможный алгоритм:

struct Point
{
   double x;
   double y;
};

double calculate_slope(Point const& p1, Point const& p2)
{
    //      dy     y2 - y1
    // m = ---- = ---------
    //      dx     x2 - x1
    return ((p2.y - p1.y) / (p2.x - p1.x));
}

// 1. Read first two points from GPS stream source
Point p0 = ... ;
Point p1 = ... ;

// 2. Accept p0 as it's first point

// 3. Calculate slope
double m0 = calculate_slope(p0, p1);

// 4. next point is now previous
p0 = p1;

// 5. Read another point
p1 = ... ;
double m1 = calculate_slope(p0, p1);

// 6. Eliminate Compare slopes
double const tolerance = 0.1; // choose your tolerance
double const diff = m0 - m1;
bool if (!((diff <= tolerance) && (diff >= -tolerance)))
{
    // 7. Accept p0 and eliminate p1

    m0 = m1;
}

// Repeat steps from 4 to 7 for the rest of points.

Я надеюсь, что это помогает.

person mloskot    schedule 24.01.2010

Приведенный выше код имеет пару проблем, которые могут сделать его непригодным:

  • Допуск «одинакового уклона» измеряет разницу в градиенте, а не в угле, поэтому ССВ и ССЗ считается гораздо большей разницей, чем ССВ и ЮВ (при условии, что ось Y проходит с севера на юг).

    Один из способов решить эту проблему — использовать допуск для измерения того, как скалярное произведение двух сегментов сравнивается с произведением их длин. (Может помочь понять, что скалярное произведение двух векторов — это произведение их длин и косинуса угла между ними.) Однако см. следующий пункт.

  • Учитывается только ошибка наклона, а не ошибка положения, поэтому длинный сегмент ENE, за которым следует длинный сегмент ESE, с такой же вероятностью будет сжат в один сегмент, как и строка коротких сегментов, чередующихся между ENE и ESE.

Подход, о котором я думал, заключался в том, чтобы посмотреть, что делают приложения векторной графики для преобразования списка координат курсора в последовательность кривых. Например. см. bezier-utils.cpp от lib2geom. Обратите внимание, что (i) это почти полностью основано на позиции, а не на направлении; и (ii) он дает кубические кривые Безье в качестве выходных данных, а не полилинию, хотя вы можете использовать тот же подход, чтобы получить полилинейный вывод, если это предпочтительнее (в этом случае шаг Ньютона-Рафсона становится просто простым скалярным произведением).

person Peter Moulder    schedule 20.05.2013