给定具有x * y单元格的网格(或表格)。每个单元格都包含一个值。这些单元格中的大多数都具有值0,但是在该网格上的某处可能存在具有高值的单元格的“热点”。然后该单元的邻居也具有> 1的值。 0.越远离热点,因为相应的网格单元中的值越低。
因此,这个热点可以看作是山顶,随着价值的降低,我们远离这座山。在某个距离,值再次降至0。
现在我需要确定网格中代表网格重心的单元格。在上面的简单示例中,这个质心将只是具有最高值的一个单元格。然而,并不总是那么简单:
热点单元周围相邻单元的下降值可能不均匀分布,或者“山边”可能比另一侧更早下降到0。
还有另一个热点/山,值为> 0也在网格内。
我可以认为这是一个典型的问题。不幸的是,我不是数学专家所以我不知道要搜索什么(至少我没有在谷歌找到答案)。
任何想法如何解决这个问题?
提前致谢。
答案 0 :(得分:3)
您正在寻找单元格值的“加权平均值”。假设每个单元格的值为z(x,y),那么您可以执行以下操作
zx = sum( z(x, y) ) over all values of y
zy = sum( z(x, y) ) over all values of x
meanX = sum( x * zx(x)) / sum ( zx(x) )
meanY = sum( y * zy(y)) / sum ( zy(y) )
我相信你可以把它转换成你选择的语言......
示例:如果您了解Matlab,则上述内容将编写如下
zx = sum( Z, 1 ); % sum all the rows
zy = sum( Z, 2 ); % sum all the columns
[ny nx] = size(Z); % find out the dimensions of Z
meanX = sum((1:nx).*zx) / sum(zx);
meanY = sum((1:ny).*zy) / sum(zy);
这将给出1 ... nx范围内的meanX:如果它在中间,则值为(nx + 1)/ 2。显然,您可以根据需要进行扩展。
编辑:再一次,用“几乎真实”的代码:
// array Z(N, M) contains values on an evenly spaced grid
// assume base 1 arrays
zx = zeros(N);
zy = zeros(M);
// create X profile:
for jj = 1 to M
for ii = 1 to N
zx(jj) = zx(jj) + Z(ii, jj);
next ii
next jj
// create Y profile:
for ii = 1 to N
for jj = 1 to M
zy(ii) = zy(ii) + Z(ii, jj);
next jj
next ii
xsum = 0;
zxsum = 0;
for ii = 1 to N
zxsum += zx(ii);
xsum += ii * zx(ii);
next ii
xmean = xsum / zxsum;
ysum = 0;
zysum = 0;
for jj = 1 to M
zysum += zy(jj);
ysum += jj * zy(ii);
next jj
ymean = ysum / zysum;
答案 1 :(得分:1)
This Wikipedia entry可能会有所帮助;标题为“粒子系统”的部分就是您所需要的。只需了解您需要为每个维度进行一次计算,其中您显然有两个维度。
这是一个完整的Scala 2.10程序,用于生成一个充满随机整数的网格(使用命令行中指定的维度)并找到重心(行和列从1开始编号):
object Ctr extends App {
val Array( nRows, nCols ) = args map (_.toInt)
val grid = Array.fill( nRows, nCols )( util.Random.nextInt(10) )
grid foreach ( row => println( row mkString "," ) )
val sum = grid.map(_.sum).sum
val xCtr = ( ( for ( i <- 0 until nRows; j <- 0 until nCols )
yield (j+1) * grid(i)(j) ).sum :Float ) / sum
val yCtr = ( ( for ( i <- 0 until nRows; j <- 0 until nCols )
yield (i+1) * grid(i)(j) ).sum :Float ) / sum
println( s"Center is ( $xCtr, $yCtr )" )
}
你可以修改一个函数来保持计算DRYer,但我想尽可能地保持它。无论如何,我们在这里运行了几次:
$ scala Ctr 3 3
4,1,9
3,5,1
9,5,0
Center is ( 1.8378378, 2.0 )
$ scala Ctr 6 9
5,1,1,0,0,4,5,4,6
9,1,0,7,2,7,5,6,7
1,2,6,6,1,8,2,4,6
1,3,9,8,2,9,3,6,7
0,7,1,7,6,6,2,6,1
3,9,6,4,3,2,5,7,1
Center is ( 5.2956524, 3.626087 )