SW/영상인식

내 손글씨를 직접 mnist 모델에 적용하는 방법

얇은생각 2019. 10. 7. 07:30
반응형

코드

import numpy as np
import matplotlib.pyplot as plt
import glob
from PIL import Image
%matplotlib inline

for image_path in glob.glob("./my_data/*.png"):
    print("image_path : {}".format(image_path))
    img = Image.open(image_path).convert("L")
    plt.imshow(img)
    plt.show()

    img = np.resize(img, (1,784))
    im2arr = ((np.array(img) / 255) - 1) * -1
    
    print(im2arr.shape)
    print(type(im2arr))
    print("Prediction: ", sess.run(tf.argmax(logits, 1), feed_dict={X: im2arr, keep_prob: 1}))

 

우선 해당하는 경로에 직접 그린 png 파일을 넣어놓았습니다. 그리고 PIL, glob 라이브러리를 활용해, 입력할 저의 손글씨를 읽어왔습니다.

 

제 모델은 (1, 784) 형태의 input을 가집니다. 따라서 저는 resize를 (1, 784) 형태로 인풋 데이터를 변형해주었습니다. 문제는 그 다음이었습니다. mnist 데이터 형태는 png 형태를 읽어오는 방식의 형태로 가지지 않기 때문입니다.

 

그래서 mnist 형식에 맞게 전처리를 해주기 위해 255로 나누어주고 -1을 해준뒤 -1을 곱하였습니다.

 

하지만 이 방식이 항상 옳지는 않는 것으로 보입니다. 그 이유는, pytorch, keras, tensorflow에서 사용하는 mnist 데이터의 형태가 다를 수 있기 때문입니다. 저는 텐서플로우에서 제공해주는 mnist 데이터를 활용하였습니다.

 

개발한 모델을 불러왔다는 가정하에 위 코드와 같이 실행을 하면 다음과 같은 결과를 가집니다.

 

 

 


결과

image_path : ./my_data\0.png

(1, 784) <class 'numpy.ndarray'>

Prediction: [0]

 

image_path : ./my_data\1.png

(1, 784)

<class 'numpy.ndarray'>

Prediction: [1]

 

image_path : ./my_data\2.png

(1, 784)

<class 'numpy.ndarray'>

Prediction: [2]


 

위와 같이 임의의 직접 제가 쓴 손글씨 데이터를 28 * 28 형태의 png 형태를 잘 읽어와서, 예측하는 것을 확인할 수 있습니다. 

 

데이터를 전처리를 본인에 input 데이터 형식에 맞게 넣기 위해서는 다음과 같은 작업을 통해 알 수 있습니다.

 

 

 


코드

print(mnist.test.images[r:r + 1].shape)
print(type(mnist.test.images[r:r + 1]))
print(mnist.test.images[r:r + 1])

 

 

 

결과

(1, 784)

<class 'numpy.ndarray'>

[[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.7568628 0.75294125 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.13725491 0.9490197 0.8745099 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.29803923 1. 0.8745099 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.04313726 0.8862746 0.9960785 0.5764706 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.47058827 0.9960785 0.9960785 0.24705884 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.00392157 0.39607847 0.9960785 .....

 


mnist 인풋 데이터를 찍어보니, 위와 같이 나오는 것을 알 수 있습니다. 텐서플로우가 아닌 다른 데이터는 어떠한 형태로 제공되는지 아직 정확히 확인을 해보지 못하였으나, 비슷한 형태일 것으로 보여집니다.

 

따라서, png 파일을 읽어오면 255 형태로 읽어옵니다. 따라서 255로 나누어 주었고, -1을 해주어 기존 255값들을 0으로 만들어 주었습니다. 그 후, 음수 값들을 양수로 바꾸어 주기 위해 -1을 곱해준 것입니다.

 

mnist는 딥러닝의 매우 대표적인 예제이지만, 실제로 배포하는 측면에서, 저의 손글씨를 어떻게 인식시키질에 대한 의문이 있었는 데, 이해하는 데 조금은 도움이 된 것 같습니다. 

 

딥러닝 프레임워크를 활용해 문제를 해결해 실제 서비스를 구현하는 경우에도, 결국 실제 데이터와 input 데이터를 동일하게 전처리를 해주는 것이 필수적이라는 것을 알게 되었습니다. 처음에는 모델이 문제인지 알고, 무의미한 시간을 보내고 말았습니다.

반응형