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

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

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

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

Ответ 1

  • Поскольку вы ищете минимальное расстояние, а не точное расстояние, вы можете пропустить квадратный корень. Я думаю, Квадратное Евклидово расстояние здесь.
  • Вы сказали, что значения ограничены между 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

Ответ 2

Я думаю, что приведенные выше комментарии верны, но они - по моему скромному мнению - не отвечают на исходный вопрос. (Поправьте меня если я ошибаюсь). Итак, позвольте мне добавить мои 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;

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

Ответ 3

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

Latex

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

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

Ответ 4

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

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

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

Ответ 5

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

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

MySQL также имеет