Skip to content

Commit c12b320

Browse files
committed
init samples
1 parent cac1c6f commit c12b320

File tree

2 files changed

+393
-0
lines changed

2 files changed

+393
-0
lines changed
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
import six
2+
if six.PY2:
3+
from Tkinter import *
4+
import tkMessageBox as messagebox
5+
else:
6+
from tkinter import *
7+
from tkinter import messagebox
8+
from azure.ai.inkrecognizer import ApplicationKind, InkPointUnit, InkStrokeKind
9+
from azure.ai.inkrecognizer import InkRecognizerClient, InkRecognitionUnitKind
10+
from collections import namedtuple
11+
12+
13+
# Ink Recognizer Client Config
14+
URL = "https://api.cognitive.microsoft.com/inkrecognizer"
15+
CREDENTIAL = "FakeCredential" # Put Azure credential instance here
16+
17+
18+
# Recognition Config
19+
# This tell Ink Recognizer Service that the sample is in en-US.
20+
# Default value is "en-US".
21+
# If "language" in a stroke is specified, this will be overlaped in that stroke.
22+
LANGUAGE_RECOGNITION_LOCALE = "en-US"
23+
# This tell Ink Recognizer Service that domain of the application is writing, i.e. all strokes are writing.
24+
# Default value is ApplicationKind.MIXED, which means let Ink Recognizer Service detect kind of strokes.
25+
# If "kind" in a stroke is specified, this will be overlaped in that stroke.
26+
APPLICATION_KIND = ApplicationKind.WRITING
27+
28+
29+
# UI Config
30+
CANVAS_WIDTH = 800
31+
CANVAS_HEIGHT = 500
32+
STROKE_COLOR = "#476042" # python green
33+
STROKE_WIDTH = 3
34+
35+
36+
# Stroke Implementations
37+
# Shows simple implementation of InkPoint and InkStroke
38+
InkPoint = namedtuple("InkPoint", "x y")
39+
40+
41+
class InkStroke():
42+
def __init__(self,
43+
ink_stroke_id,
44+
ink_points,
45+
stroke_kind=InkStrokeKind.UNKNOWN,
46+
stroke_language=""):
47+
self.id = ink_stroke_id
48+
self.points = ink_points
49+
self.kind = stroke_kind
50+
self.language = stroke_language
51+
52+
53+
# Sample wrapper for InkRecognizerClient that shows how to
54+
# (1) Convert stroke unit from pixel to mm
55+
# (2) Set language recognition locale
56+
# (3) Indexing a key word from recognition results
57+
# (4) Set application kind if user know expected type of ink content
58+
class RecognitionManager:
59+
def __init__(self, pixel_per_mm):
60+
self._pixel_per_mm = pixel_per_mm
61+
self._client = InkRecognizerClient(URL, CREDENTIAL)
62+
self.reset_ink()
63+
64+
def _reset_stroke(self):
65+
self._curr_stroke_points = []
66+
67+
def _pixel_to_mm(self, pixel):
68+
return pixel * 1.0 / self._pixel_per_mm
69+
70+
def reset_ink(self):
71+
self._ink_stroke_list = []
72+
self._root = None
73+
self._reset_stroke()
74+
75+
def add_point(self, x, y):
76+
# Convert from pixel to mm before sending to InkPoint
77+
# You can also specify keyword argument "unit_multiple" in InkRecognizerClient constructor or in recognizer_ink() request
78+
self._curr_stroke_points.append(InkPoint(self._pixel_to_mm(x), self._pixel_to_mm(y)))
79+
80+
def stroke_end(self):
81+
stroke = InkStroke(len(self._ink_stroke_list), self._curr_stroke_points)
82+
self._ink_stroke_list.append(stroke)
83+
self._reset_stroke()
84+
85+
def recognize(self):
86+
self._root = None
87+
try:
88+
root = self._client.recognize_ink(
89+
self._ink_stroke_list,
90+
# Pre-set recognition type
91+
application_kind=APPLICATION_KIND,
92+
# Set language recognition locale
93+
language=LANGUAGE_RECOGNITION_LOCALE)
94+
result_text = []
95+
for word in root.ink_words:
96+
result_text.append(word.recognized_text)
97+
for shape in root.ink_drawings:
98+
result_text.append(shape.recognized_shape.value)
99+
result_text = "\n".join(result_text)
100+
messagebox.showinfo("Result", result_text)
101+
self._root = root
102+
except Exception as e:
103+
messagebox.showinfo("Error", e)
104+
105+
def search(self, word):
106+
# Indexing a key word from recognition results
107+
if self._root is not None:
108+
words = self._root.find_word(word)
109+
messagebox.showinfo("Search Result", "Find %s words" % len(words))
110+
else:
111+
messagebox.showinfo("Search Result", "Find %s words" % 0)
112+
113+
114+
# Sample UI
115+
class InkRecognizerDemo:
116+
def __init__(self):
117+
self._master = Tk()
118+
self._pack_widgets()
119+
120+
self._recognition_manager = RecognitionManager(pixel_per_mm=self._master.winfo_fpixels("1m"))
121+
# point for drawing stroke
122+
self._last_point = None
123+
124+
def _pack_widgets(self):
125+
self._master.title("Ink Recognizer Demo")
126+
# search words
127+
self._search_variable = StringVar(value="")
128+
search_entry = Entry(self._master, textvariable=self._search_variable)
129+
search_button = Button(self._master, text="search a word", command=self._search)
130+
search_entry.pack(pady=5)
131+
search_button.pack()
132+
# main canvas
133+
self._canvas = Canvas(self._master,
134+
width=CANVAS_WIDTH,
135+
height=CANVAS_HEIGHT)
136+
self._canvas.pack(expand=YES, fill = BOTH)
137+
self._canvas.bind( "<B1-Motion>", self._draw)
138+
self._canvas.bind( "<Button-1>", self._stroke_start)
139+
self._canvas.bind("<ButtonRelease-1>", self._stroke_end)
140+
# recognize and clear buttons
141+
recognize_button = Button(
142+
self._master, text="Recognize", command=self._recognize)
143+
recognize_button.pack(pady=5)
144+
clear_button = Button(
145+
self._master, text="Clear", command=self._clear_canvas)
146+
clear_button.pack(pady=5)
147+
148+
def _draw(self, event):
149+
# paint on canvas
150+
x_curr, y_curr = event.x, event.y
151+
if self._last_point is not None:
152+
x_last, y_last = self._last_point[0], self._last_point[1]
153+
self._canvas.create_line(
154+
x_last, y_last, x_curr, y_curr, fill=STROKE_COLOR, width=STROKE_WIDTH)
155+
self._last_point = x_curr, y_curr
156+
# add point to stroke store
157+
self._recognition_manager.add_point(x_curr, y_curr)
158+
159+
def _stroke_start(self, event):
160+
# nothing need to do
161+
pass
162+
163+
def _stroke_end(self, event):
164+
self._recognition_manager.stroke_end()
165+
self._last_point = None
166+
167+
def _clear_canvas(self):
168+
self._canvas.delete("all")
169+
self._recognition_manager.reset_ink()
170+
171+
def _recognize(self):
172+
self._recognition_manager.recognize()
173+
174+
def _search(self):
175+
self._recognition_manager.search(self._search_variable.get())
176+
177+
def run(self):
178+
mainloop()
179+
180+
181+
if __name__ == "__main__":
182+
demo = InkRecognizerDemo()
183+
demo.run()
Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
import wx
2+
from azure.ai.inkrecognizer import ApplicationKind, InkPointUnit, InkStrokeKind
3+
from azure.ai.inkrecognizer import InkRecognizerClient
4+
from collections import namedtuple
5+
6+
7+
# Ink Recognizer Client Config
8+
URL = "https://api.cognitive.microsoft.com/inkrecognizer"
9+
CREDENTIAL = "FakeCredential" # Put Azure credential instance here
10+
11+
12+
# Recognition Config
13+
# This tell Ink Recognizer Service that the sample is in en-US.
14+
# Default value is "en-US".
15+
# If "language" in a stroke is specified, this will be overlaped in that stroke.
16+
LANGUAGE_RECOGNITION_LOCALE = "en-US"
17+
# This tell Ink Recognizer Service that domain of the application is writing, i.e. all strokes are writing.
18+
# Default value is ApplicationKind.MIXED, which means let Ink Recognizer Service detect kind of strokes.
19+
# If "kind" in a stroke is specified, this will be overlaped in that stroke.
20+
APPLICATION_KIND = ApplicationKind.WRITING
21+
22+
23+
# This ratio map the number of pixel for x and y axis coordinates on canvas into number of mm
24+
# In InK Recognizer Server, every coordinate in InkPoint will multiply this number
25+
# You may also want to mutliply /divide this value before sending request and after receiving response
26+
app = wx.App(False)
27+
mm_on_canvas = float(wx.GetDisplaySizeMM()[1])
28+
pixel_on_canvas = float(wx.GetDisplaySize()[1])
29+
UNIT_MULTIPLE = mm_on_canvas / pixel_on_canvas
30+
31+
32+
# UI config
33+
canvas_width = 800
34+
canvas_height = 600
35+
linewidth = 3
36+
37+
38+
# Stroke Implementations
39+
# Shows simple implementation of InkPoint and InkStroke
40+
InkPoint = namedtuple("InkPoint", "x y")
41+
42+
43+
class InkStroke():
44+
def __init__(self,
45+
ink_stroke_id,
46+
ink_points,
47+
stroke_kind=InkStrokeKind.UNKNOWN,
48+
stroke_language=""):
49+
self.id = ink_stroke_id
50+
self.points = ink_points
51+
self.kind = stroke_kind
52+
self.language = stroke_language
53+
54+
55+
# Sample wrapper for InkRecognizerClient that shows how to
56+
# (1) Convert stroke unit from pixel to mm
57+
# (2) Set language recognition locale
58+
# (3) Indexing a key word from recognition results
59+
# (4) Set application kind if user know expected type of ink content
60+
class RecognitionManager:
61+
def __init__(self):
62+
self._client = InkRecognizerClient(
63+
URL, CREDENTIAL,
64+
ink_point_unit=InkPointUnit.MM,
65+
# Convert stroke unit from pixel to mm by specify unit_multiple
66+
# You can also multiply the number when creating InkPoints
67+
unit_multiple=UNIT_MULTIPLE,
68+
# Set language recognition locale
69+
language=LANGUAGE_RECOGNITION_LOCALE,
70+
# Pre-set recognition type
71+
application_kind=APPLICATION_KIND
72+
)
73+
self._reset_ink()
74+
75+
def _reset_ink(self):
76+
self._stroke_list = []
77+
self._reset_stroke()
78+
self._root = None
79+
80+
def _reset_stroke(self):
81+
self._curr_stroke_points = []
82+
83+
def add_point(self, x, y):
84+
self._curr_stroke_points.append(
85+
InkPoint(x, y))
86+
87+
def stroke_start(self):
88+
return
89+
90+
def stroke_end(self):
91+
stroke = InkStroke(len(self._stroke_list),
92+
self._curr_stroke_points)
93+
self._stroke_list.append(stroke)
94+
self._reset_stroke()
95+
96+
def get_stroke_list(self):
97+
return self._stroke_list
98+
99+
def get_curr_points(self):
100+
return self._curr_stroke_points
101+
102+
def recognize(self, call_back):
103+
self._root = self._client.recognize_ink(self._stroke_list)
104+
result_text = []
105+
for word in self._root.ink_words:
106+
result_text.append(word.recognized_text)
107+
for shape in self._root.ink_drawings:
108+
result_text.append(shape.recognized_shape.value)
109+
result_text = "\n".join(result_text)
110+
call_back(result_text)
111+
112+
def search(self, word, call_back):
113+
if self._root is not None:
114+
# Indexing a key word from recognition results
115+
words = self._root.find_word(word)
116+
call_back(len(words))
117+
else:
118+
call_back(0)
119+
120+
121+
# Sample canvas
122+
class Canvas(wx.Panel):
123+
def __init__(self, parent):
124+
super(Canvas, self).__init__(parent)
125+
self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
126+
self.Bind(wx.EVT_SIZE, self.on_size)
127+
self.Bind(wx.EVT_PAINT, self.on_paint)
128+
self.Bind(wx.EVT_LEFT_DOWN, self.on_click)
129+
self.Bind(wx.EVT_MOTION, self.on_drag)
130+
self.Bind(wx.EVT_LEFT_UP, self.on_release)
131+
132+
self._recognition_manager = RecognitionManager()
133+
134+
def on_size(self, event):
135+
event.Skip()
136+
self.Refresh()
137+
138+
def on_paint(self, event):
139+
self.dc = wx.PaintDC(self)
140+
self.dc.SetPen(wx.Pen(wx.BLACK, linewidth))
141+
self.dc.Clear()
142+
for stroke in self._recognition_manager.get_stroke_list():
143+
points = stroke.points
144+
for i in range(len(points) - 1):
145+
self.dc.DrawLine(points[i].x, points[i].y, points[i+1].x, points[i+1].y)
146+
147+
points = self._recognition_manager.get_curr_points()
148+
for i in range(len(points) - 1):
149+
self.dc.DrawLine(points[i].x, points[i].y, points[i+1].x, points[i+1].y)
150+
151+
def on_click(self, event):
152+
self._recognition_manager.stroke_start()
153+
154+
def on_drag(self, event):
155+
if event.Dragging():
156+
self._recognition_manager.add_point(event.X, event.y)
157+
self.Refresh()
158+
159+
def on_release(self, event):
160+
self._recognition_manager.stroke_end()
161+
self.Refresh()
162+
163+
def recognize(self, event, call_back):
164+
self._recognition_manager.recognize(call_back)
165+
166+
def clear(self, event):
167+
self._recognition_manager._reset_ink()
168+
self.Refresh()
169+
170+
def search(self, event, word, call_back):
171+
self._recognition_manager.search(word, call_back)
172+
173+
174+
# Sample wxpython app
175+
class InkRecognizerDemo(wx.Frame):
176+
def __init__(self):
177+
super(InkRecognizerDemo, self).__init__(None)
178+
self.SetTitle('Ink Recognition Demo')
179+
self.SetClientSize((canvas_width, canvas_height))
180+
self.Center()
181+
self.view = Canvas(self)
182+
self.search_button = wx.Button(self.view, wx.ID_ANY, 'Search', (0, canvas_height - 90))
183+
self.recognize_button = wx.Button(self.view, wx.ID_ANY, 'Recognize', (0, canvas_height - 60))
184+
self.clear_button = wx.Button(self.view, wx.ID_ANY, 'Clear', (0, canvas_height - 30))
185+
186+
self.search_text = wx.TextCtrl(self.view, wx.ID_ANY, "", (0, canvas_height - 120))
187+
func_search = lambda event: self.view.search(event, self.search_text.GetLineText(0), call_back=self.show_search_result)
188+
self.search_button.Bind(wx.EVT_BUTTON, func_search)
189+
func_recognize = lambda event: self.view.recognize(event, call_back=self.show_result)
190+
self.recognize_button.Bind(wx.EVT_BUTTON, func_recognize)
191+
self.clear_button.Bind(wx.EVT_BUTTON, self.view.clear)
192+
193+
194+
def show_result(self, result):
195+
dlg = wx.MessageDialog(self, result, "Recognition Result")
196+
dlg.ShowModal()
197+
198+
def show_search_result(self, num_words):
199+
dlg = wx.MessageDialog(self, "Find %s words" % num_words, "Recognition Result")
200+
dlg.ShowModal()
201+
202+
203+
def main():
204+
frame = InkRecognizerDemo()
205+
frame.Show()
206+
app.MainLoop()
207+
208+
209+
if __name__ == '__main__':
210+
main()

0 commit comments

Comments
 (0)