<repo_name>AbhishekHonmute/Mnist_CNN_model_with_drawing_image_GUI<file_sep>/README.md
# Guessing-Drawed-Number

It has GUI made using tkinter to draw image and then that image is feed to a CNN model made using python tensorflow and the ans is showed to user

to run requirements :
1. Install python3
2. Install Tensorflow
3. Install tkinter

Steps : 
1. First activate virtual environment for tensorflow
2. Go to directory of project/
3. Go to directory Mnist_GUI/
4. run the file gui_tf.py using python3 command
5. Draw a image of digit on the given canvas field
6. click on scan button and you will get the output of the Neural Network on right side
7. for redrawing the numbar click on reset button

<file_sep>/mnist_GUI/gui_tf.py
import tensorflow as tf
from tensorflow import keras
import matplotlib.pyplot as plt
import numpy as np
from tkinter import *
import tkinter.font as font
import skimage.io as ski_io
from PIL import Image, ImageFilter

class Paint(object):
	DEFAULT_PEN_SIZE = 5.0
	DEFAULT_COLOR = 'black'	
	def __init__(self):
		self.root = Tk()
		self.root.title("RON Digit Recognizer")
		self.choose_size_button = 35
		self.DEFAULT_COLOR = 'black'
		self.h = Text(self.root, height=1, width=45, font=("Helvetica", 16))
		self.h.grid(row = 0, columnspan = 3)
		self.h.insert(END, "Please draw digit to full scale to area for better accuracy")
		self.h.config(state=DISABLED)
		self.c = Canvas(self.root, bg='white', width=400, height=400)
		self.c.grid(row=1, columnspan = 2)
		self.t = Text(self.root, height=1, width=8, font=("Helvetica", 60))
		self.t.grid(row = 1, column = 2)
		self.t.insert(END, "")
		self.reset_button = Button(self.root, text='Reset', command=self.clear)
		self.reset_button.grid(row=2, column=0)
		self.scan_button = Button(self.root, text='Scan', command=self.scan)
		self.scan_button.grid(row=2, column=1)
		self.setup()
		self.root.mainloop()
	def setup(self):
		self.old_x = None
		self.old_y = None
		self.line_width = self.choose_size_button
		self.color = self.DEFAULT_COLOR
		self.eraser_on = False
		self.c.bind('<B1-Motion>', self.paint)
		self.c.bind('<ButtonRelease-1>', self.reset)
	def paint(self, event):
		self.line_width = self.choose_size_button
		paint_color = self.color
		if self.old_x and self.old_y:
			self.c.create_line(self.old_x, self.old_y, event.x, event.y,
				width=self.line_width, fill=paint_color,
				capstyle=ROUND, smooth=TRUE, splinesteps=36)
		self.old_x = event.x
		self.old_y = event.y
	def reset(self, event):
		self.old_x, self.old_y = None, None
	def clear(self) :
		self.c.delete('all')
		self.t.delete(1.0,"end")
		self.t.insert(1.0, "")
	def scan(self) :
		self.c.postscript(file="tmp_canvas.eps", colormode="color", width=400, height=400, pagewidth=399, pageheight=399)
		data = ski_io.imread("tmp_canvas.eps")
		ski_io.imsave("canvas_image.png", data)
		argv = "canvas_image.png"
		im = Image.open(argv).convert('L')
		width = float(im.size[0])
		height = float(im.size[1])
		newImage = Image.new('L', (28, 28), (255))
		if width > height :
			nheight = int(round((20.0 / width * height), 0))
			if (nheight == 0):
				nheight = 1
			img = im.resize((20, nheight), Image.ANTIALIAS).filter(ImageFilter.SHARPEN)
			wtop = int(round(((28 - nheight) / 2), 0))
			newImage.paste(img, (4, wtop))
		else:
			nwidth = int(round((20.0 / height * width), 0))
			if (nwidth == 0):
				nwidth = 1
			img = im.resize((nwidth, 20), Image.ANTIALIAS).filter(ImageFilter.SHARPEN)
			wleft = int(round(((28 - nwidth) / 2), 0))
			newImage.paste(img, (wleft, 4))
		tv = list(newImage.getdata())
		tva = [(255 - x) * 1.0 / 255.0 for x in tv]
		img = np.array(tva).reshape(28, 28)

		# plt.imshow(np.array(tva).reshape(28, 28))
		# plt.colorbar()
		# plt.show()
		model = tf.keras.models.load_model("./mnist_model_file_final/mnist_model")
		probability_model = tf.keras.Sequential([model, tf.keras.layers.Softmax()])
		predictions = probability_model.predict(img.reshape(1, 28, 28))
		maxp = np.amax(predictions)
		if maxp > 0.8 :
			self.n = np.argmax(predictions)
			self.t.delete(1.0,"end")
			self.t.insert(1.0, self.n)
		else :
			self.t.delete(1.0,"end")
			self.t.insert(1.0, "Not Sure")

if __name__ == '__main__':
    Paint()

    # print(predictions)
    # print(np.argmax(predictions))
    # plt.imshow(x_test[1])
    # plt.show()


<file_sep>/mnist_GUI/mnist_model.py
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
from tensorflow import keras

(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()

x_train, x_test = x_train / 255.00, x_test / 255.00

model = keras.Sequential([
	keras.layers.Flatten(input_shape = (28, 28)),
	keras.layers.Dense(256, activation = 'relu'),
	keras.layers.Dense(128, activation = 'relu'),
	keras.layers.Dense(10)
	])

model.compile(
	optimizer = 'adam',
	loss = tf.keras.losses.SparseCategoricalCrossentropy(from_logits = True),
	metrics = ['accuracy']
	)

model.fit(x_train, y_train, epochs = 10)

test_loss, test_acc = model.evaluate(x_test, y_test, verbose = 2)

print("\n\nTest loss : " + str(test_loss) + "\nTest accurecy : " + str(test_acc * 100))

model.save("./mnist_model_file_4/mnist_model")
# 0 : 97.89
# 1 : 98.07
# 2 : 97.93
# 3 : 98.24