Проективное преобразование

Вы можете использовать простую операцию reduce:

 

var res = [
{  "url": "/page1", "views": 2 },
{  "url": "/page2", "views": 1 },
{  "url": "/page1", "views": 10 },
{  "url": "/page2", "views": 4 },
{  "url": "/page3", "views": 1 },
{  "url": "/page2", "views": 0 },
{  "url": "/page3", "views": 14 },
{  "url": "/page1", "views": 04 },
{  "url": "/page3", "views": 14 },
];

res = res.reduce((val, acc) => {
if (acc.some(e => e.url == val.url)) {
    acc.find(e => e.url == val.url).views += val.views;
} else {
    acc.push({
        url: val.url,
        views: val.views,
    });
}
return acc;
}, []);

console.log(res);

12
задан Michael Wehner 4 October 2008 в 07:14
поделиться

6 ответов

Править

Предположение ниже об инвариантности угловых отношений является неправильным. Проективные преобразования вместо этого сохраняют сложные отношения и падение. Решение затем:

  1. Найдите точку C' на пересечении строк определенной сегментами AD и CP.
  2. Найдите точку B' на пересечении строк определенной сегментами AD и BP.
  3. Определите сложное отношение B'DAC', т.е. r = (BA' * DC') / (DA * B'C').
  4. Создайте спроектированную строку F'HEG'. Сложное отношение этих точек равно r, т.е. r = (F'E * HG') / (HE * F'G').
  5. F'F и G'G пересекутся в спроектированной точке Q настолько приравнивающийся сложные отношения и знание длины стороны квадрата, можно определить положение Q с некоторой арифметической гимнастикой.

Hmmmm.... Я попробую этого. Это решение полагается при условии, что отношения углов сохраняются в преобразовании. См. изображение для руководства (извините для низкого качества изображения... ДЕЙСТВИТЕЛЬНО поздно). Алгоритм только обеспечивает отображение точки в четырехугольнике к точке в квадрате. Необходимо было бы все еще реализовать контакт с несколькими квадратическими точками, отображаемыми на той же квадратной точке.

Позвольте ABCD быть четырехугольником, где A является верхней левой вершиной, B является верхней правой вершиной, C является нижней правой вершиной, и D является нижней левой вершиной. Пара (xA, yA) представляют координаты X и Y вершины A. Мы отображаем точки в этом четырехугольнике к квадратному EFGH, сторона которого имеет длину, равную m.

alt text

Вычислите длины AD, CD, AC, BD и до н.э:

AD = sqrt((xA-xD)^2 + (yA-yD)^2)
CD = sqrt((xC-xD)^2 + (yC-yD)^2)
AC = sqrt((xA-xC)^2 + (yA-yC)^2)
BD = sqrt((xB-xD)^2 + (yB-yD)^2)
BC = sqrt((xB-xC)^2 + (yB-yC)^2)

Позвольте thetaD быть углом в вершине D и thetaC быть углом в вершине C. Вычислите эти углы с помощью теоремы косинусов:

thetaD = arccos((AD^2 + CD^2 - AC^2) / (2*AD*CD))
thetaC = arccos((BC^2 + CD^2 - BD^2) / (2*BC*CD))

Мы отображаем каждую точку P в четырехугольнике к точке Q в квадрате. Для каждой точки P в четырехугольнике, сделайте следующее:

  • Найдите расстояние DP:

    DP = sqrt((xP-xD)^2 + (yP-yD)^2)
    
  • Найдите расстояние CP:

    CP = sqrt((xP-xC)^2 + (yP-yC)^2)
    
  • Найдите угол thetaP1 между CD и DP:

    thetaP1 = arccos((DP^2 + CD^2 - CP^2) / (2*DP*CD))
    
  • Найдите угол thetaP2 между CD и CP:

    thetaP2 = arccos((CP^2 + CD^2 - DP^2) / (2*CP*CD))
    
  • Отношение thetaP1 к thetaD должно быть отношением thetaQ1 к 90. Поэтому вычислите thetaQ1:

    thetaQ1 = thetaP1 * 90 / thetaD
    
  • Точно так же вычислите thetaQ2:

    thetaQ2 = thetaP2 * 90 / thetaC
    
  • Найдите расстояние HQ:

    HQ = m * sin(thetaQ2) / sin(180-thetaQ1-thetaQ2)
    
  • Наконец, положение X и Y Q относительно нижнего левого угла EFGH:

    x = HQ * cos(thetaQ1)
    y = HQ * sin(thetaQ1)
    

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

5
ответ дан 2 December 2019 в 07:22
поделиться

Я думаю, что Вы, после плоская homography, взгляните на эти примечания лекции:

http://www.cs.utoronto.ca/~strider/vis-notes/tutHomography04.pdf

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

4
ответ дан 2 December 2019 в 07:22
поделиться

Существует проект C++ на CodeProject, который включает источник для проективных преобразований битовых массивов. Математика находится на Википедию здесь. Обратите внимание, что, насколько я знаю, проективное преобразование не отобразит произвольного четырехугольника на другого, но сделает так для треугольников, можно также хотеть искать, скос преобразовывает.

2
ответ дан 2 December 2019 в 07:22
поделиться

Если это преобразование должно выглядеть хорошим (в противоположность способу, которым битовый массив смотрит при изменении размеров его в Краске) Вы не можете только создать формулу, которая отображает целевые пиксели на исходные пиксели. Значения в целевом буфере должны быть основаны на усреднении комплекса соседних исходных пикселей, или иначе результаты будут высоко пикселизированы.

Таким образом, если Вы не хотите войти в некоторое сложное кодирование, используйте чужую волшебную функцию, как smacl и Ian предположили.

2
ответ дан 2 December 2019 в 07:22
поделиться

Вот то, как сделал бы это в принципе:

  • отобразите источник к источнику B через traslation вектор t.
  • возьмите единичные векторы (1,0) и (0,1) и вычислите, как они были бы отображены на единичные векторы B.
  • это дает Вам матрицу преобразования M так, чтобы каждый вектор a в карты к M a + t
  • инвертируйте матрицу и инвертируйте traslation вектор так для каждого вектора b в B у Вас есть обратное отображение b -> M-1 (b - t)
  • после того как у Вас есть это преобразование для каждой точки в целевой области в B, найдите соответствие в A и копии.

Преимущество этого отображения состоит в том, что Вы только вычисляете точки, в которых Вы нуждаетесь, т.е. Вы циклично выполняетесь на целевых точках, не исходных точках. Это была широко используемая техника в "демонстрации, кодирующей" сцену несколько лет назад.

0
ответ дан 2 December 2019 в 07:22
поделиться

Использовать линейную алгебру намного проще, чем всю эту геометрию! Кроме того, вам не нужно использовать синус, косинус и т. Д., Поэтому вы можете сохранить каждое число как рациональную дробь и получить точный числовой результат, если он вам нужен.

Что вам нужно, так это сопоставление ваших старых координат (x, y) с новыми координатами (x ', y'). Вы можете сделать это с помощью матриц. Вам нужно найти матрицу проекции P размером 2 на 4 так, чтобы P, умноженное на старые координаты, равнялось новым координатам. Предположим, что вы сопоставляете линии с линиями (а не, например, прямые линии с параболами). Поскольку у вас есть проекция (параллельные линии не остаются параллельными) и перенос (скольжение), вам также нужен коэффициент (xy) и (1). Нарисовано в виде матриц:

          [x  ]
[a b c d]*[y  ] = [x']
[e f g h] [x*y]   [y']
          [1  ]

Вам нужно знать от a до h, поэтому решите эти уравнения:

a*x_0 + b*y_0 + c*x_0*y_0 + d = i_0
a*x_1 + b*y_1 + c*x_1*y_1 + d = i_1
a*x_2 + b*y_2 + c*x_2*y_2 + d = i_2
a*x_3 + b*y_3 + c*x_3*y_3 + d = i_3

e*x_0 + f*y_0 + g*x_0*y_0 + h = j_0
e*x_1 + f*y_1 + g*x_1*y_1 + h = j_1
e*x_2 + f*y_2 + g*x_2*y_2 + h = j_2
e*x_3 + f*y_3 + g*x_3*y_3 + h = j_3

Опять же, вы можете использовать линейную алгебру:

[x_0 y_0 x_0*y_0 1]   [a e]   [i_0 j_0]
[x_1 y_1 x_1*y_1 1] * [b f] = [i_1 j_1]
[x_2 y_2 x_2*y_2 1]   [c g]   [i_2 j_2]
[x_3 y_3 x_3*y_3 1]   [d h]   [i_3 j_3]

Вставьте углы для x_n, y_n, i_n, j_n. (Углы работают лучше всего, потому что они находятся далеко друг от друга, чтобы уменьшить ошибку, если вы выбираете точки, скажем, по щелчкам пользователя.) Возьмите обратную матрицу 4x4 и умножьте ее на правую часть уравнения. Транспонирование этой матрицы - P. Вы должны быть в состоянии найти функции для вычисления обратной матрицы и умножения в режиме онлайн.

Где вы, вероятно, столкнетесь с ошибками:

  • При вычислении не забывайте проверять деление на ноль. Это признак того, что ваша матрица необратима. Это может произойти, если вы попытаетесь сопоставить одну координату (x, y) с двумя разными точками.
  • Если вы пишете свою собственную математику матриц, помните, что матрицы обычно представляют собой строку, столбец (вертикальный, горизонтальный), а экранная графика - x, y (горизонтальная, вертикальная).Вы обязательно ошибетесь в первый раз.
8
ответ дан 2 December 2019 в 07:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: