▩  설현과 수지 인식 신경망 만들기 수업 노트 전체 

 잘 선별한 수지 사진 100장과 설현 사진 100장을 하나의 폴더에 모아져 있어야합니다.
 수지사진은 1.jpg ~ 100.jpg 로 번호가 붙어있어야하고 
 설현사진은 101.jpg ~ 200.jpg 로 변호가 붙어있어야 합니다.

        **<코랩에서 진행>**
#0.  구글드라이브 마운트
from google.colab import drive
drive.mount('/content/drive')
								# Mounted at /content/drive
								

#0.  수지 사진 100장, 설현 사진 100장을 구글 드라이브에 /content/drive/MyDrive/pretty 폴더에 올리세요 ~~
		<https://cafe.daum.net/oracleoracle/SmRD/381> 
		- zip 파일 상태로 
		- 데이터  :  잘 선별한 상태
				- 다른 사람과 같이 있는 사진 x  ->  혼자 있는 사진
				- 이상한, 엉뚱한 사진 x 

#1.  train200 이라는 폴더를 코렙에 생성하시오 
/content/drive/MyDrive/pretty 폴더 밑에 생성

#2. 코렙에 올린 사진 압축파일의 압축을 풉니다. 
!unzip  -uq  /content/drive/MyDrive/pretty/image_all.zip  -d /content/drive/MyDrive/pretty/train200

#3. train_resize 라는 폴더를 만듭니다. 
!mkdir /content/drive/MyDrive/pretty/train_resize
		- 리눅스 명령어 

#4. 32x32 로 사진들을 전부 resize 합니다.

		# 훈련 이미지를 resize 합니다.
import  cv2
import  os 
import  numpy  as np

path = "/content/drive/MyDrive/pretty/train200"    # 원본위치
file_list = os.listdir(path)   # 파일이름 불러오는 부분 

for k in file_list:     # 리스트안에 있는 파일들을 하나씩 빼내는 코드 
    img = cv2.imread(path + '/' + k) #  이미지 데이터를 행렬로 숫자로 변환합니다. 
    resize_img = cv2.resize(img, (32 , 32), interpolation=cv2.INTER_CUBIC)  
    cv2.imwrite( '/content/drive/MyDrive/pretty/train_resize/' + k, resize_img)   

# train_resize 에 resize 된 이미지들이 몇개가 있는지 확인합니다.
!ls /content/drive/MyDrive/pretty/train_resize | wc -l
								# 200

#5. 정답 csv 파일을 생성합니다.
				# 수지를 0번으로하고 설현을 1번으로 하겠습니다.
path='/content/drive/MyDrive/pretty/train_label.csv'
file = open( path, 'w' )
 
# 숫자 0을 100개 , 숫자 1을 100개 씁니다. 
for   i   in   range( 1, 101 ):
    file.write( str(0) + '\\n' )
for  i  in  range( 101, 201 ):
    file.write( str(1) + '\\n' ) 

file.close()

#6. 지난번에 만들었던 image_load 함수와 label_load 함수를 생성하시오 !

<https://cafe.daum.net/oracleoracle/SmRD/387> <--- 전체 코드, 게시글 387번

train_images='/content/drive/MyDrive/pretty/train_resize'

import   os
import   re
import   cv2

def  image_load(path):
    #1. 사진  파일명에서 숫자부분만 취합니다.
    file_list  = os.listdir(path)   # path 디렉토리에 파일명들을 불러옵니다.
    file_name = []
    for   i   in   file_list:
        a = int( re.sub('[^0-9]', '',  i ) )  #  i 가 숫자가 아니라면 null 로 변경해라
        file_name.append(a)
    file_name.sort()
 
    #2. 디렉토리와 숫자 파일명을 이어 붙입니다.
    file_res = [ ]
    for   j   in  file_name:    
        file_res.append( path + '/' + str(j) + '.jpg')   # 전체 경로 + 파일명을 생성

    #3. 위에서만든 디렉토리와 파일명을 가지고 사진을 숫자로 변경합니다.
    image= [ ]
    for  k   in  file_res:
        img = cv2.imread(k)   # 이미지를 숫자로 변경합니다.
        image.append(img)

    return  np.array(image)

print ( image_load(train_images)  )

from  tensorflow.keras.utils   import   to_categorical
import  csv
import  numpy  as  np

train_label = '/content/drive/MyDrive/pretty/train_label.csv'

def  label_load(path):
    file = open(path)
    labeldata = csv.reader(file)
    labellist = [ ]
    for  i  in  labeldata:
        labellist.append(i)
 
    label = np.array( labellist )   # 넘파이 배열로 변환
    label = label.astype(int)   # 숫자로 변환      
    label = to_categorical(label)  #  [ 1,  0] 또는 [0, 1] 로 one hot encoding 합니다.
    return  label

print ( label_load(train_label) )

#7.  수지와 설현 사진을 분류하는 신경망을 학습 시키시오 !

# 1. 필요한 패키지 가져오는 코드
import tensorflow as tf   # 텐써 플로우 2.0
from tensorflow.keras.datasets.mnist import load_data  # 텐써플로우에 내장되어있는
                                                                         # mnist 데이터를 가져온다.
from tensorflow.keras.models import Sequential  # 모델을 구성하기 위한 모듈
from tensorflow.keras.layers import Dense, Conv2D, MaxPooling2D, Flatten ,BatchNormalization,Dropout # CNN, 완전 연결계층을 구성하기 위한 모듈
from tensorflow.keras.utils import to_categorical # one encoding 하는 모듈

tf.random.set_seed(777)

# 데이터를 가져오는 코드
train_images='/content/drive/MyDrive/pretty/train_resize'
train_label = '/content/drive/MyDrive/pretty/train_label.csv'

x_train = image_load( train_images)
y_train = label_load(train_label)

# 2. 정규화를 진행합니다.
x_train = x_train / 255.0
print(x_train.shape) # (4000, 32, 32, 3)

# 3. 모델을 구성합니다. 3층 신경망으로 구성
model = Sequential()
model.add(Conv2D(100, kernel_size=(5,5), input_shape=(32,32,3), padding='same', activation='relu') )
model.add(MaxPooling2D(pool_size=(2,2), padding='same') ) # 이미지를 선명하게 해주는 층
model.add(BatchNormalization())
model.add(Dropout(0.2))

model.add(Flatten() ) # 완전연결계층에 들어갈수 있도록 이미지(피쳐맵들)를 1차원으로 변경합니다.
model.add(Dense(50, activation = 'relu'))  # 1층
model.add(BatchNormalization())
model.add(Dropout(0.2))

model.add(Dense(50, activation = 'relu') ) # 2층 은닉층
model.add(BatchNormalization())
model.add(Dropout(0.2))

model.add(Dense( 2, activation = 'softmax'))  # 3층 출력층

# 5. 모델을 설정합니다. ( 경사하강법, 오차함수를 정의해줍니다. )
model.compile(optimizer='Adam',
                     loss = 'categorical_crossentropy',
                     metrics=['acc'])  # 학습과정에서 정확도를 보려고

#6. 모델을 훈련시킵니다.
history = model.fit(x_train, y_train,
                         epochs = 200,  # 30에폭
                         batch_size = 10 )

# 7.모델을 평가합니다. (오차, 정확도가 출력됩니다.)
#model.evaluate(x_test, y_test)
model.save('/content/drive/MyDrive/pretty/suji_model.keras')

								# Epoch 200/200
								# 20/20 ━━━━━━━━━━━━━━━━━━━━ 1s 57ms/step - acc: 1.0000 - loss: 0.0031
▩  신경망 활용 화면 개발   <로컬 주피터 노트북> 

예제1.  신경망 모델을 내리는 코드 
		model.save('/content/drive/MyDrive/pretty/suji_model.keras')
		<https://cafe.daum.net/oracleoracle/SmRD/404> <--- 전체 코드 

예제4. 코렙에서  여러분들이 생성한 모델을 로컬 컴퓨터로 다운로드 받아
          c 드라이브 밑에  data 폴더 밑에 둡니다.

예제5.  로컬 주피터 노트북에서 다운 받은 모델을 불러옵니다.
from  tensorflow.keras.models  import   load_model   # 만들어진 모델을 불러오는 함수

new_model = load_model('c:\\\\data\\\\suji_model.keras')
new_model                #  built=True

예제6.  사진 한장을 모델에 넣고 잘 예측하는지 확인합니다.
<https://cafe.daum.net/oracleoracle/SmRD/399> 

#0. 신경망에 넣어서 맞추고 싶은 사진을 선택합니다.

file_path='C:\\\\image_all\\\\1.jpg'    

#※ 주의사항 : 경로에 한글이 포함되어 있으면 안됩니다. 

#1. 필요한 패키지를 불러옵니다. 
import tensorflow as  tf
import cv2

# 설명: cv2 가 없다고 나오면 다음과 같이 설치합니다. 

#!pip  install  opencv-python 

#2. 이미지를 숫자로 변환합니다. 
img = cv2.imread(file_path)  # 이미지를 숫자로 변환하는 코드 
img

#3. 32 x 32 로 reshape 합니다.  
import  matplotlib.pyplot  as plt 
resize_img = cv2.resize( img, (32, 32), interpolation = cv2.INTER_CUBIC)                    

# 설명: 어제 만들었던 신경망이 학습한 사진들이 32x32 로 학습 했기 때문에
# 예측할 사진도 32x32로 resize 해줘야합니다. 

# 4. 학습 시킨 모델 불러오는 코드
from tensorflow.keras.models import load_model
new_model = load_model('c:\\\\data10\\\\suji_model.h5')

#5. 리사이즈한 사진을 4차원으로 변경하고 정규화 작업을 수행 
x4 = tf.reshape(resize_img,(1,32,32,3))
x4 = x4/255  # 정규화

#6. 모델에 이미지 넣고 예측을 합니다. 
results = new_model.predict(x4)
a= np.argmax(results)   #  [0.6, 0.4]  ---> 0,  [ 0.2, 0.8 ] ---> 1 
print(a)

#7.  0번이면 '수지', 1번이면 '설현' 으로 매칭해줍니다. 
target_dict = {
   0: '수지',
   1: '설현'
}

print( target_dict[a] )

#8. 시각화 합니다. 

import cv2
import matplotlib.pyplot as plt

# 이미지 파일을 읽어옵니다.

image = cv2.imread(file_path)

# 이미지를 BGR에서 RGB로 변환합니다.
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

# 이미지를 시각화합니다.
plt.imshow(image)
plt.axis('off')  # 축과 눈금 숨기기
plt.show()

예제7. 화면 개발을 위한 패키지들을 임폴트해서 오류가 나는지 확인합니다.

<https://cafe.daum.net/oracleoracle/SmRD/400>

# 게임화면 또는 특정 목적의 사용자 인터페이스를 구현 할 수 있는 tkinter 모듈을 임폴트 받습니다. 
import tkinter as tk
from tkinter import filedialog
from tkinter import *
import numpy as np

# 이미지 데이터 전처리하는 모듈과 텐써 플로우 케라스 load_model 모듈을 임폴트 합니다. 
from PIL import ImageTk, Image
import numpy  as  np
from keras.models import load_model
import cv2

# 화면을 띄웁니다.

top=tk.Tk()  # tkinter 의 Tk 클래스를 이용해서 top 이라는 객체를 만듭니다. 
top.geometry('800x600') # 사용자 화면 가로 세로 사이즈를 지정합니다. 
top.title('수지와 설현 분류 Classification') # 맨 위에 막대에 제목을 적어줍니다. 
top.configure(background='#CDCDCD')  # 맨위에 막대에 색깔을 회색으로 지정합니다. 
label=Label(top,background='#CDCDCD', font=('arial',15,'bold'))
sign_image = Label(top)

def  classify(file_path):
    #1. 필요한 패키지를 불러옵니다. 
    import tensorflow as  tf
    import cv2

    #2. 이미지가 있는 위치를 지정합니다.
    img = cv2.imread(file_path)  # 이미지를 숫자로 변환하는 코드 
    #img = cv2.bitwise_not(img)

    #3. 28x 28 로 reshape 합니다.
    import  matplotlib.pyplot  as plt 
    resize_img = cv2.resize( img, (32, 32), interpolation = cv2.INTER_CUBIC)                    

    #4. 다음 코드를 이용해서 흑백으로 변경합니다. 
    import numpy as np
    #x2 =tf.image.rgb_to_grayscale(resize_img)

    # 5. 학습 시킨 모델 불러오는 코드
    from tensorflow.keras.models import load_model
    new_model = load_model('c:\\\\data100\\\\suji_model.h5')

    x4 = tf.reshape(resize_img,(1,32,32,3))  # 컬러 사진을 인식할 수 있게 사이즈 설정
    x4 = x4/255  # 정규화

    results = new_model.predict(x4)
    a= np.argmax(results)

    #7. 9번의 상품이 뭔지 확인하기 

    target_dict = {
     0: '수지',
     1: '설현'
    }

    sign = target_dict[a]

    label.configure(foreground='#011638', text=sign) 

def show_classify_button(file_path): # 분류하는 버튼을 구현하는 함수
    classify_b=Button(top,text="Classify Image",
    command=lambda: classify(file_path), padx=10,pady=5)
    classify_b.configure(background='#364156', foreground='white',font=('arial',10,'bold'))
    classify_b.place(relx=0.79,rely=0.46)
    
def upload_image():  # 이미지를 업로드하는 버튼을 구현하는 함수 
    try:
        file_path=filedialog.askopenfilename()
        uploaded=Image.open(file_path)
        uploaded.thumbnail(((top.winfo_width()/2.25),(top.winfo_height()/2.25)))
        im=ImageTk.PhotoImage(uploaded)
        sign_image.configure(image=im)
        sign_image.image=im
        label.configure(text='')
        show_classify_button(file_path)
    except:
        pass
    
# 위에서 만든 함수들을 가지고 실행하는 코드들
upload=Button(top,text="Upload an image",command=upload_image,padx=10,pady=5)
upload.configure(background='#364156', foreground='white',font=('arial',10,'bold'))
upload.pack(side=BOTTOM,pady=50)
sign_image.pack(side=BOTTOM,expand=True)
label.pack(side=BOTTOM,expand=True)
heading = Label(top, text="수지와 설현 분류",pady=20, font=('arial',20,'bold'))
heading.configure(background='#CDCDCD',foreground='#364156')
heading.pack()
top.mainloop()