我有一个浮点值数组,可以解释为灰度图像或3D表面(高度图)。 例如,它可能是一个像这样的10x10数组:
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 0
0 0 4 0 9 0 0 0 0 0
0 0 0 0 0 0 0 0 3 0
0 8 0 0 0 0 0 0 0 0
0 0 0 6 0 2 8 7 0 0
0 0 0 0 0 3 5 5 0 0
0 0 0 0 0 6 2 1 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
我正在寻找一个Java库(或高效算法)来检测类似于参考模式的一个(或多个)模式的存在和位置,例如我想获取位置(5,5)作为结果无论我在寻找:
2 8 7
3 5 5
6 2 1
或:
3 8 6
3 6 5
5 2 3
有什么想法吗?
答案 0 :(得分:1)
我不知道任何Java库,但我认为编程不会太难。这个问题可以看作是子串问题的衍生物,除了你没有线性字符串。这里有一些Java-ish伪代码可能非常接近。
for(int x = 0; x < heightmap.width(); ++x)
for(int y = 0; y < heightmap.height(); ++y)
if(find_pattern(x, y))
// YAY! pattern starts at (x, y)
// start at (x, y) and find an exact match
boolean find_pattern(int x, int y)
{
for(int xx = 0; xx < pattern.width(); ++x)
for(int yy = 0; yy < pattern.width(); ++x)
if(heightmap[x + xx][y + yy] != pattern[xx][yy])
return false;
return true;
}
这将找到完全匹配。如果你想要一些东西,比如加或减2,那么你需要在find_pattern()中使用一些额外的逻辑而不是!=比较。
可能还有一些其他算法运行得更好。这可能是编程最简单的。复杂性在O(n ^ 2 * m ^ 2)中运行:给定n是高度图的宽度和高度,m是图案的宽度和高度。
注意:这不做边界检查!
如果实施边界检查,它将减少所需的比较次数,因为很明显上述模式无法在高度图的最右边两列中开始。有趣的是,当你进行边界检查时,复杂性变为O(n ^ 2),因为比率n:m变为1:1或0:1
答案 1 :(得分:0)
如果您可以将数据表示为一维数据 数组你基本上有一个字符串(只包含数值) 可以使用正则表达式搜索模式。如果 这是不可能的Java(即创建一串浮动代替 字符)它不应该太难滚动(简单) 用于匹配正则表达式的实现[1]。
[1] http://matt.might.net/articles/implementation-of-nfas-and-regular-expressions-in-java/
答案 2 :(得分:0)
这是图像过滤的问题。最基本的方法可以用这种方式表达:
for i in 0..image.height
for j in 0..image.width
result = 0
for k in 0..pattern.height
for l in 0..pattern.width
if i + k < image.height && j + l < image.width
result += image[i + k][j + l] * pattern[k][l]
if result > threshold
/* Found a solution */
对于给定问题,您必须通过反复试验来找到数字threshold
。也许将数字标准化为[0,1]区间是个好主意。然后,例如result / (pattern.width * pattern.height) > 0.75
意味着“75%喜欢模式”。
根据图像的大小和图案,这可能会很慢 - 在这种情况下,您可以查看Image Filtering in the Frequency Domain