Каков наиболее эффективный способ найти евклидово расстояние в 3d с помощью mysql?

У меня есть таблица MySQL с тысячами точек данных, хранящихся в 3 столбцах R, G,B. Как я могу найти,какая точка данных ближе всего к данной точке (a, b, c), используя евклидово расстояние?

Я сохраняю значения RGB цветов отдельно в таблице, поэтому значения ограничены 0-255 в каждом столбце. Я пытаюсь найти ближайший цвет, найдя цвет с наименьшим евклидовым расстоянием.

Я, очевидно, мог бы пробежаться по каждой точке таблицы, чтобы вычислите расстояние, но это будет недостаточно эффективно для масштабирования. Есть идеи?

5 ответов


  1. поскольку вы ищете минимальное расстояние, а не точное расстояние, вы можете пропустить квадратный корень. Я думаю Квадрат Евклидова Расстояния здесь применимо.
  2. Вы сказали, что значения ограничены между 0-255, поэтому вы можете сделать индексированную таблицу поиска с 255 значениями.

вот что я думаю с точки зрения SQL. r0, g0 и b0 представляют целевой цвет. В таблице Vector будет содержать квадратные значения, упомянутые выше в #2. Это решение будет посещать все записи, но результирующий набор может быть установлен в 1 путем сортировки и выбора только первой строки.

select 
    c.r, c.g, c.b,
    mR.dist + mG.dist + mB.dist as squared_dist
from 
    colors c,
    vector mR,
    vector mG,
    vector mB
where
    c.r-r0 = mR.point and
    c.g-g0 = mG.point and
    c.b-b0 = mB.point
group by
    c.r, c.g, c.b

Я думаю, что все вышеприведенные комментарии верны, но они - по моему скромному мнению - не отвечают на первоначальный вопрос. (Поправьте меня, если я ошибаюсь). Итак, позвольте мне добавить мои 50 центов:

вы просите оператор select, который, учитывая, что ваша таблица называется "цвета", и учитывая, что ваши столбцы называются r, g и b, они являются целыми числами в диапазоне 0..255, и вы ищете значение в своей таблице, ближайшее к заданному значению, скажем: rr, gg, bb, тогда я бы осмелился попробовать следующий:

select min(sqrt((rr-r)*(rr-r)+(gg-g)*(gg-g)+(bb-b)*(bb-b))) from colors;

теперь этот ответ дается с большим количеством предостережений, так как я не уверен, что правильно понял ваш вопрос, поэтому pls подтвердит, правильно ли это, или исправит меня, чтобы я мог помочь.


первый уровень оптимизации, который я вижу, что вы можете сделать, будет квадратным расстоянием, на которое вы хотите ограничить запрос, чтобы вам не нужно было выполнять квадратный корень для каждой строки. Второй уровень оптимизации, который я бы рекомендовал, был бы некоторой предварительной обработкой, чтобы облегчить необходимость в постороннем квадрате для каждого запроса (что могло бы создать дополнительное время выполнения для больших таблиц RGB). Вам нужно будет сделать некоторые бенчмаркинг, чтобы увидеть, но путем замены значений для a, b, c, и d, а затем выполняя запрос, вы можете облегчить некоторый стресс от MySQL.

Latex

обратите внимание, что разница в производительности между последними двумя строками может быть незначительной. Вам придется использовать тестовые запросы в системе, чтобы определить, что быстрее.

Я просто перечитал и заметил, что вы заказываете по расстоянию. В этом случае d должен быть удален, все должно быть перемещено в одну сторону. Вы все еще можете подключить константы, чтобы предотвратить дополнительные обработка на конце MySQL.


Я считаю, что есть два варианта.

вы должны либо, как вы говорите, итерации по всему набору и сравнить и проверить против максимума, который вы установили изначально на Невозможно низкое число, как -1. Это работает в линейном времени, n раз (так как вы сравниваете только 1 точку с каждой точкой в наборе, это масштабируется линейным способом).

Я все еще думаю о другом варианте... что-то вроде выполнения первого поиска ширины от входной точки до точка находится в наборе в искомой точке, но это требует немного больше размышлений (я полагаю, что 3D-пространство должно быть довольно сильно заполнено, чтобы это было более эффективным в среднем).


Если вы пробегаете через каждую точку и вычисляете расстояние, не используйте функцию квадратного корня, это не обязательно. Самой маленькой суммы квадратов будет достаточно.

Это вы пытаетесь решить. (Плоский регистр, выберите все точки, отсортированные по оси x, y или Z. Затем используйте PHP для их обработки)

MySQL также имеет Пространственная База Данных который может иметь это как функцию. Но я не уверен.