我一直想自己实现这样的东西,但用于不同的用例。我希望我的用户能够手动绘制“圆形”、“矩形”和“菱形”,而我的软件将用完美的圆形、矩形和菱形代替原来的曲折线。这是我想到的一个简单的图形/图表绘图 web 应用程序。
无论如何,需要的是从用户不完美的手绘中检测形状。我想我有一个粗略的想法。
几年前,我在 Tcl wiki 上发现了一个简单的玩具手写识别应用程序。它没有使用花哨的人工智能或任何东西来检测字母,而是使用了一种巧妙的图片“散列”技术。
这个想法基本上是这样的:
将您的书写区域划分为多个区域 - 最简单的是网格,但它可以是形状奇特的区域以提高准确性。
当用户绘制一些东西时,遍历区域列表并检测其中是否有任何“墨水”。
如果有“ink”,则将该区域的值设置为 1。如果不设置为 0。这将为您提供一个包含 1 和 0 的数组(或字符串)。如果您累积了一个数组,请将其转换为字符串。该字符串是您的绘图“哈希”。
将此“哈希”与形状哈希数据库进行比较。完全匹配的可能性很小,因此使用像 Levenshtein 距离这样的模糊匹配函数来找到最接近的匹配。
如果找到匹配项(在合理的阈值内),那么您就找到了您的形状(在原始算法中它是一个字母或数字,但这个想法可以推广到形状)。
以下是检测三角形的一个示例:
Sample triangle:
. . . . . . . . . . . . . . . .
0 1 2 # 3 4 .
. . . # # . . .
. . . . . . .#. .#. . . . . . .
5 . # # . .
. . #. .# . .
. . . . . # . . . . # . . . . .
10 . # . . # . .
. . # . . # . .
. . . .#. . . . . . . .#. . . .
15 # . . # .
. #. . . .# .
. . # . . . . . . . . . . # . .
20 # . . . 24 # .
. ########################### .
. . . . . . . . . . . . . . . .
从上面的 ASCII 艺术。数据库中的示例三角形生成“哈希”:
00100
01110
01010
11011
11111
重新排列为字符串:0010001110010101101111111
。
现在让我们比较一个非常糟糕的用户绘制的三角形:
User drawing:
. . . . . . . . . . . . . . . .
0 1 2 # 3 4 .
. . . # # . . .
. . . . . . .#. .#. . . . . . .
5 . # # . .
. . # . # . .
. . . . . # . . . . # . . . . .
10 . # . . # . .
. .# . . # . .
. . . .#. . . . . . . .#. . . .
15 # . . # .
. # . . . . # .
. .# . . . . . . ### . . #. .
20### . .#### . ## 24 # .
. #######. . ###### .
. . . . . . . . . . . . . . . .
其哈希值为:0010001110010101111111111
。将其与数据库中的原始三角形进行比较:
triangle: 0010001110010101101111111
drawing: 0010001110010101111111111
difference: -----------------1-------
现在将绘图与其他形状的散列进行比较:
circle: 0111011011100011101101110
drawing: 0010001110010101111111111
difference: -1-1-1-1-111-11--1--1---1
square: 1111110001100011000111111
drawing: 0010001110010101111111111
difference: 11-111111111-11-111------
diamond: 0111001010100010101001110
drawing: 0010001110010101111111111
difference: -1-1---1--11-111-1-11---1
由于三角形是最佳匹配,我们假设用户正在尝试绘制三角形。
我一直在考虑一些策略来提高算法的可靠性。
- 而不是只存储 1 和 0 存储 0,1,2。这使得数据库中的散列成为“灰度”散列,这可能使我们能够捕捉到画得非常糟糕的形状。
- 而不是只存储 1 和 0 存储 0,1 和“不关心”,这可以让我们过滤掉绘图中的噪声并可以改善匹配。
- 不是使用固定网格,而是获取图形的边界矩形,然后将图形划分为多个区域。这使我们能够检测具有相同哈希值的圆形和椭圆形以及具有相同哈希值的正方形和矩形。它还适用于比预期更小或更大的图纸。
至于如何记录绘图 - 这取决于你。您可以使用画布、SVG 甚至只是使用 onmousemove 轮询鼠标坐标。