ABC 부트캠프 데이터 탐험가 4기

[26 일] ABC 부트캠프 : 머신러닝 팀 프로젝트 (2)

marriina 2024. 8. 8. 17:00
import cv2  # OpenCV 라이브러리 가져오기
import numpy as np  # NumPy 라이브러리 가져오기
import matplotlib.pyplot as plt  # Matplotlib의 pyplot 모듈 가져오기
import keras  # Keras 라이브러리 가져오기
import matplotlib.font_manager as fm  # Matplotlib의 폰트 관리 모듈 가져오기

# 이미지를 출력하는 함수 정의
def plot_images(n_row: int, n_col: int, image: list[np.array]) -> None:
    fig = plt.figure()  # 새로운 그림 객체 생성
    (fig, ax) = plt.subplots(n_row, n_col, figsize=(n_col, n_row))  # 서브플롯 생성
    for i in range(n_row):  # 행을 반복
        for j in range(n_col):  # 열을 반복
            if n_row <= 1:  # 행이 1일 경우
                axis = ax[j]  # 축 선택
            else:
                axis = ax[i, j]  # 다차원 배열에서 축 선택
                axis.get_xaxis().set_visible(False)  # x축 숨기기
                axis.get_yaxis().set_visible(False)  # y축 숨기기
                axis.imshow(image[i * n_col + j])  # 이미지 표시
    plt.show()  # 그림 표시
    return None

# picnic 이미지를 읽어와서 리스트에 저장
picnic_images = list()
for i in range(150):  # 150개의 이미지에 대해 반복
    file = './picnic/' + 'picnic ({0}).jpg'.format(i + 1)  # 파일 경로 생성
    img = cv2.imread(file)  # 이미지 읽기
    img = cv2.resize(img, (64, 64))  # 이미지 크기 조정
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)  # 색상 변환
    picnic_images.append(img)  # 리스트에 추가

# 이미지를 출력하는 함수 호출
plot_images(n_row=3, n_col=5, image=picnic_images)

# umbrella 이미지를 읽어와서 리스트에 저장
umb_images = []
for i in range(150):  # 150개의 이미지에 대해 반복
    file = './umb/' + 'umb ({0}).jpg'.format(i + 1)  # 파일 경로 생성
    img = cv2.imread(file)  # 이미지 읽기
    img = cv2.resize(img, (64, 64))  # 이미지 크기 조정
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)  # 색상 변환
    umb_images.append(img)  # 리스트에 추가

# 이미지를 출력하는 함수 호출
plot_images(n_row=3, n_col=5, image=umb_images)

# pet 이미지를 읽어와서 리스트에 저장
pat_images = []
for i in range(150):  # 150개의 이미지에 대해 반복
    file = './pat/' + 'pat ({0}).jpg'.format(i + 1)  # 파일 경로 생성
    img = cv2.imread(file)  # 이미지 읽기
    img = cv2.resize(img, (64, 64))  # 이미지 크기 조정
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)  # 색상 변환
    pat_images.append(img)  # 리스트에 추가

# 이미지를 출력하는 함수 호출
plot_images(n_row=3, n_col=5, image=pat_images)

# cafe_cup 이미지를 읽어와서 리스트에 저장
cafe_cup_images = []
for i in range(150):  # 150개의 이미지에 대해 반복
    file = './cafe_cup/' + 'cafe_cup ({0}).jpg'.format(i + 1)  # 파일 경로 생성
    img = cv2.imread(file)  # 이미지 읽기
    img = cv2.resize(img, (64, 64))  # 이미지 크기 조정
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)  # 색상 변환
    cafe_cup_images.append(img)  # 리스트에 추가

# 이미지를 출력하는 함수 호출
plot_images(n_row=3, n_col=5, image=cafe_cup_images)

# 학습할 데이터와 정답 데이터 생성
X = picnic_images + umb_images + pat_images + cafe_cup_images  # 모든 이미지 리스트 결합
y = ([[1, 0, 0, 0]] * len(picnic_images) +
     [[0, 1, 0, 0]] * len(umb_images) +
     [[0, 0, 1, 0]] * len(pat_images) +
     [[0, 0, 0, 1]] * len(cafe_cup_images))  # 각 클래스에 대한 정답 데이터 생성
# 넘파이 배열로 변환
X = np.array(X)  # 이미지 데이터
y = np.array(y)  # 정답 데이터

# CNN 모델 정의
model = keras.models.Sequential([keras.Input(shape=(64, 64, 3)),  # 입력 레이어
                                 keras.layers.Conv2D(filters=32, kernel_size=(3, 3)),  # 첫 번째 합성곱 레이어
                                 keras.layers.MaxPool2D(pool_size=(2, 2), strides=2),  # 첫 번째 맥스풀 레이어
                                 keras.layers.Conv2D(filters=32, kernel_size=(3, 3)),  # 두 번째 합성곱 레이어
                                 keras.layers.MaxPool2D(pool_size=(2, 2), strides=2),  # 두 번째 맥스풀 레이어
                                 keras.layers.Conv2D(filters=32, kernel_size=(3, 3)),  # 세 번째 합성곱 레이어
                                 keras.layers.MaxPool2D(pool_size=(2, 2), strides=2),  # 세 번째 맥스풀 레이어
                                 keras.layers.Conv2D(filters=32, kernel_size=(3, 3)),  # 네 번째 합성곱 레이어
                                 keras.layers.MaxPool2D(pool_size=(2, 2), strides=2),  # 네 번째 맥스풀 레이어
                                 keras.layers.Flatten(),  # Flatten 레이어
                                 keras.layers.Dense(units=128, activation='relu', name='LAYER1'),  # 첫 번째 밀집 레이어
                                 keras.layers.Dense(units=32, activation='relu', name='LAYER2'),  # 두 번째 밀집 레이어
                                 keras.layers.Dense(units=4, activation='softmax', name='OUTPUT')  # 출력 레이어 (4개 클래스)
                                 ], name="RECYCLE_CNN")  # 모델 이름 설정
# model.summary()  # 모델 요약 출력 (주석 처리됨)
# model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])  # 모델 컴파일 (주석 처리됨)
#
# history = model.fit(X, y, epochs=1_000)  # 모델 학습 (주석 처리됨)
# model.save('RECYCLE_DETECTOR.keras')  # 모델 저장 (주석 처리됨)

# 성능 테스트를 위한 예제 이미지 읽기
example_images = list()
for i in range(16):  # 16개의 예제 이미지에 대해 반복
    file = './examples/' + 'examples ({0}).jpg'.format(i + 1)  # 파일 경로 생성
    img = cv2.imread(file)  # 이미지 읽기
    img = cv2.resize(img, (64, 64))  # 이미지 크기 조정
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)  # 색상 변환
    example_images.append(img)  # 리스트에 추가

# 예제 이미지를 넘파이 배열로 변환
example_images = np.array(example_images)
# 예제 이미지를 출력하는 함수 호출
plot_images(n_col=5, n_row=2, image=example_images)

model2 = keras.models.load_model('RECYCLE_DETECTOR.keras')  # 저장된 모델 불러오기
predict_images = model2.predict(x=example_images)  # 예제 이미지 예측
print(np.round(predict_images))  # 예측 결과 반올림하여 출력

# 예측 결과 시각화
# 한글 폰트 설정 (예: 맑은 고딕)
font_path = './BMDOHYEON_ttf.ttf'  # 폰트 파일 경로
font_prop = fm.FontProperties(fname=font_path, size=14)  # 폰트 속성 설정

# 예측 결과 시각화
for i in range(len(example_images)):  # 예제 이미지 수만큼 반복
    plt.imshow(example_images[i])  # 이미지 표시
    plt.axis('off')  # 축 숨기기

    # 예측 결과에 따라 타이틀 설정
    predicted_class = np.argmax(predict_images[i])  # 예측된 클래스 인덱스
    if predicted_class == 0:
        plt.title
  1. 이미지 로딩 및 전처리:
    • picnic, umbrella, pet, cafe_cup 폴더에서 각각 150개의 이미지를 읽어와서 크기를 64x64로 조정하고, 색상 형식을 BGR에서 RGB로 변환합니다. 이 과정에서 각 클래스의 이미지를 리스트에 저장합니다.
  2. 이미지 출력:
    • plot_images 함수가 호출되어 각 클래스의 이미지를 3행 5열로 출력합니다. 각 이미지가 올바르게 로딩되었는지 확인할 수 있습니다.
  3. 데이터셋 구성:
    • X는 모든 이미지 데이터가 포함된 배열이고, y는 각 이미지에 대한 정답 레이블을 원-핫 인코딩 방식으로 구성합니다. 예를 들어, picnic 클래스의 이미지는 [1, 0, 0, 0]으로 레이블링됩니다.
  4. CNN 모델 정의:
    • 합성곱 신경망(CNN)을 정의합니다. 입력 레이어와 여러 개의 합성곱 및 맥스풀 레이어를 쌓아 최종적으로 4개의 클래스에 대해 소프트맥스 활성화 함수를 사용하는 출력 레이어를 설정합니다.
  5. 모델 학습 및 저장:
    • 주석 처리된 부분에서는 모델을 컴파일하고 학습시키며, 학습이 완료된 모델을 파일로 저장합니다. 이 과정이 완료되면 모델이 각 클래스의 이미지를 분류하는 데 사용될 수 있습니다.
  6. 예제 이미지 예측:
    • examples 폴더에서 16개의 예제 이미지를 로딩하여 동일한 전처리를 수행한 후, 저장된 모델을 사용해 예측합니다. 예측 결과는 각 클래스의 확률을 나타내는 배열 형태로 반환됩니다.
  7. 예측 결과 시각화:
    • 각 예제 이미지에 대해 예측된 클래스를 기반으로 제목을 설정하여 이미지를 표시합니다. 한글 폰트를 사용해 예측 결과를 적절하게 표현합니다.
  8. 클래스 분포 시각화:
    • 예측된 결과를 바탕으로 각 클래스의 개수를 세고, 파이 차트를 통해 예측된 클래스의 분포를 시각화합니다.

최종 결과

  • 최종적으로, 각 이미지의 예측 결과를 시각적으로 확인할 수 있으며, 파이 차트를 통해 전체 예측 결과의 분포를 한눈에 파악할 수 있습니다. 이를 통해 모델의 성능을 평가하고, 여러 클래스에 대한 예측 정확성을 알 수 있습니다.

이 코드는 이미지 분류 작업을 수행하는 기본적인 CNN 모델을 구성하는 좋은 예시이며, 실제 프로젝트에 적용하기 위한 기초적인 구조를 제공합니다.