2D阵列的1D索引的最近邻映射到较小的2D阵列

时间:2009-12-18 20:39:25

标签: c pointers indexing multidimensional-array nearest-neighbor

这是在C.

我有两个2D阵列,ArrayA和ArrayB,它们采样相同的空间。 B比ArrayA更少地采样与ArrayA不同的属性,因此它小于A.

试着定义一些变量: ArrayA:SizeAX by SizeAY,由indexA索引,位置为posAX,posAY ArrayB:SizeBX by SizeAY,由indexB索引,位置为posBX,posBY

ArrayA和ArrayB是指向数组开头的指针,其中先行存储X行,然后Y递增,然后存储下一行X(Y = 1)

所以我需要从给定的indexA设置indexB,使其成为最近邻居样本,与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

posA 0,1; indexA = 9 posB 0,0; indexB = 0(更接近底部点)

posA 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和余数来分解它,对吧?还是有更快捷的方式?甲

我也试过这个:

indexB =(posAY * SizeBY / SizeAY)* SizeBY +(posAX * SizeBX / SizeAX)

我认为问题是我需要将X和Y索引分开,然后再使用SizeBX和SizeBY?

另外需要注意的是,ArrayA和ArrayB来自较大的数据集,它们都会占用更大的空间。由于矩形是任意的,因此ArrayA或ArrayB可能具有最接近矩形边界的点,从而导致关于最近邻居真正抓取的方式的其他问题。我也不确定如何解决这个问题。

2 个答案:

答案 0 :(得分:0)

你的意思是你有两个不同间距的网格覆盖同一区域,并给出其中一个网格点的索引,你想在第二个中找到最接近的网格点。像这样:

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获取posAYindexA

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;

答案 1 :(得分:0)

这些是你选择的一些令人反感的名字,但至少它们已被定义。

我想你想在[0 ... 1] x [0 ... 1]真实坐标空间中经过(x,y);也就是说,A的右下角应该从B的右下角抓取值,对于中左上角等也是如此。这意味着您应该将数组中点的外边缘视为0宽度在[0 ... 1] x [0 ... 1]框的边缘处指出样本值;即如果你有一个3x3阵列,那么在(0.5,0.5)处有一个点,其余的都在边缘。

我假设你的2d B数组中有实数值,所以插值是有意义的;因为数组的大小不同

这是从

开始的方案

indexA - &gt; (posAX,posay) - &gt; (x,y) - &gt; (fracBX,fracBY) - &gt;(通过最近邻插值)来自ArrayB的值

重要说明:(fracBX,fracBY)是方框[0 ... SizeBX-1] x [0 ... SizeBY-1]中的实值坐标。

让我们一步一步。假设我理解你,就像标准C数组一样,值在内存中以left-&gt; right,top-&gt; bottom(英文阅读)顺序存在。然后:

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&lt; = SizeBX且0&lt; = fracBY&lt; = SizeBY:

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

现在,在B数组中最多(最多4个)最近的整数点之间进行插值:

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来忽略值,也可能导致段错误)。或者,您可以通过分配比您需要的更多行/列来简化操作。

bv [0]是ArrayB [intBX] [intBY],bv [1]是右边的一个,bv [sizeBY]是一个向下,bv [sizeBY + 1]是一个向下和向右。 (aBX,aBY)是[0 ... 1] x [0 ... 1]中的另一个点,但这次是由ArrayB中的那四个相邻点限定的。