ch0nny_log

[빅데이터분석] 딥러닝_13. 코렙에서 정상 이파리와 질병 이파리 분류 신경망 만들기 본문

빅데이터 분석(with 아이티윌)/deep learning

[빅데이터분석] 딥러닝_13. 코렙에서 정상 이파리와 질병 이파리 분류 신경망 만들기

chonny 2024. 10. 17. 16:36

▣ 코렙에서 정상 이파리와 질병 이파리 분류 신경망 만들기

 
#1. 정상 이파리와 질병 이파리 데이터를 다운로드 받습니다.

https://cafe.daum.net/oracleoracle/SpOP/283

훈련 4000장( 정상: 2000장, 질병: 2000장 )
테스트 100장

#2. 일반 컬러 사진을 신경망에 넣고 분류하는 모델 만드는 전체적인 과정

 

1. 원본 이미지를 작은 사이즈로 resize 합니다.

2. image_load 함수로 사진을 숫자 행렬로 변환

3. 정답 csv 파일을 생성

4. 정답 csv 을 위한 인코딩

5. 신경망을 생성

6. 신경망에 데이터를 넣고 학습시킴

7. 모델 성능 개선

8. 신경망 활용 사용자 인터페이스 생성

9. 전체코드를 github 에 올리기

 

실습 
1. 구글 코렙에 /content/drive/MyDrive/leaf 디렉토리를 만들고 train4000 폴더와 test100 폴더를 생성하시오 !


2. train4000.zip 파일과 test100.zip 을 코렙에 올리는데 train4000.zip 파일을 /content/drive/MyDrive/leaf/train4000 폴더에 압축을 풀고 test100.zip 파일을 /content/drive/MyDrive/leaf/test100 폴더에 압축을 풉니다.
!unzip  -uq  /content/drive/MyDrive/leaf/train4000.zip  -d  /content/drive/MyDrive/leaf/train4000

!ls -l /content/drive/MyDrive/leaf/train4000/*

!unzip  -uq  /content/drive/MyDrive/leaf/test100.zip  -d  /content/drive/MyDrive/leaf/test100

!ls -l /content/drive/MyDrive/leaf/test100/*​

3. /content/drive/MyDrive/leaf 밑에 train_resize 와 test_resize 폴더를 각각 만드시오 !


4. 원본 이미지가 256x256 사이즈의 이미지를 32x32 로 resize 해서 train_resize 폴더와 test_resize 폴더에 넣으시오 !
# 1. resize 하는데 필요한 모듈을 임폴트 합니다.
import   cv2 
import   os
import  numpy   as   np

#2.  원본 이미지가 있는 디렉토리를 지정합니다. 
path = '/content/drive/MyDrive/leaf/train4000'
file_list = os.listdir(path)  #  path 경로에 있는 이미지들을 하나씩 불러오는 코드
print(file_list)   # ['1.jpg', '10.jpg', '100.jpg', '1000.jpg', ....    ]  

#3. file_list 안에 있는 파일들을 하나씩 불러와서  32x32 로 리사이즈합니다.
for   k   in   file_list:  #  리스트안에 있는 파일들을 하나씩 빼내는 코드 
    img = cv2.imread( path + '/' + k )  #  이미지를 숫자로 변환 
    resize_img = cv2.resize( img, ( 32, 32 ), interpolation=cv2.INTER_CUBIC ) # 32X32로...
    cv2.imwrite('/content/drive/MyDrive/leaf/train_resize/' + k, resize_img ) # 이미지 저장​
# 1. resize 하는데 필요한 모듈을 임폴트 합니다.
import cv2
import os
import numpy as np

# 2. 원본 이미지가 있는 디렉토리를 지정합니다.
path = '/content/drive/MyDrive/leaf/test100'
file_list = os.listdir(path)  # path 경로에 있는 이미지들을 하나씩 불러오는 코드
print(file_list)  # ['1.jpg', '10.jpg', '100.jpg', '1000.jpg', ....    ]

# 3. file_list 안에 있는 파일들을 하나씩 불러와서 32x32 로 리사이즈합니다.
for k in file_list:  # 리스트안에 있는 파일들을 하나씩 빼내는 코드
    # Check if the file is an image file and not a hidden directory
    if k.startswith('.') or not (k.endswith('.jpg') or k.endswith('.png') or k.endswith('.jpeg')):
        continue  # Skip non-image files

    img = cv2.imread(path + '/' + k)  # 이미지를 숫자로 변환
    # Check if the image was loaded successfully
    if img is not None:
        resize_img = cv2.resize(img, (32, 32), interpolation=cv2.INTER_CUBIC)  # 32X32로...
        cv2.imwrite('/content/drive/MyDrive/leaf/test_resize/' + k, resize_img)  # 이미지 저장
    else:
        print(f"Failed to load image: {path + '/' + k}")  # Print an error message if image loading fails



5. 신경망에 이미지를 넣으려면 리사이즈한 사진을 숫자로 변경

 
# 신경망에 이미지를 넣으려면 리사이즈한 사진을 숫자로 변경을 해야하는데
#  사진을 숫자로 변경하는 함수를 다음과 같이 생성합니다.

train_images='/content/drive/MyDrive/leaf/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)  )​


6. test_resize에 있는 사진들도 위의 load_image 함수로 잘 변경이 되는지 확인하시오 

test_images='/content/drive/MyDrive/leaf/test_resize'

print(image_load(test_images))​

7. 정답 csv파일 생성하기
- 훈련데이터
  정상:1~2000번/질병:2001~4000번
- 테스트 데이터
  정상:1~50번/질병:51~100번

정상과 질병만 분류하는 이진 분류인데 정상을 0번으로 하고 질병을 1번으로 합니다.

훈련 데이터의 csv 파일을 0을 2000번, 1을 2000번 적을겁니다.
테스트 데이터의 csv 파일을 0을 50번, 1을 50번으로 해서 구성하면 됩니다.
path = '/content/drive/MyDrive/leaf/train_label.csv'

file = open( path, 'w' )  # 비어있는 파일 생성

# 숫자0 을 2000개, 숫자 1을 2000개 씁니다.
for  i  in range(1, 2001):
    file.write( str(0) + '\n')
for  i  in range(2001, 4001):
    file.write( str(1) + '\n') 

file.close()  # 저장합니다.​
path = '/content/drive/MyDrive/leaf/test_label.csv'

file = open( path, 'w' )  # 비어있는 파일 생성

# 숫자0을 50개, 숫자 1을 50개 씁니다.
for  i  in range(1, 51):
    file.write( str(0) + '\n')
for  i  in range(51, 101):
    file.write( str(1) + '\n') 

file.close()  # 저장합니다.


8.  정답 csv 파일을 불러와서 one hot encoding 하는 함수를 생성하시오 !

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

train_label = '/content/drive/MyDrive/leaf/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 

train_label = '/content/drive/MyDrive/leaf/train_label.csv'
print( label_load(train_label) )​

# 테스트 데이터도 원핫  인코딩이 잘되는지 확인합니다. 

test_label = '/content/drive/MyDrive/leaf/test_label.csv'
print( label_load(test_label) )

# 설명: 오차함수에 정답과 예측값이 들어가서 오차가 출력되는데
# 오차함수에 정답을 넣을 때는 위와 같이 one hot encoding 을 해줘야합니다.​


10. 코렙에 텐써 플로우 버젼이 어떻게 되는지 확인합니다.

import  tensorflow  as  tf
print( tf.__version__ )

11.위의 image_load 와 label_load 함수를 이용해서 신경망에 입력할 이미지들을  숫자로 변경하는 코드를 수행하시오 !
# 2. 정규화를 진행합니다.

x_train = x_train / 255.0
x_test = x_test / 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(Flatten() ) # 완전연결계층에 들어갈수 있도록 이미지(피쳐맵들)를 1차원으로 변경합니다.
model.add(Dense(50, activation = 'sigmoid', input_shape = (784, )))  # 1층
model.add(Dense(50, activation = 'sigmoid') ) # 2층 은닉층 
model.add(Dense( 2, activation = 'softmax'))  # 3층 출력층 

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

#6. 모델을 훈련시킵니다. 

history = model.fit(x_train, y_train, 
                         epochs = 30,  # 30에폭
                         batch_size = 100,
                         validation_data=(x_test, y_test) )

# 7.모델을 평가합니다. (오차, 정확도가 출력됩니다.)
model.evaluate(x_test, y_test)

train_acc_list=history.history['acc']
train_acc_list

test_acc_list=history.history['val_acc']
test_acc_list

import  matplotlib.pyplot  as  plt

x = np.arange( len(train_acc_list) )
plt.plot( x, train_acc_list, label='train acc')
plt.plot( x, test_acc_list, label='test acc',  linestyle='--')
plt.ylim(0, 1)
plt.legend(loc='lower right')
plt.xlabel('epochs')
plt.ylabel('accuracy')
plt.show()

 


12.배치 정규화와 드롭아웃 추가한 코드
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, Dropout, BatchNormalization  # CNN, 완전 연결계층, 드롭아웃, 배치 정규화를 구성하기 위한 모듈
from tensorflow.keras.callbacks import EarlyStopping  # 얼리 스탑핑을 위한 모듈
from tensorflow.keras.utils import to_categorical  # one-hot encoding을 위한 모듈
import numpy as np
import matplotlib.pyplot as plt

tf.random.set_seed(777)

# 이미지와 라벨 데이터를 불러오는 코드
train_images = '/content/drive/MyDrive/leaf/train_resize'
test_images = '/content/drive/MyDrive/leaf/test_resize'
train_label = '/content/drive/MyDrive/leaf/train_label.csv'
test_label = '/content/drive/MyDrive/leaf/test_label.csv'

x_train = image_load(train_images)
x_test = image_load(test_images)
y_train = label_load(train_label)
y_test = label_load(test_label)

# 정규화 진행
x_train = x_train / 255.0
x_test = x_test / 255.0
print(x_train.shape)  # (4000, 32, 32, 3)

# 모델 구성
model = Sequential()
model.add(Conv2D(100, kernel_size=(5, 5), input_shape=(32, 32, 3), padding='same', activation='relu'))
model.add(BatchNormalization())  # 배치 정규화 추가
model.add(MaxPooling2D(pool_size=(2, 2), padding='same'))

model.add(Flatten())
model.add(Dense(50, activation='relu'))
model.add(BatchNormalization())  # 배치 정규화 추가
model.add(Dropout(0.2))  # 드롭아웃 추가 (50% 비율)

model.add(Dense(50, activation='relu'))
model.add(Dropout(0.2))  # 드롭아웃 추가 (50% 비율)

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

# 모델 컴파일
model.compile(optimizer='Adam',
              loss='categorical_crossentropy',
              metrics=['acc'])

# 얼리 스탑핑 설정 (validation accuracy가 10번 향상되지 않으면 학습 중단)
early_stopping = EarlyStopping(monitor='val_acc', patience=10, restore_best_weights=True)

# 모델 훈련
history = model.fit(x_train, y_train,
                    epochs=100,  # 최대 100 에폭
                    batch_size=100,
                    validation_data=(x_test, y_test),
                    callbacks=[early_stopping])  # 얼리 스탑핑 콜백 추가

# 모델 평가
model.evaluate(x_test, y_test)

# 훈련 및 검증 정확도 시각화
train_acc_list = history.history['acc']
test_acc_list = history.history['val_acc']

x = np.arange(len(train_acc_list))
plt.plot(x, train_acc_list, label='train acc')
plt.plot(x, test_acc_list, label='test acc', linestyle='--')
plt.ylim(0, 1)
plt.legend(loc='lower right')
plt.xlabel('epochs')
plt.ylabel('accuracy')
plt.show()

# 모델 저장

model.save('/content/drive/MyDrive/leaf/my_model.h5') # 모델을 h5 파일로 저장​


13. 위의 코드에 배치 정규화와 드롭아웃과 모델 저장하는 코드까지 추가해서 돌리기

import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, BatchNormalization, Dropout
from tensorflow.keras.callbacks import EarlyStopping

# 모델 구성 시작
model = Sequential()

# 첫 번째 컨볼루션 레이어 (CONV1) + 배치 정규화 + 두 번째 컨볼루션 레이어 (factorization)
model.add(Conv2D(32, (3, 3), padding='same', activation='relu', input_shape=(32, 32, 3)))
model.add(Conv2D(32, (3, 3), padding='same', activation='relu'))
model.add(BatchNormalization())
model.add(MaxPooling2D(pool_size=(2, 2), strides=2, padding='same'))  # 첫 번째 풀링 레이어

# 두 번째 컨볼루션 레이어 (CONV2) + 배치 정규화 + 풀링 레이어
model.add(Conv2D(64, (3, 3), padding='same', activation='relu'))
model.add(BatchNormalization())
model.add(MaxPooling2D(pool_size=(2, 2), strides=2, padding='same'))  # 두 번째 풀링 레이어

# 세 번째 컨볼루션 레이어 (CONV3) + 배치 정규화 + 풀링 레이어
model.add(Conv2D(128, (3, 3), padding='same', activation='relu'))
model.add(BatchNormalization())
model.add(MaxPooling2D(pool_size=(2, 2), strides=2, padding='same'))  # 세 번째 풀링 레이어

# 네 번째 컨볼루션 레이어 (CONV4) + 배치 정규화 + 풀링 레이어
model.add(Conv2D(256, (3, 3), padding='same', activation='relu'))
model.add(BatchNormalization())
model.add(MaxPooling2D(pool_size=(2, 2), strides=2, padding='same'))  # 네 번째 풀링 레이어

# 완전 연결 계층 (Fully Connected Layers)
model.add(Flatten())  # 평탄화
model.add(Dense(2560, activation='relu'))  # 첫 번째 FC 레이어
model.add(Dropout(0.5))  # 드롭아웃 추가
model.add(Dense(1000, activation='relu'))  # 두 번째 FC 레이어

# 출력층 (2개의 클래스, softmax 활성화 함수 사용)
model.add(Dense(2, activation='softmax'))

# 모델 요약 출력
model.summary()

# 모델 컴파일
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])

# 얼리 스토핑 설정 (검증 정확도가 10번 향상되지 않으면 중단)
early_stopping = EarlyStopping(monitor='val_accuracy', patience=10, restore_best_weights=True)

# 모델 훈련 (데이터는 가상의 변수로 사용 중)
history = model.fit(x_train, y_train,
                    epochs=100,
                    batch_size=64,
                    validation_data=(x_test, y_test),
                    callbacks=[early_stopping])

# 모델 평가
test_loss, test_acc = model.evaluate(x_test, y_test)
print(f'테스트 정확도: {test_acc}')

# 학습 결과 시각화 (정확도 그래프)
import matplotlib.pyplot as plt
plt.plot(history.history['accuracy'], label='train accuracy')
plt.plot(history.history['val_accuracy'], label='validation accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend()
plt.show()​


 

 

저장된 모델을 불러와서 이미지 1장을 맞추는 코드를 구현하시오 !
import tensorflow as tf
from tensorflow.keras.models import load_model
import numpy as np
from PIL import Image

# 모델 불러오기
model = load_model('c:\\data\\my_model.h5')

# 이미지를 불러오는 함수 정의 (모델에 맞는 크기로 이미지를 조정)
def load_and_process_image(image_path):
    img = Image.open(image_path)
    img = img.resize((32, 32))  # 모델 입력 크기에 맞게 32x32로 크기 조정
    img = np.array(img)  # 이미지 배열로 변환
    img = img / 255.0  # 정규화 (모델 학습 시 정규화했으므로 동일하게 적용)
    img = np.expand_dims(img, axis=0)  # 배치 차원 추가 (1, 32, 32, 3)
    return img

# 이미지 경로 설정
image_path = '테스트 할 이미지 경로'

# 이미지 로드 및 처리
processed_image = load_and_process_image(image_path)

# 예측 수행
predictions = model.predict(processed_image)

# 결과 출력
class_names = ['Normal', 'Disease']  # 클래스 이름 설정
predicted_class = np.argmax(predictions)  # 예측된 클래스 (0 또는 1)
predicted_probability = predictions[0][predicted_class]  # 예측된 클래스의 확률

print(f'Predicted class: {class_names[predicted_class]}')
print(f'Confidence: {predicted_probability * 100:.2f}%')​

정상 이파리: image_path = 'C:\\data\\train4000\\1.jpg'

질병 이파리: image_path = 'C:\\data\\train4000\\18944.jpg'

1. 5기 임미선 선배가 만든 신경망으로 코드를 구현하기

import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, BatchNormalization, Dropout
from tensorflow.keras.callbacks import EarlyStopping

# 모델 구성 시작
model = Sequential()

# 첫 번째 컨볼루션 레이어 (CONV1) + 배치 정규화 + 두 번째 컨볼루션 레이어 (factorization)
model.add(Conv2D(32, (3, 3), padding='same', activation='relu', input_shape=(32, 32, 3)))
model.add(Conv2D(32, (3, 3), padding='same', activation='relu'))
model.add(BatchNormalization())
model.add(MaxPooling2D(pool_size=(2, 2), strides=2, padding='same'))  # 첫 번째 풀링 레이어

# 두 번째 컨볼루션 레이어 (CONV2) + 배치 정규화 + 풀링 레이어
model.add(Conv2D(64, (3, 3), padding='same', activation='relu'))
model.add(BatchNormalization())
model.add(MaxPooling2D(pool_size=(2, 2), strides=2, padding='same'))  # 두 번째 풀링 레이어

# 세 번째 컨볼루션 레이어 (CONV3) + 배치 정규화 + 풀링 레이어
model.add(Conv2D(128, (3, 3), padding='same', activation='relu'))
model.add(BatchNormalization())
model.add(MaxPooling2D(pool_size=(2, 2), strides=2, padding='same'))  # 세 번째 풀링 레이어

# 네 번째 컨볼루션 레이어 (CONV4) + 배치 정규화 + 풀링 레이어
model.add(Conv2D(256, (3, 3), padding='same', activation='relu'))
model.add(BatchNormalization())
model.add(MaxPooling2D(pool_size=(2, 2), strides=2, padding='same'))  # 네 번째 풀링 레이어

# 완전 연결 계층 (Fully Connected Layers)
model.add(Flatten())  # 평탄화
model.add(Dense(2560, activation='relu'))  # 첫 번째 FC 레이어
model.add(Dropout(0.5))  # 드롭아웃 추가
model.add(Dense(1000, activation='relu'))  # 두 번째 FC 레이어

# 출력층 (2개의 클래스, softmax 활성화 함수 사용)
model.add(Dense(2, activation='softmax'))

# 모델 요약 출력
model.summary()

# 모델 컴파일
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])

# 얼리 스토핑 설정 (검증 정확도가 10번 향상되지 않으면 중단)
early_stopping = EarlyStopping(monitor='val_accuracy', patience=10, restore_best_weights=True)

# 모델 훈련 (데이터는 가상의 변수로 사용 중)
history = model.fit(x_train, y_train,
                    epochs=100,
                    batch_size=64,
                    validation_data=(x_test, y_test),
                    callbacks=[early_stopping])

# 모델 평가
test_loss, test_acc = model.evaluate(x_test, y_test)
print(f'테스트 정확도: {test_acc}')

# 학습 결과 시각화 (정확도 그래프)
import matplotlib.pyplot as plt
plt.plot(history.history['accuracy'], label='train accuracy')
plt.plot(history.history['val_accuracy'], label='validation accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend()
plt.show()​

2. 이파리 모델을 손쉽게 사용할 수 있는 화면 인터페이스를 생성하기
import tkinter as tk
from tkinter import filedialog
from PIL import Image, ImageTk
import numpy as np
import tensorflow as tf
import cv2  # 이미지를 전문으로 전처리하는 모듈

# 신경망 모델 로드 (질병 잎사귀 분류 모델)
model = tf.keras.models.load_model('c:\\data\\my_model.h5')

# 타겟 딕셔너리 (정상 및 질병에 해당하는 레이블)
target_dict = {
    0: 'Healthy',
    1: 'Disease',
}

# 이미지 전처리 함수
def preprocess_image(image_path):
    # 이미지 불러오기
    img = cv2.imread(image_path)

    # 이미지 크기를 32x32로 조정 (모델 입력 크기)
    resized_img = cv2.resize(img, (32, 32))

    # RGB 이미지를 그대로 사용
    img_array = np.array(resized_img) / 255.0  # 정규화
    img_array = img_array.reshape(1, 32, 32, 3)  # CNN 입력 형태로 변환 (배치 크기 포함)
    
    return img_array

# 이미지 선택 및 표시
def select_image():
    global file_path
    file_path = filedialog.askopenfilename()  # 선택한 이미지 경로 저장
    if not file_path:
        return

    # 선택한 이미지 표시
    img_display = cv2.imread(file_path)
    img_display = cv2.resize(img_display, (400, 400))  # 화면에 출력할 크기로 조정
    img_display = cv2.cvtColor(img_display, cv2.COLOR_BGR2RGB)  # OpenCV는 BGR, tkinter는 RGB를 사용함
    img_tk = ImageTk.PhotoImage(Image.fromarray(img_display))
    
    # 이미지 위젯 업데이트
    label_image.config(image=img_tk)
    label_image.image = img_tk

# 예측 및 결과 표시
def predict_image():
    if not file_path:
        label_prediction.config(text="No image selected")
        return

    # 이미지를 전처리하여 예측
    img = preprocess_image(file_path)
    prediction = model.predict(img)
    predicted_label = np.argmax(prediction)
    
    # 라벨 번호에 해당하는 타겟 텍스트
    predicted_text = target_dict.get(predicted_label, "Unknown")

    # 예측된 클래스의 확률
    predicted_probability = prediction[0][predicted_label]  # 예측된 클래스의 확률
    
    # 예측 결과 업데이트
    label_prediction.config(text=f"Prediction: {predicted_text} ({predicted_probability:.4f})")

# tkinter 윈도우 설정
root = tk.Tk()
root.title("Leaf Disease Classifier")
root.geometry("600x700")  # 기본 창 크기 설정

# 이미지 선택 버튼 (위쪽에 배치)
button_select = tk.Button(root, text="Select Image", command=select_image)
button_select.pack(pady=10)  # 위쪽에 공간을 추가

# 이미지 출력할 라벨 (이미지 박스)
label_image = tk.Label(root)
label_image.pack(pady=10)

# 예측 버튼 (이미지 아래에 배치)
button_predict = tk.Button(root, text="Predict", command=predict_image)
button_predict.pack(pady=10)

# 예측 결과 출력할 라벨 (예측 버튼 아래에 배치)
label_prediction = tk.Label(root, text="", font=("Helvetica", 16))
label_prediction.pack(pady=20)

# tkinter 실행
root.mainloop()​


3. 위의 화면에 출력되는 메세지가 영어가 아닌 한글로 ‘정상’,’질병’ 으로 출력되게하기

import tkinter as tk
from tkinter import filedialog
from PIL import Image, ImageTk
import numpy as np
import tensorflow as tf
import cv2  # 이미지를 전문으로 전처리하는 모듈

# 신경망 모델 로드 (질병 잎사귀 분류 모델)
model = tf.keras.models.load_model('c:\\data\\my_model.h5')

# 타겟 딕셔너리 (정상 및 질병에 해당하는 레이블)
target_dict = {
    0: '정상',
    1: '질병',
}

# 이미지 전처리 함수
def preprocess_image(image_path):
    # 이미지 불러오기
    img = cv2.imread(image_path)

    # 이미지 크기를 32x32로 조정 (모델 입력 크기)
    resized_img = cv2.resize(img, (32, 32))

    # RGB 이미지를 그대로 사용
    img_array = np.array(resized_img) / 255.0  # 정규화
    img_array = img_array.reshape(1, 32, 32, 3)  # CNN 입력 형태로 변환 (배치 크기 포함)
    
    return img_array

# 이미지 선택 및 표시
def select_image():
    global file_path
    file_path = filedialog.askopenfilename()  # 선택한 이미지 경로 저장
    if not file_path:
        return

    # 선택한 이미지 표시
    img_display = cv2.imread(file_path)
    img_display = cv2.resize(img_display, (400, 400))  # 화면에 출력할 크기로 조정
    img_display = cv2.cvtColor(img_display, cv2.COLOR_BGR2RGB)  # OpenCV는 BGR, tkinter는 RGB를 사용함
    img_tk = ImageTk.PhotoImage(Image.fromarray(img_display))
    
    # 이미지 위젯 업데이트
    label_image.config(image=img_tk)
    label_image.image = img_tk

# 예측 및 결과 표시
def predict_image():
    if not file_path:
        label_prediction.config(text="No image selected")
        return

    # 이미지를 전처리하여 예측
    img = preprocess_image(file_path)
    prediction = model.predict(img)
    predicted_label = np.argmax(prediction)
    
    # 라벨 번호에 해당하는 타겟 텍스트
    predicted_text = target_dict.get(predicted_label, "Unknown")

    # 예측된 클래스의 확률
    predicted_probability = prediction[0][predicted_label]  # 예측된 클래스의 확률
    
    # 예측 결과 업데이트
    label_prediction.config(text=f"Prediction: {predicted_text} ({predicted_probability:.4f})")

# tkinter 윈도우 설정
root = tk.Tk()
root.title("Leaf Disease Classifier")
root.geometry("600x700")  # 기본 창 크기 설정

# 이미지 선택 버튼 (위쪽에 배치)
button_select = tk.Button(root, text="Select Image", command=select_image)
button_select.pack(pady=10)  # 위쪽에 공간을 추가

# 이미지 출력할 라벨 (이미지 박스)
label_image = tk.Label(root)
label_image.pack(pady=10)

# 예측 버튼 (이미지 아래에 배치)
button_predict = tk.Button(root, text="Predict", command=predict_image)
button_predict.pack(pady=10)

# 예측 결과 출력할 라벨 (예측 버튼 아래에 배치)
label_prediction = tk.Label(root, text="", font=("Helvetica", 16))
label_prediction.pack(pady=20)

# tkinter 실행
root.mainloop()