전체 Source는 Github 에 있습니다.
1. Keras로 MNIST 모델생성
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation
from keras.optimizers import Adam
from keras.utils import np_utils
(X_train, y_train), (X_test, y_test) = mnist.load_data()
X_train = X_train.reshape(60000 , 784 ).astype('float32' )
X_test = X_test.reshape(10000 , 784 ).astype('float' )
X_train /= 255
X_test /= 255
y_train = np_utils.to_categorical(y_train, 10 )
y_test = np_utils.to_categorical(y_test, 10 )
model = Sequential()
model.add(Dense(512 , input_shape=(784 ,)))
model.add(Activation('relu' ))
model.add(Dropout(0.2 ))
model.add(Dense(512 ))
model.add(Activation('relu' ))
model.add(Dropout(0.2 ))
model.add(Dense(10 ))
model.add(Activation('softmax' ))
model.compile (loss='categorical_crossentropy' ,
optimizer=Adam(),
metrics=['accuracy' ])
hist = model.fit(X_train, y_train, epochs = 100 )
score = model.evaluate(X_test, y_test, verbose=1 )
print ('loss=' , score[0 ])
print ('accuracy=' , score[1 ])
model.save('keras_mnist.h5' )
print ("keras_mnist Image Classification Model Save OK" )
2. 필기인식 Data Load
손글씨 숫자 데이터로 MNIST 에서 공개하고 있는 데이를 사용. 이미지 데이터는 각 픽셀을 Grayscale 256단계로 나타내며, 왼쪽 위부터 오른쪽 아래로 차례차례 픽셀이 나열된 형태. 0은 기본 배경색(흰색)이고, 1 ~ 255가 실제 손글씨가 적힌 부분을 나타냄 (28 X 28 픽셀)
import numpy as np
import os
import urllib.request
import gzip
import struct
import base64
def download_data (url, force_download=True ):
fname = url.split("/" )[-1 ]
if force_download or not os.path.exists(fname):
urllib.request.urlretrieve(url, fname)
return fname
def read_data (label_url, image_url ):
with gzip.open (download_data(label_url)) as flbl:
magic, num = struct.unpack(">II" , flbl.read(8 ))
label = np.frombuffer(flbl.read(), dtype=np.int8)
with gzip.open (download_data(image_url), 'rb' ) as fimg:
magic, num, rows, cols = struct.unpack(">IIII" , fimg.read(16 ))
image = np.frombuffer(fimg.read(), dtype=np.uint8).reshape(len (label), rows, cols)
return (label, image)
path='http://yann.lecun.com/exdb/mnist/'
(train_lbl, train_img) = read_data(path+'train-labels-idx1-ubyte.gz' , path+'train-images-idx3-ubyte.gz' )
(val_lbl, val_img) = read_data(path+'t10k-labels-idx1-ubyte.gz' , path+'t10k-images-idx3-ubyte.gz' )
처음 10 개의 이미지를 레이블(Lable)과 함께 출력함
%matplotlib inline
import matplotlib .pyplot as plt
for i in range (10 ):
plt .subplot (1 ,10 ,i+1 )
plt .imshow (train_img[i], cmap='Greys_r' )
plt .axis ('off' )
plt .show ()
print ('Label: %s' % (train_lbl[0 :10 ],))
3. 모델 불러오기
import numpy as np
from keras.models import load_model
model = load_model('keras_mnist.h5' )
모델 테스트
img = val_img[0 ]
plt .imshow(img, cmap='Greys_r')
plt .axis('off ')
plt .show()
re_val_img = img.reshape(1 , 784 ).astype('float32 ')
prob = model.predict(re_val_img/255 )[0 ]
assert max(prob) > 0 .99 , "Low prediction accuracy."
print ('Classified as %d with probability %f' % (prob.argmax(), max(prob)))
input_form = """
<style type ="text/css" >
canvas { border : 1px solid black; }
</style >
<div id ="board" >
<canvas id ="myCanvas" width ="200px" height ="200px" >
Sorry, your browser doesn't support canvas technology.
</canvas >
<p >
<button id ="classify" onclick ="classify()" >
Classify
</button >
<button id ="clear" onclick ="myClear()" >
Clear
</button >
Result:
<input type ="text" id ="result_output" size ="5" value ="" >
</p >
</div >
"""
5. Script 작성
javascript = """
<script type = "text/JavaScript" src = "https://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js?ver=1.4.2" > </script >
<script type = "text/javascript" >
function init ( ) {
var myCanvas = document .getElementById("myCanvas" );
var curColor = $('#selectColor option:selected' ).val();
if (myCanvas) {
var isDown = false ;
var ctx = myCanvas.getContext("2d" );
var canvasX, canvasY;
ctx.lineWidth = 8 ;
$(myCanvas).mousedown(function (e ) {
isDown = true ;
ctx.beginPath();
var parentOffset = $(this ).parent().offset();
canvasX = e.pageX - parentOffset.left;
canvasY = e.pageY - parentOffset.top;
ctx.moveTo(canvasX, canvasY);
}).mousemove(function (e ) {
if (isDown != false ) {
var parentOffset = $(this ).parent().offset();
canvasX = e.pageX - parentOffset.left;
canvasY = e.pageY - parentOffset.top;
ctx.lineTo(canvasX, canvasY);
ctx.strokeStyle = curColor;
ctx.stroke();
}
}).mouseup(function (e ) {
isDown = false ;
ctx.closePath();
});
}
$('#selectColor' ).change(function ( ) {
curColor = $('#selectColor option:selected' ).val();
});
}
init();
function handle_output (out ) {
console .log(out);
var res = null ;
if (out.msg_type == "stream" ){
res = out.content.data;
}
else if (out.msg_type === "execute_result" ){
res = out.content.data["text/plain" ];
}
else if (out.msg_type == "pyerr" ){
res = out.content.ename + ": " + out.content.evalue;
}
else {
res = out.msg_type;
}
document .getElementById("result_output" ).value = res;
}
function classify ( ) {
var kernel = IPython.notebook.kernel;
var myCanvas = document .getElementById("myCanvas" );
data = myCanvas.toDataURL('image/png' );
document .getElementById("result_output" ).value = "" ;
kernel.execute("classifyML('" + data + "')" , {
'iopub' : {
'output' : handle_output
}
}, {
silent : false
});
}
function myClear ( ) {
var myCanvas = document .getElementById("myCanvas" );
myCanvas.getContext("2d" ).clearRect(0 , 0 , myCanvas.width, myCanvas.height);
}
</script >
"""
6. 테스트
from IPython.display import HTML
import cv2
import numpy as np
def classifyML(img):
img = base64 .b64 decode(img[len('data:image/png;base64 ,'):])
img = cv2 .imdecode(np.fromstring(img, np.uint8 ), -1 )
img = cv2 .resize(img[:,:,3 ], (28 ,28 ))
img = img.astype(np.float32 ).reshape((1 ,784 ))/255 .0
print (model.predict(img)[0 ].argmax())
return model.predict(img)[0 ].argmax()
HTML (input_form + javascript)
Jupyter Notebook에서 실행하여 테스트 할 수 있습니다.
댓글을 사용할 수 없습니다.