Kivy 简明教程

Kivy - Gesture

Kivy 框架能够记录和识别手势。手势是由多点触控设备上的鼠标指针或手指生成的一系列触摸。kivy.gesture 模块定义了 Gesture 类,其对象通过 Kivy 画布上捕获的连续触摸事件的 (x,y) 坐标获得。Kivy 中的手势是 Oleg Dopertchouk 手势识别算法的 Python 实现。

同一个模块还具有 GestureDatabase 类。您可以在手势数据库中存储更多 Gesture 对象,并找出某个手势是否与已存储在数据库中的任何手势匹配。

若要创建 Gesture 对象,您需要一个 x、y 坐标列表。例如 −

from kivy.gesture import Gesture
g = Gesture()
g.add_stroke(point_list=[(1,1), (3,4), (2,1)])
g.normalize()

add_stroke() 方法从坐标对构造一个手势对象。normalize() 方法需要运行手势规范化算法并计算与 self 的点积。

此类 Gesture 对象存储在 GestureDatabase 中。

from kivy.gesture import Gesture, GestureDatabase

# Create a gesture
gdb = GestureDatabase()
gdb.add_gesture(g)

针对此数据库中存储的对象,您可以比较另一个对象并找出数据库中的任何手势是否匹配。

g2 = Gesture()
# ...
gdb.find(g2)

kivy.gesture 模块在 Gesture 类中定义了以下方法 −

  1. add_stroke() − 从手势的触摸点列表构造一个笔触并返回 Stroke 实例。

  2. normalize() − 运行手势规范化算法并计算与 self 的点积。

  3. get_score() − 当一个手势与另一个手势匹配时,此方法返回匹配分数。

GestureDatabase 类具有以下重要方法:−

  1. add_gesture() − 向数据库添加一个新的手势。

  2. find() − 在数据库中查找匹配的手势。可以使用 min_score 参数定义查找精度。它应该介于 0 到 1 之间。

  3. gesture_to_str(gesture) − 将手势转换为一个唯一字符串。

  4. str_to_gesture(data) − 将一个唯一字符串转换为一个手势。

Example

我们定义 touch_down()、touch_move() 和 touch_up() 处理程序来捕获触点并从中绘制一个图案。带有其(touch.x 和 touch.y)坐标的所有点都收集在一个 List 中。

按 Add 按钮时,点 List 将用于构建一个 Gesture。gesture_to_string() 方法返回一个二进制字符串。

if instance.text=='Add':
   g = Gesture()
   g.add_stroke(point_list=Drawgesture.points)
   g.normalize()
   print (self.d.gdb.gesture_to_str(g))
   self.d.gdb.add_gesture(g)
   print (str(g))

手势字符串的一个示例可能如下所示 -

b'eNprYJmayc4ABj082ZlllXrpqcUlpUWpU3rY3aGsyVM0G6fUTtHoYS3PTCnJmOLuYO9kuU766IwetozUzPSMEqCIC9NEhiUOGj38UO3xBUX5KaXJICmhWZ/F3Pse9LAXlxTlZ6cWT4mdksHQwws1PRgsiLCDrSA/M68EpEgDqIoHqioAJIhQxFgxxX3/LdkuHrnEhh7Gyinu9g9vmvlOTnlRmpQhCFGTIQJXkSHqbn9/U85stZMXcMrfxiZ/TfZI/b2QH8TIXydH/pLsv8/zPDJA8pfJkT9jU3RuT/kBYuTPp4ACaAGq/AmbtU412Qo45Q/YKmn+CRIAyR+nUP4wWD4BVX5DtZ7Sj8IHIPltJ4EeUHdAlY9n/VPH/4ABJL92MtAAvwaS5O3n8Z6ZJZ8Gkt9fDLK/hwGn/CJQ8G1E078eZP5TB5D8RlDyunEAp/xOkPxNNPO3N3WGd3CD/Lf/AND4TTlo5u9vEingUAHLnwDLo4aP/eED54+4yH3AKX/8wNSAFu0JIPkzYHnU8Lc/fSDqzhELUPzuvwBynpkBqvz5AwqZLC4LQPJXwPKo4W9/8f6nX4s0iJK/hk3+6v0dbY9MNUDyNyiUvwNzf2oPT3FyUWpqHqKccHdIcNSwvsgQ4+5QGrZn4XqNnLYpyGJOuwTWtWijiultr197/w2qGNum2DXTs8FiE3XfGfUrYRcrubfWerXfa7DYQ+MFU2RfAsW2rZBcxQZWl2hoGfR1zXocYn2Lvq/Y+wosFmmjo1YijCq20vFeB9NNoFja3KvLS7NQxYJmuyy7qAkWu+iyfccpW6CY3YzNy3Qgen+6T3g5cQFQTGua0tKOVSCxJE9fZ2+FdKCY2OSJS55kgsUKA2Sqn59ydyh+15e/ePZLVLFb3fcWfV8JFpsJcrIuUOxYp++i4ExUsU1toIAGix0MPXe3bCJQbF6L9kKuF2CxlxEr+Gy/AMXK6jnnH8oAiSULRjfas4ajilnGReWf2Q0US6qpmC+nDhZLTAQGqhxQzK/y+bzKF6hiVuVhc6+uAIt1pvBcjG4EiqmVHJ1rmA4W25j2jEnpKQ4xoSKTOb3qKGJF/4BB8OI5SCyFMWdG8sbVOMRe5QrNdlmOKnYtq3HWArAdKZr5hVMq+ZHEUkuTEns4S/JzUosS85JTgTXUzpkgMKs0SQ8Ayq8zuw=='

您可以添加任意数量的手势。

kivy gesture

然后,在画布上绘制一个图案,并尝试找出是否有什么手势与该图案匹配。当按 Find 按钮时,find() 方法完成这项工作。

if instance.text=='Find':
   g=Gesture()
   g.add_stroke(point_list=Drawgesture.points)
   g.normalize()
   g1=self.d.gdb.find(g, 0.65)
   print (g1)

以下是用于手势识别练习的 complete code

from kivy.app import App
from kivy.graphics import *
from kivy.uix.floatlayout import FloatLayout
from kivy.gesture import Gesture, GestureDatabase
from kivy.uix.button import Button
from kivy.uix.widget import Widget
from random import random
from kivy.core.window import Window

Window.size = (720, 400)

class Drawgesture(Widget):
   points = []

   def __init__(self, *args, **kwargs):
      super(Drawgesture, self).__init__()
      self.gdb = GestureDatabase()

   def on_touch_down(self, touch):
      with self.canvas:
         self.col = (random(), random(), random())
         Color(self.col)
         touch.ud["line"] = Line(points=(touch.x, touch.y), width=3)
         Drawgesture.points.append((touch.x, touch.y))

   def on_touch_move(self, touch):
      with self.canvas:
         Color(self.col)
         touch.ud["line"].points += (touch.x, touch.y)
         Drawgesture.points.append((touch.x, touch.y))

   def on_touch_up(self, touch):
      print('touch up')

class gestureApp(App):
   def pressed(self, instance):
      if instance.text == 'Add':
         g = Gesture()
         g.add_stroke(point_list=Drawgesture.points)
         g.normalize()
         print(self.d.gdb.gesture_to_str(g))
         self.d.gdb.add_gesture(g)
         print(str(g))

      if instance.text == 'Find':
         g = Gesture()
         g.add_stroke(point_list=Drawgesture.points)
         g.normalize()
         g1 = self.d.gdb.find(g, 0.65)
         print(g1)

      if instance.text == 'Clear':
         self.d.canvas.clear()

   def build(self):
      f = FloatLayout()
      self.d = Drawgesture()
      f.add_widget(self.d)
      b1 = Button(
         text='Add', pos_hint={'x': 0, 'y': 0},
         size_hint=(None, None)
      )
      f.add_widget(b1)
      b2 = Button(
         text='Find', pos_hint={'x': .2, 'y': 0},
         size_hint=(None, None)
      )
      f.add_widget(b2)
      b3 = Button(
         text='Clear', pos_hint={'x': .4, 'y': 0},
         size_hint=(None, None)
      )
      f.add_widget(b3)
      b1.bind(on_press=self.pressed)
      b2.bind(on_press=self.pressed)
      b3.bind(on_press=self.pressed)
      return f

gestureApp().run()

Output

如果匹配分值大于或等于 min_score 参数,则将得到以下结果 −

(0.7093289348205829, <kivy.gesture.Gesture object at 0x000001B817C70490>)