Отображение ближайшего соседа 1D индекса для двумерного массива в меньший двумерный массив - PullRequest
0 голосов
/ 18 декабря 2009

Это в с.

У меня есть два 2D-массива, ArrayA и ArrayB, которые сэмплируют одно и то же пространство. B выбирает иной атрибут, чем ArrayA, реже, чем ArrayA, поэтому он меньше, чем A.

Просто чтобы попытаться определить некоторые переменные: ArrayA: SizeAX по SizeAY, индексируется по indexA для позиции posAX, posAY ArrayB: SizeBX по SizeAY, индексируется по indexB для позиции posBX, posBY

ArrayA и ArrayB являются указателями на начало массива, где сначала сохраняется строка X, затем увеличивается Y, и сохраняется следующая строка X (Y = 1)

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

Вот где я (исправьте все ошибки, пожалуйста! Обратите внимание, что я начинаю с индекса 0): Если ArrayA - 9x9, а ArrayB - 3x3: (PosX, Posy) posA 0,0; indexA = 0 posB 0,0; indexB = 0

posA 8,0; indexA = 8 (конец первого ряда) posB 2,0; indexB = 2

позA 0,1; indexA = 9 posB 0,0; indexB = 0 (все еще ближе к нижней точке)

позА 0,3; indexA = 27 posB 0,1; indexB = 3

PosA 8,8; indexA = 80 (последняя точка) posB 2,2; indexB = 8

пока у меня есть: indexA = posAX + (posAY * SizeAX)

что я пробовал (и, конечно, не смог): indexB = (int) (indexA * (SizeBX * SizeBY / (SizeAX * SizeAY)) + 0.5) // Кажется, что работает только для первой строки и последнего значения ... но это явно не работает - но мне любопытно, как как именно он сопоставляет два вместе, но я посмотрю на это после того, как я это исправлю ..

У меня не было доступа к posAY или posAX, только indexA, но я должен иметь возможность разбить его, используя mod и остаток, верно? или есть более эффективный способ быстрее? A

Я тоже пробовал это:

indexB = (posAY * РазмерBY / SizeAY) * РазмерBY + (posAX * РазмерBX / SizeAX)

Думаю, проблема в том, что мне нужно округлить индексы X и Y, а затем использовать SizeBX и SizeBY?

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

Ответы [ 2 ]

0 голосов
/ 19 декабря 2009

Это некоторые отвратительные имена, которые вы выбрали, но, по крайней мере, они определены.

Я думаю, вы хотите пройти через (x, y) в [0 ... 1] x [0 ... 1] реальном координатном пространстве; то есть нижний правый угол A должен захватывать значение из нижнего правого угла B, а также для середины верхнего левого угла и т. д. Это означает, что вы должны думать о внешних краях точек в вашем массиве как о ширине 0 значения точечных выборок по краям поля [0 ... 1] x [0 ... 1]; то есть, если у вас есть массив 3х3, есть одна точка (0,5,0,5), а остальные - вдоль ребра.

Я предполагаю, что в вашем 2d B массиве есть реальные значения, так что имеет смысл интерполировать; потому что массивы имеют разные размеры

Вот схема перехода с

indexA -> (posAX, posAY) -> (x, y) -> (fracBX, fracBY) -> (по интерполяции ближайшего соседа) из ArrayB

Важно: (fracBX, fracBY) - это действительные координаты в поле [0 ... SizeBX-1] x [0 ... SizeBY-1].

Давайте сделаем это по одному шагу за раз. Предполагая, что я вас понял, значения находятся в памяти в порядке слева-> справа, сверху-> снизу (чтение на английском), так же, как стандартные массивы Си. Тогда:

unsigned posAX=indexA%SizeAX;
unsigned posAY=indexA/SizeAX;

Теперь давайте сопоставим (x, y):

double x=posAX/(SizeAX-1.0); // we get double division when we subtract by 1.0
double y=posAY/(SizeAY-1.0);

Теперь к (fracBX, fracBY), где 0 <= fracBX <= SizeBX и 0 <= fracBY <= SizeBY: </p>

double fracBX=x*(SizeBX-1);
double fracBY=y*(SizeBY-1);

Теперь, чтобы интерполировать между (до 4) ближайшими целочисленными точками в массиве B:

unsigned intBX=(unsigned)fracBX;
double aBX=fracBX-intBX;
unsigned intBY=(unsigned)fracBY;
double aBY=fracBY-intBY;
double *bv=ArrayB+(intBX*sizeBY)+intBY;
#define INTERP(alpha,v1,v2) ((1-alpha)*v1+alpha*v2)
#define INTERPI(alpha,i1,i2) (alpha>0 ? INTERP(alpha,bv[i1],bv[i2] : bv[i1])
double v0=INTERPI(aBX,0,1);
double value=fracBY>0 ? INTERP(aBY,v0,INTERPI(aBX,sizeBY,sizeBY+1)) : v0;

значение - ваш ответ. Проверки для дробных позиций aBX и aBY, равных 0, необходимы для предотвращения доступа к значениям за пределами массива (что может вызвать ошибку сегмента, даже если значения игнорируются умножением на 0). Или вы можете упростить задачу, выделив на 1 строку / столбец больше, чем нужно.

bv [0] - массив ArrayB [intBX] [intBY], bv [1] - один справа, bv [sizeBY] - один вниз, а bv [sizeBY + 1] - один вниз и вправо. (aBX, aBY) - еще одна точка в [0 ... 1] x [0 ... 1], но на этот раз она ограничена этими четырьмя соседними точками в ArrayB.

0 голосов
/ 18 декабря 2009

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

int posBX = (int)floorf((float(posAX) / float(sizeAX - 1)) * float(sizeBX - 1) + 0.5f);
int posBY = (int)floorf((float(posAY) / float(sizeAY - 1)) * float(sizeBY - 1) + 0.5f);
int indexB = posBX + posBY * sizeBX;

Чтобы получить posAX и posAY из indexA:

posAX = indexA % sizeAX;
posAY = indexA / sizeAX;

Для выполнения билинейной интерполяции:

float bx = (float(posAX) / float(sizeAX - 1)) * float(sizeBX - 1);
float by = (float(posAY) / float(sizeAY - 1)) * float(sizeBY - 1);
int x = min(int(floorf(bx)), sizeBX - 2); //x + 1 must be <= sizeBX - 1
int y = min(int(floorf(by)), sizeBY - 2); //y + 1 must be <= sizeBY - 1
float s = bx - float(x);
float t = by - float(y);
float v[4];
v[0] = arrayB[x + y * sizeBX];
v[1] = arrayB[x + 1 + y * sizeBX];
v[2] = arrayB[x + (y + 1) * sizeBX];
v[3] = arrayB[x + 1 + (y + 1) * sizeBX];
float result = (v[0] * (1.0f - s) + v[1] * s) * (1.0f - t) +
               (v[2] * (1.0f - s) + v[3] * s) * t;
...