目录
多笔画手势识别器¶
在 1.9.0 版本加入.
警告
此功能目前处于实验阶段,只要此警告提示存在,其内容可能会有所变动。
完整的应用示例请参见 kivy/examples/demo/multistroke/main.py。
概念概述¶
该模块实现了量角器手势识别算法。
Recognizer 是类似于 GestureDatabase 的搜索/数据库 API。它维护一个 MultistrokeGesture 对象的列表,并允许您在其中搜索用户输入的手势。
ProgressTracker 用于跟踪 Recognizer.recognize() 调用的进度。它可以用来与正在运行的识别器任务进行交互,例如强制其中途停止,或在结果到达时进行分析。
MultistrokeGesture 表示手势数据库(Recognizer.db)中的一个手势。它是 UnistrokeTemplate 对象的容器,并实现了堆排列算法,以自动生成所有可能的笔画顺序(如果需要)。
UnistrokeTemplate 表示单个笔画路径。它通常由 MultistrokeGesture 自动实例化,但有时您可能需要手动创建它们。
Candidate 表示一个用户输入的手势,用于在手势数据库中搜索匹配项。通常通过调用 Recognizer.recognize() 自动实例化。
使用示例¶
完整的应用示例请参见 kivy/examples/demo/multistroke/main.py。
您可以绑定到 Recognizer 上的事件,以跟踪所有对 Recognizer.recognize() 调用的状态。回调函数将接收一个 ProgressTracker 实例,该实例可用于分析和控制识别过程的各个方面
from kivy.vector import Vector
from kivy.multistroke import Recognizer
gdb = Recognizer()
def search_start(gdb, pt):
print("A search is starting with %d tasks" % (pt.tasks))
def search_stop(gdb, pt):
# This will call max() on the result dictionary, so it's best to store
# it instead of calling it 3 times consecutively
best = pt.best
print("Search ended (%s). Best is %s (score %f, distance %f)" % (
pt.status, best['name'], best['score'], best['dist'] ))
# Bind your callbacks to track all matching operations
gdb.bind(on_search_start=search_start)
gdb.bind(on_search_complete=search_stop)
# The format below is referred to as `strokes`, a list of stroke paths.
# Note that each path shown here consists of two points, ie a straight
# line; if you plot them it looks like a T, hence the name.
gdb.add_gesture('T', [
[Vector(30, 7), Vector(103, 7)],
[Vector(66, 7), Vector(66, 87)]])
# Now you can search for the 'T' gesture using similar data (user input).
# This will trigger both of the callbacks bound above.
gdb.recognize([
[Vector(45, 8), Vector(110, 12)],
[Vector(88, 9), Vector(85, 95)]])
在下一个 Clock 时钟滴答时,匹配过程开始(并且在此情况下完成)。
要跟踪对 Recognizer.recognize() 的单独调用,请使用返回值(也是一个 ProgressTracker 实例):
# Same as above, but keep track of progress using returned value
progress = gdb.recognize([
[Vector(45, 8), Vector(110, 12)],
[Vector(88, 9), Vector(85, 95)]])
progress.bind(on_progress=my_other_callback)
print(progress.progress) # = 0
# [ assuming a kivy.clock.Clock.tick() here ]
print(result.progress) # = 1
算法细节¶
关于匹配算法的更多信息,请参阅:
- 《量角器:一种快速且精确的手势识别器》——杨力 著
好的,请发送需要翻译的英文内容。
- Lisa Anthony 和 Jacob O. Wobbrock 的“$N-Protractor”
很抱歉,我无法访问外部链接或下载文件。请将需要翻译的英文内容直接粘贴发送给我,我会为您进行专业的中文翻译。
- 部分代码源自此处JavaScript实现:
http://depts.washington.edu/aimgroup/proj/dollar/ndollar.html
- class kivy.multistroke.Candidate(strokes=None, numpoints=16, **kwargs)[源代码]¶
基类:
object表示一组用户输入的单笔路径集合,即用于通过 Protractor 算法与
UnistrokeTemplate对象进行匹配的数据。默认情况下,数据会预先计算,以匹配旋转受限和完全旋转不变的UnistrokeTemplate对象。- 参数:
- strokes
参见
MultistrokeGesture.strokes中的格式示例。候选笔画按给定顺序简单地合并为一个单笔画。其思路是,这将与 MultistrokeGesture.templates 中的某个单笔画排列相匹配。- numpoints
候选对象的默认N值;这仅作为回退使用,通常不会用到,因为N由我们正在比较的UnistrokeTemplate驱动。
- skip_bounded
如果为 True,则不生成/存储旋转有界向量。
- skip_invariant
如果为 True,则不生成/存储旋转不变向量。
请注意,如果您设置了跳过标志(skip-flag),然后尝试检索数据,您将会遇到错误。
- get_angle_similarity(tpl, **kwargs)[源代码]¶
(仅限内部使用)计算此候选对象与UnistrokeTemplate对象之间的角度相似度。返回一个表示角度相似度的数值(数值越低表示越相似)。
- get_protractor_vector(numpoints, orientation_sens)[源代码]¶
(仅限内部使用)返回用于与UnistrokeTemplate进行Protractor比较的向量。
- class kivy.multistroke.MultistrokeGesture(name, strokes=None, **kwargs)[源代码]¶
基类:
objectMultistrokeGesture表示一个手势。它维护一组 strokes`(笔画),并生成单笔画(即 :class:`UnistrokeTemplate)的排列组合,这些排列组合稍后用于评估候选手势与该手势的匹配度。- 参数:
- name
识别手势的名称——它会在
Recognizer.recognize()搜索的结果中返回给您。您可以拥有任意多个具有相同名称的 MultistrokeGesture 对象;即一个手势的多种定义。所有生成的单笔手势排列都会使用相同的名称。此属性为必填项,无默认值。- strokes
表示手势的路径列表。路径是Vector对象的列表:
gesture = MultistrokeGesture('my_gesture', strokes=[ [Vector(x1, y1), Vector(x2, y2), ...... ], # stroke 1 [Vector(), Vector(), Vector(), Vector() ] # stroke 2 #, [stroke 3], [stroke 4], ... ])
为了模板匹配的目的,所有笔画被合并为一个列表(unistroke)。您仍应单独指定笔画,并在可能的情况下将 stroke_sensitive 设置为 True。
一旦完成此操作,除非你将 permute 标志设为 False,否则单笔手势排列会立即生成并存储在 self.templates 中供后续使用。
- priority
决定
Recognizer.recognize()何时尝试匹配此模板,优先级较低的先被评估(仅当使用优先级 filter 时)。对于更可能匹配的手势,应使用较低的优先级。例如,将用户模板设置为比通用模板更低的数值。默认值为 100。- numpoints
确定此手势应重采样到的点数(用于匹配目的)。默认值为16。
- stroke_sensitive
确定在手势匹配过程中,候选(用户输入)手势的笔画(路径)数量是否必须与此手势相同。如果此值为False,则始终评估候选手势,忽略笔画数量。默认值为True。
- orientation_sensitive
确定此手势是否对方向敏感。若为True,则将指示方向与八个基本方向中旋转角度最小的那个对齐。默认值为True。
- angle_similarity
此值由
Recognizer.recognize()函数在评估候选手势与该手势匹配时使用。如果它们之间的角度偏差过大,则该模板被视为不匹配。默认值为 30.0(度)。- permute
如果设为 False,则在实例化时不使用 Heap Permute 算法来生成不同的笔画顺序。若将此设为 False,则仅使用由 strokes 构建的单个 UnistrokeTemplate。
- add_stroke(stroke, permute=False)[源代码]¶
将笔画添加到self.strokes列表中。如果`permute`为True,则调用:meth:`permute`方法以生成新的单笔画模板。
- get_distance(cand, tpl, numpoints=None)[源代码]¶
计算该候选与UnistrokeTemplate之间的距离。返回笔画路径之间的余弦距离。
numpoints 会将 UnistrokeTemplate 和 Candidate 路径都准备为 n 个点(必要时),你可能并不想这样做。
- match_candidate(cand, **kwargs)[源代码]¶
将给定的候选手势与此MultistrokeGesture对象进行匹配。将针对所有模板进行测试,并以包含四个项目的列表形式报告结果:
- 索引 0
最佳匹配模板的索引(在self.templates中)
- 索引 1
从模板到候选路径的计算距离
- 索引 2
所有模板的距离列表。列表索引对应于self.templates中一个:class:`UnistrokeTemplate`的索引。
- 索引 3
已执行的匹配操作计数器,即候选对象与模板进行匹配的次数。
- permute()[源代码]¶
从self.strokes生成所有可能的单笔手势排列,并将生成的UnistrokeTemplate对象列表保存到self.templates中。
引用自 http://faculty.washington.edu/wobbrock/pubs/gi-10.2.pdf ::
We use Heap Permute [16] (p. 179) to generate all stroke orders in a multistroke gesture. Then, to generate stroke directions for each order, we treat each component stroke as a dichotomous [0,1] variable. There are 2^N combinations for N strokes, so we convert the decimal values 0 to 2^N-1, inclusive, to binary representations and regard each bit as indicating forward (0) or reverse (1). This algorithm is often used to generate truth tables in propositional logic.
详见所链接论文第4.1节:“$N算法”。
警告
使用堆排列算法处理超过3笔的手势时,可能会生成极其庞大的模板数量(例如,一个9笔手势相当于3800万个模板)。如果您正在处理这类手势,建议手动组合所有所需的笔画顺序。
- class kivy.multistroke.ProgressTracker(candidate, tasks, **kwargs)[源代码]¶
-
表示一个正在进行(或已完成)的搜索操作。当调用
Recognizer.recognize()方法时,会实例化并返回该对象。results 属性是一个字典,随着识别操作的进行而更新。备注
您无需实例化此类。
- 参数:
- candidate
待评估的
Candidate对象- tasks
任务列表中的手势总数(用于测试比对)
- 事件:
- on_progress
每次处理手势时都会触发该事件。
- on_result
当添加新结果,且该结果是目前对`name`的首次匹配,或是得分更高的连续匹配时触发。
- on_complete
搜索完成时触发,无论出于何种原因。(使用 ProgressTracker.status 来查明原因)
- 属性:
- results
到目前为止的所有结果字典。键是手势的名称(即:attr:UnistrokeTemplate.name,通常继承自
MultistrokeGesture)。字典中的每一项都是一个包含以下条目的字典:- name
匹配模板的名称(冗余)
- score
从1.0(完全匹配)到0.0计算得出的分数。
- dist
候选到模板的余弦距离(低=更接近)
- gesture 手势
匹配到的
MultistrokeGesture对象。- best_template
最佳匹配模板的索引(在
MultistrokeGesture.templates中)- template_results
所有模板的距离列表。列表索引对应于gesture.templates中的:class:`UnistrokeTemplate`索引。
- status
- search
目前正在工作中。
- stop
被用户停止(调用了
stop())- timeout
发生超时(在`recognize()`中指定为`timeout=`)
- goodscore
搜索提前停止,因为找到了一个得分足够高的手势(在recognize()中指定为`goodscore=`)。
- complete
搜索已完成(所有符合筛选条件的手势均已测试完毕)
- property best¶
返回recognize()目前找到的最佳匹配结果。它返回一个包含三个键的字典:'name'、'dist'和'score',分别代表模板名称、距离(来自候选路径)以及计算出的得分值。这是一个Python属性。
- property progress¶
返回进度值,类型为浮点数,0表示完成0%,1表示完成100%。这是一个Python属性。
- class kivy.multistroke.Recognizer(**kwargs)[源代码]¶
-
Recognizer提供了一个带有匹配功能的手势数据库。- 事件:
- on_search_start
当使用此Recognizer开始新的搜索时触发。
- on_search_complete
当正在进行的搜索因任何原因结束时触发。(使用
ProgressTracker.status来查明原因)
- 属性:
- db
一个
ListProperty,包含可用的MultistrokeGesture对象。db是一个ListProperty,默认值为 []。
- add_gesture(name, strokes, **kwargs)[源代码]¶
向数据库中添加一个新手势。这将使用`strokes`实例化一个新的:class:MultistrokeGesture,并将其追加到self.db中。
备注
如果你已经实例化了一个
MultistrokeGesture对象并希望添加它,请手动将其追加到Recognizer.db中。
- export_gesture(filename=None, **kwargs)[源代码]¶
导出
MultistrokeGesture对象的列表。输出一个 base64 编码的字符串,可通过parse_gesture()函数解码为 Python 列表,或使用Recognizer.import_gesture()直接导入到self.db。如果指定了 filename,输出将写入磁盘,否则返回该字符串。该方法接受可选的
Recognizer.filter()参数。
- filter(**kwargs)[源代码]¶
filter()根据给定条件返回self.db中对象的子集。此方法被Recognizer的许多其他方法所使用;例如,在调用Recognizer.recognize()或Recognizer.export_gesture()时可以使用以下参数。通常您无需直接调用此方法。- 参数:
- name
将返回的列表限制为那些
MultistrokeGesture.name与给定正则表达式匹配的手势。如果 re.match(name, MultistrokeGesture.name) 测试为真,则该手势会被包含在返回的列表中。可以是字符串或字符串数组gdb = Recognizer() # Will match all names that start with a capital N # (ie Next, New, N, Nebraska etc, but not "n" or "next") gdb.filter(name='N') # exactly 'N' gdb.filter(name='N$') # Nebraska, teletubbies, France, fraggle, N, n, etc gdb.filter(name=['[Nn]', '(?i)T', '(?i)F'])
- priority
将返回的列表限制为具有特定
MultistrokeGesture.priority值的手势。如果指定为整数,则仅返回优先级较低的手势。如果指定为列表(最小值/最大值):# Max priority 50 gdb.filter(priority=50) # Max priority 50 (same result as above) gdb.filter(priority=[0, 50]) # Min priority 50, max 100 gdb.filter(priority=[50, 100])
使用此选项时,
Recognizer.db会自动按优先级排序,这会带来额外开销。如果您的姿势已按优先级排序,可以使用 force_priority_sort 来覆盖此行为。- orientation_sensitive
将返回的列表限制为对方向敏感的姿势(True)、不对方向敏感的姿势(False)或None(忽略模板敏感性,这是默认值)。
- numstrokes
将返回的手势列表限制为具有指定笔画数(在
MultistrokeGesture.strokes中)的手势。可以是单个整数或整数列表。- numpoints
将返回的手势列表限制为具有特定
MultistrokeGesture.numpoints值的手势。这是为了灵活性而提供的,除非你理解其作用,否则不要使用它。可以是单个整数或整数列表。- force_priority_sort
可用于覆盖默认的排序行为。通常,如果使用了 priority 选项,
MultistrokeGesture对象会按优先级顺序返回。将此设置为 True 将按优先级顺序返回手势,设置为 False 将按手势添加的顺序返回。None 表示自动决定(默认值)。备注
为了提高性能,您可以按优先级顺序加载手势数据库,并在调用
Recognizer.recognize()时将其设置为 False。- db
如果你想要过滤与
Recognizer.db不同的对象列表,可以设置此属性。你可能不需要这样做;它由import_gesture()内部使用。
- import_gesture(data=None, filename=None, **kwargs)[源代码]¶
导入由
export_gesture()格式化的一系列手势。必须指定 data 或 filename 其中之一。该方法接受可选的
Recognizer.filter()参数,如果未指定任何参数,则将导入指定数据中的所有手势。
- parse_gesture(data)[源代码]¶
解析由export_gesture()格式化的数据。返回一个:class:`MultistrokeGesture`对象的列表。此方法由:meth:`import_gesture`内部使用,通常您无需直接调用。
- prepare_templates(**kwargs)[源代码]¶
该方法用于在self.db中的手势内准备:class:`UnistrokeTemplate`对象。如果您希望提前计算所有向量,以减少惰性重采样带来的性能惩罚,这将非常有用。如果在调用:meth:`Recognizer.export_gesture`之前执行此操作,则在稍后加载数据时,向量将已被计算。
该方法接受可选的
Recognizer.filter()参数。force_numpoints,如果指定,将把所有模板准备为给定的点数(而不是每个模板的首选点数;即
UnistrokeTemplate.numpoints)。通常你不会想要这样做。
- recognize(strokes, goodscore=None, timeout=0, delay=0, **kwargs)[源代码]¶
搜索与 strokes 匹配的手势。返回一个
ProgressTracker实例。该方法接受可选的
Recognizer.filter()参数。- 参数:
- strokes
一个笔画路径列表(由
Vector对象组成的列表的列表),将用于与数据库中的手势进行匹配。也可以是一个Candidate实例。警告
如果你手动提供一个带有跳过标志的
Candidate,请确保设置了正确的过滤器参数。否则,系统将尝试加载尚未计算的向量。例如,如果你设置了 skip_bounded 而未将 orientation_sensitive 设为 False,当遇到一个 orientation_sensitive 的UnistrokeTemplate时,将会引发异常。- goodscore
如果设置了此属性(取值范围在0.0 - 1.0之间),并且手势得分等于或高于指定值,则搜索会立即停止,并触发`on_search_complete`事件(同时也会触发关联的:class:`ProgressTracker`实例的`on_complete`事件)。默认值为None(禁用)。
- timeout
指定搜索中止并返回结果时的超时时间(以秒为单位)。此选项仅在 max_gpf 不为 0 时适用。默认值为 0,意味着将测试数据库中的所有手势,无论耗时多久。
- max_gpf
指定每帧可处理的
MultistrokeGesture对象的最大数量。超过此数量时,搜索将暂停并在下一帧继续。设置为 0 将立即完成搜索(并阻塞用户界面)。警告
这并不会限制匹配的
UnistrokeTemplate对象的数量!如果单个手势有一百万个模板,它们将在 max_gpf=1 的情况下于单帧内全部被处理!- delay
设置识别器循环每次运行之间的可选延迟。通常,运行会被安排到下一帧,直到任务列表耗尽。如果设置了此参数,每次运行之间将增加额外的延迟(以秒为单位)。默认值为0,即在下一帧继续。
- force_numpoints
强制所有模板(及候选模板)准备到一定数量的点。例如,在评估模板以确定最佳n值时,这可能很有用(除非你理解其作用,否则不要使用此功能)。
- transfer_gesture(tgt, **kwargs)[源代码]¶
将
MultistrokeGesture对象从Recognizer.db传输到另一个Recognizer实例 tgt。该方法接受可选的
Recognizer.filter()参数。
- class kivy.multistroke.UnistrokeTemplate(name, points=None, **kwargs)[源代码]¶
基类:
object将(单)笔画路径表示为一系列Vector的列表。通常,此类由MultistrokeGesture实例化,而非程序员直接创建。然而,手动组合UnistrokeTemplate对象也是可行的。
- 参数:
- name
标识手势的名称。通常在生成模板时,从父级 MultistrokeGesture 对象继承而来。
- points
表示单笔手势路径的点列表。这通常是MultistrokeGesture中可能的笔画顺序排列之一。
- numpoints
该模板在匹配过程前(理想情况下)应重采样的点数。默认值为16,但如果提高结果质量,您可以使用模板特定的设置。
- orientation_sensitive
确定此模板是否对方向敏感(True)或完全旋转不变(False)。默认值为True。
备注
如果你设置了跳过标志,然后尝试检索这些向量,将会引发异常。