loading...

Jumat, 07 Desember 2018

python-Handwriting Recognition in Action


Pengenalan tulisan tangan yang dibuat kali ini menggunakan deep learning dengan library tensorflow dan keras. Adapun dataset terdiri dari angka 0-9 dari MNIST




Sebelum membaca postingan ini, sebaiknya anda perlu tahu dasar-dasar python terlebih dahulu
Serta cara instal OpenCV, silahkan beli buku saya di:
http://www.softscients.web.id/2018/11/buku-belajar-mudah-python-dengan.html
Untuk instalasi tensorflow yang agak ribet
Silahkan untuk baca postingan ini
http://www.softscients.web.id/2018/05/install-tensorflow-di-windows-dengan.html
Adapun postingan saya didapatkan https://towardsdatascience.com
Kemudian saya sederhanakan saja!

Dibagi menjadi 3 tahap yaitu
  1. Persiapan Dataset
  2. Kompilasi Model
  3. Testing

Persiapan Dataset

Dataset diambildari MNIST yang berisi tulisan tangan 0 s.d 9 dengan 60 ribu data training dan 10 ribu data testing dengan ukuran 28x28
Cara download datanya

import keras
from keras.datasets import mnist
#load mnist dataset
(X_train, y_train), (X_test, y_test) = mnist.load_data()

Alangkah lebih bagusnya disimpan saja dalam format *.npy via spyder
Apa itu spyder baca saja buku saya:

Kompilasi Model

Berikut kode lengkapnya mengenai kompilasi model
X merupakan input berupa array 28x28
Sedangkan Y merupakan target dengan format kelas kategori/target kelas misalkan untuk kelas 3 dibuat menjadi vektor  [0, 0, 0, 1, 0, 0, 0, 0, 0, 0]

# -*- coding: utf-8 -*-
"""
Created on Sat May 26 22:04:42 2018

"""

import keras
from keras.layers.convolutional import Conv2D
from keras.layers.convolutional import MaxPooling2D
from keras.layers import Dense
from keras.layers import Dropout
from keras.layers import Flatten
from keras.layers import Activation
import numpy as np
from keras.models import Sequential


X_train = np.load('X_train.npy') #database untuk training
y_train = np.load('y_train.npy')

X_test = np.load('X_test.npy') #database untuk testing
y_test = np.load('y_test.npy')

img_cols = 28 #ukuran gambar
img_rows = 28

X_train = X_train.reshape(X_train.shape[0], img_rows, img_cols, 1) #diubah menjadi 4 dimensi
X_test = X_test.reshape(X_test.shape[0], img_rows, img_cols, 1) #idem
input_shape = (img_rows, img_cols, 1) 

X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
X_train /= 255
X_test /= 255

num_category = 10
# convert class vectors to binary class matrices
y_train = keras.utils.to_categorical(y_train, num_category)
y_test = keras.utils.to_categorical(y_test, num_category)

model = Sequential()
#convolutional layer with rectified linear unit activation
model.add(Conv2D(32, kernel_size=(3, 3),
                 activation='relu',
                 input_shape=input_shape))

model.add(Conv2D(64, (3, 3), activation='relu'))


model.add(MaxPooling2D(pool_size=(2, 2)))
#randomly turn neurons on and off to improve convergence
model.add(Dropout(0.25))
#flatten since too many dimensions, we only want a classification output
model.add(Flatten())
#fully connected to get all relevant data
model.add(Dense(128, activation='relu'))
#one more dropout for convergence' sake :) 
model.add(Dropout(0.5))
#output a softmax to squash the matrix into output probabilities
model.add(Dense(num_category, activation='softmax'))

model.compile(loss=keras.losses.categorical_crossentropy,
              optimizer=keras.optimizers.Adadelta(),
              metrics=['accuracy'])

batch_size = 128
num_epoch = 5
#model training
model_log = model.fit(X_train, y_train,
          batch_size=batch_size,
          epochs=num_epoch,
          verbose=1,
          validation_data=(X_test, y_test))

score = model.evaluate(X_test, y_test, verbose=0)
print('Test loss:', score[0]) #Test loss: 0.0296396646054
print('Test accuracy:', score[1]) #Test accuracy: 0.9904


#Save the model
# serialize model to JSON
model_digit_json = model.to_json()
with open("model_digit.json", "w") as json_file:
    json_file.write(model_digit_json)
# serialize weights to HDF5
model.save_weights("model_digit.h5")
print("Saved model to disk")


print ('done')

Lebih lanjut bisa anda pelajari di http://cs231n.github.io/convolutional-networks/

Testing

Saya membuat aplikasi painting menggunakan Tkinter dan canvas, berikut tampilan aplikasinya










Berikut kode lengkap dari aplikasi testingnya

‘’’
mulkan.ms@gmail.com 
www.softscients.web.id 
‘’’
from tkinter import *
from PIL import ImageGrab
import cv2
from keras.models import model_from_json
import numpy as np

class Paint(object):

    DEFAULT_PEN_SIZE = 50
    DEFAULT_COLOR = 'black'
    WIDTH = 400
    HEIGHT = 400

    def __init__(self):
        self.root = Tk()

        self.pen_button = Button(self.root, text='pen', command=self.use_pen)
        self.pen_button.grid(row=0, column=0)

        self.brush_button = Button(self.root, text='prediksi', command=self.prediksi)
        self.brush_button.grid(row=0, column=1)

        self.eraser_button = Button(self.root, text='hapus', command=self.hapus)
        self.eraser_button.grid(row=0, column=2)

        self.c = Canvas(self.root, bg='white', width=self.WIDTH, height=self.HEIGHT)
        self.c.grid(row=1, columnspan=3)
        #self.root.overrideredirect(1) # FRAMELESS CANVAS WINDOW
        self.setup()
        self.root.mainloop()

    def setup(self):
        self.old_x = None
        self.old_y = None
        self.line_width = self.DEFAULT_PEN_SIZE
        self.color = self.DEFAULT_COLOR
        self.active_button = self.pen_button
        self.c.bind('<B1-Motion>', self.paint)
        self.c.bind('<ButtonRelease-1>', self.reset)
        self.root.title("Pengenalan Tulisan Tangan Angka")
        lok = "D:/5. Project/python-handwriting recognition/dataset/"
        # Model reconstruction from JSON file
        with open(lok+'model_digit.json', 'r') as f:
            self.model = model_from_json(f.read())
        
        # Load weights into the new model
        self.model.load_weights(lok+'model_digit.h5')
    def simpan_gambar(self,widget):
        x=self.root.winfo_rootx()+widget.winfo_x()
        y=self.root.winfo_rooty()+widget.winfo_y()
        x1=x+widget.winfo_width()
        y1=y+widget.winfo_height()
        ImageGrab.grab().crop((x,y,x1,y1)).save("D:/image.jpg")
    def use_pen(self):
        self.activate_button(self.pen_button)
    def prediksi(self):
        self.simpan_gambar(self.c) #simpan gambar canvas
        img_cols = 28
        img_rows = 28
        
        I = cv2.imread('D:/image.jpg',0) #read sebagai grayscale
        thresh = 127
        I = cv2.threshold(I, thresh, 255, cv2.THRESH_BINARY)[1]
        I = cv2.resize(I, (img_cols,img_rows))
        #untuk operasi negation saja
        I[I>0]=9
        I[I==0]=1
        I[I==9]=0
        
        X_test = I.reshape(1, img_rows, img_cols, 1)
        X_test = X_test.astype('float32')
        
        n2=np.full([1,img_rows,img_cols,1],X_test)
        hasil = self.model.predict(n2)
        pred=(str(np.argmax(hasil))) #cari lokasi index tertinggi
        self.root.title("prediksi : "+pred)
    def hapus(self):
        self.c.create_rectangle(0,0, self.WIDTH,self.HEIGHT,fill="white")
        self.root.title("Pengenalan Tulisan Tangan Angka")
    def paint(self, event):
        self.line_width = self.DEFAULT_PEN_SIZE
        paint_color = 'black'
        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
if __name__ == '__main__':
    Paint()

Tidak ada komentar: