Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
import ui, io
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image as PILImage
import console
###########################################################################
# Simple Neural Network
class Neural_Network(object):
def __init__(self):
#parameters
self.inputSize = 100
self.hiddenSize = 25
self.outputSize = 1
#weights
self.W1 = np.random.randn(self.inputSize, self.hiddenSize) # weight matrix from input to hidden layer
self.W2 = np.random.randn(self.hiddenSize, self.outputSize) # weight matrix from hidden to output layer
def forward(self, X):
#forward propagation through our network
self.z = np.dot(X, self.W1) # dot product of X (input) and first set of weights
self.z2 = self.sigmoid(self.z) # activation function
self.z3 = np.dot(self.z2, self.W2) # dot product of hidden layer (z2) and second set of weights
o = self.sigmoid(self.z3) # final activation function
return o
def sigmoid(self, s):
# activation function
return 1/(1+np.exp(-s))
def sigmoidPrime(self, s):
#derivative of sigmoid
return s * (1 - s)
def backward(self, X, y, o):
# backward propagate through the network
self.o_error = y - o # error in output
self.o_delta = self.o_error*self.sigmoidPrime(o) # applying derivative of sigmoid to error
self.z2_error = self.o_delta.dot(self.W2.T) # z2 error: how much our hidden layer weights contributed to output error
self.z2_delta = self.z2_error*self.sigmoidPrime(self.z2) # applying derivative of sigmoid to z2 error
self.W1 += X.T.dot(self.z2_delta) # adjusting first set (input --> hidden) weights
self.W2 += self.z2.T.dot(self.o_delta) # adjusting second set (hidden --> output) weights
def train(self, X, y):
o = self.forward(X)
self.backward(X, y, o)
def saveWeights(self):
np.savetxt("w1.txt", self.W1, fmt="%s")
np.savetxt("w2.txt", self.W2, fmt="%s")
def loadWeights(self):
self.W1 = np.loadtxt("w1.txt")
self.W2 = np.loadtxt("w2.txt")
def predict(self, predict):
output = self.forward(predict)
if output > 0.5:
output = 'Positive'
else:
output = 'Negative'
return output
def trainAll(self, iterations):
self.lossArray = []
self.bestLoss = {'val': 99, 'i': 0, 'W1': None, 'W2': None }
for i in range(iterations):
self.lossArray.append(np.mean(np.square(y - NN.forward(X))))
if self.lossArray[i] <= self.bestLoss["val"]:
self.bestLoss = {'val': min(self.lossArray), 'i': i, 'W1': np.copy(self.W1), 'W2': np.copy(self.W2) }
self.train(X, y)
self.W1 = np.copy(self.bestLoss["W1"])
self.W2 = np.copy(self.bestLoss["W2"])
# plt.plot(self.lossArray)
# plt.plot(self.bestLoss["i"], self.bestLoss["val"], 'ro')
# plt.grid(1)
# plt.xlabel('Iterations')
# plt.ylabel('Cost')
# plt.show()
###########################################################################
# The PathView class is responsible for tracking
# touches and drawing the current stroke.
# It is used by SketchView.
class PathView (ui.View):
def __init__(self, frame):
self.frame = frame
self.flex = ''
self.path = None
self.action = None
def touch_began(self, touch):
x, y = touch.location
self.path = ui.Path()
self.path.line_width = 8.0
self.path.line_join_style = ui.LINE_JOIN_ROUND
self.path.line_cap_style = ui.LINE_CAP_ROUND
self.path.move_to(x, y)
def touch_moved(self, touch):
x, y = touch.location
self.path.line_to(x, y)
self.set_needs_display()
def touch_ended(self, touch):
# Send the current path to the SketchView:
if callable(self.action):
self.action(self)
# Clear the view (the path has now been rendered
# into the SketchView's image view):
self.path = None
self.set_needs_display()
def draw(self):
if self.path:
self.path.stroke()
###########################################################################
# The main SketchView contains a PathView for the current
# line and an ImageView for rendering completed strokes.
class SketchView (ui.View):
def __init__(self, width, height):
self.bg_color = 'lightgrey'
iv = ui.ImageView(frame=(0, 0, width, height)) #, border_width=1, border_color='black')
pv = PathView(iv.bounds)
pv.action = self.path_action
self.add_subview(iv)
self.add_subview(pv)
self.image_view = iv
self.bounds = iv.bounds
def path_action(self, sender):
path = sender.path
old_img = self.image_view.image
width, height = self.image_view.width, self.image_view.height
with ui.ImageContext(width, height) as ctx:
if old_img:
old_img.draw()
path.stroke()
self.image_view.image = ctx.get_image()
###########################################################################
# Various helper functions
def getVector(v):
pil_image = ui2pil(snapshot(v.subviews[0]))
# pil_image.show()
pil_image = pil_image.resize((200,200))
# print(pil_image.size)
w, h = int(v.image_view.width), int(v.image_view.height)
# print(w,h)
px = 20
p = int(w / px)
xStep = int(w / p)
yStep = int(h / p)
vector = []
for x in range(0, w, xStep):
for y in range(0, h, yStep):
crop_area = (x, y, xStep + x, yStep + y)
cropped_pil = pil_image.crop(crop_area)
# print(crop_area)
# cropped_pil.show()
crop_arr = cropped_pil.load()
nonEmptyPixelsCount = 0
for x1 in range(xStep):
for y1 in range(yStep):
isEmpty = (crop_arr[x1,y1][3] == 0)
# print(x1, y1, crop_arr[x1,y1], isEmpty)
if not isEmpty:
nonEmptyPixelsCount += 1
if nonEmptyPixelsCount > 0:
nonEmptyPixelsCount = 1
vector.append(nonEmptyPixelsCount)
# print(len(vector))
return vector
def snapshot(view):
with ui.ImageContext(view.width, view.height) as ctx:
view.draw_snapshot()
return ctx.get_image()
def ui2pil(ui_img):
return PILImage.open(io.BytesIO(ui_img.to_png()))
def pil2ui(pil_image):
buffer = io.BytesIO()
pil_image.save(buffer, format='PNG')
return ui.Image.from_data(buffer.getvalue())
def train_action(sender):
global NN, X, y
X = []
y = [[1], [1], [1], [0], [0], [0]]
X.append(getVector(mv.subviews[2]))
X.append(getVector(mv.subviews[3]))
X.append(getVector(mv.subviews[4]))
X.append(getVector(mv.subviews[6]))
X.append(getVector(mv.subviews[7]))
X.append(getVector(mv.subviews[8]))
X = np.array(X, dtype=float)
y = np.array(y, dtype=float)
NN.trainAll(50)
def guess_action(sender):
global NN, X, y
if len(X) == 0:
console.hud_alert('You need to do Steps 1 and 2 first.', 'error')
else:
p = getVector(mv.subviews[12])
p = np.array(p, dtype=float)
console.hud_alert(NN.predict(p))
def clear_action(sender):
mv.subviews[12].image_view.image = None
def clearAll_action(sender):
mv.subviews[2].image_view.image = None
mv.subviews[3].image_view.image = None
mv.subviews[4].image_view.image = None
mv.subviews[6].image_view.image = None
mv.subviews[7].image_view.image = None
mv.subviews[8].image_view.image = None
mv.subviews[12].image_view.image = None
##############################################
NN = Neural_Network()
# We use a square canvas, so that the same image can be used in portrait and landscape orientation.
w, h = ui.get_screen_size()
canvas_size = max(w, h)
box_size = 200
X = []
y = []
mv = ui.View(canvas_size, canvas_size)
mv.bg_color = 'white'
clearAll_button = ui.ButtonItem()
clearAll_button.title = 'Reset !!'
clearAll_button.tint_color = 'red'
clearAll_button.action = clearAll_action
mv.right_button_items = [clearAll_button]
lb = ui.Label()
lb.text='First, prepare the data'
lb.flex = 'W'
lb.x = 290
lb.y = 10
mv.add_subview(lb)
lb = ui.Label()
lb.text='Draw 3 positive images'
lb.flex = 'W'
lb.x = 280
lb.y = 30
mv.add_subview(lb)
sv = SketchView(box_size, box_size)
sv.x = 30
sv.y = 100
mv.add_subview(sv)
sv = SketchView(box_size, box_size)
sv.x = 260
sv.y = 100
mv.add_subview(sv)
sv = SketchView(box_size, box_size)
sv.x = 490
sv.y = 100
mv.add_subview(sv)
lb = ui.Label()
lb.text='Then draw 3 negative images'
lb.flex = 'W'
lb.x = 270
lb.y = 270
mv.add_subview(lb)
sv = SketchView(box_size, box_size)
sv.x = 30
sv.y = 340
mv.add_subview(sv)
sv = SketchView(box_size, box_size)
sv.x = 260
sv.y = 340
mv.add_subview(sv)
sv = SketchView(box_size, box_size)
sv.x = 490
sv.y = 340
mv.add_subview(sv)
lb = ui.Label()
lb.text='Once you have images above, Train the Model'
lb.flex = 'W'
lb.x = 200
lb.y = 520
mv.add_subview(lb)
train_button = ui.Button(frame = (330, 590, 80, 32))
train_button.border_width = 2
train_button.corner_radius = 4
train_button.title = 'Train'
train_button.action = train_action
mv.add_subview(train_button)
lb = ui.Label()
lb.text='OK now lets see if it can Guess right'
lb.flex = 'W'
lb.x = 220
lb.y = 610
mv.add_subview(lb)
sv = SketchView(box_size, box_size)
sv.x = 260
sv.y = 680
mv.add_subview(sv)
guess_button = ui.Button(frame = (280, 890, 80, 32))
guess_button.border_width = 2
guess_button.corner_radius = 4
guess_button.title = 'Guess'
guess_button.action = guess_action
mv.add_subview(guess_button)
clear_button = ui.Button(frame = (370, 890, 80, 32))
clear_button.border_width = 2
clear_button.corner_radius = 4
clear_button.title = 'Clear'
clear_button.action = clear_action
mv.add_subview(clear_button)
mv.name = 'Image Recognition'
mv.present('full_screen', orientations='portrait')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.