Kivy 手勢



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() 方法需要執行手勢歸一化演算法並計算與自身的點積。

此類 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 類中定義了以下方法:

  • add_stroke() − 從觸控點列表構建手勢的筆劃,並返回 Stroke 例項。

  • normalize() − 執行手勢歸一化演算法並計算與自身的點積。

  • get_score() − 當手勢與另一個手勢匹配時,此方法返回匹配分數。

GestureDatabase 類具有以下重要方法:

  • add_gesture() − 向資料庫新增新的手勢。

  • find() − 在資料庫中查詢匹配的手勢。您可以使用 min_score 引數定義查詢的精度。它應該在 0 到 1 之間。

  • gesture_to_str(gesture) − 將手勢轉換為唯一的字串。

  • str_to_gesture(data) − 將唯一的字串轉換為手勢。

示例

我們定義 touch_down()、touch_move() 和 touch_up() 處理程式來捕獲觸控點並從中繪製圖案。所有具有 (touch.x 和 touch.y) 座標的點都收集在一個列表中。

按下“新增”按鈕時,將使用 points 列表構建 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() 方法會執行此操作。

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)

以下是手勢識別練習的完整程式碼

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()

輸出

如果匹配分數大於或等於 min_score 引數,您將得到以下結果:

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