본문 바로가기
  • You find inspiration to create your own path !
업무 자동화/python & CAD

개 와 고양이 이미지를 분류 하기 #3

by ToolBOX01 2025. 8. 29.
반응형

개 또는 고양이 이미지를 입력받아 분류하는 Python 프로그램을 만들기 위해, 머신러닝 기반의 이미지 분류 모델을 사용하는 것이 효과적 입니다.

▣ 프로그램 개발 방법

1. TensorFlow와 pre-trained 모델 선택:

  • TensorFlow의 tf.keras.applications.MobileNetV2를 사용. MobileNetV2는 가볍고, ImageNet 데이터셋으로 학습되어 있어 개/고양이 분류에 적합.
  • ImageNet 클래스 중 개(dog: 151~268), 고양이(cat: 281~285)를 그룹화하여 분류.
  • fine-tuning 없이 pre-trained 모델을 바로 사용해 간단히 구현.

TensorFlow 자체에는 개와 고양이를 직접적으로 구분하는 전용 pre-trained 모델(즉, "dog" vs "cat" 이진 분류 모델)은 포함되어 있지 않습니다. 하지만 TensorFlow의 tf.keras.applications 모듈에서 제공하는 pre-trained 모델들(예: MobileNetV2, ResNet50 등)은 ImageNet 데이터셋으로 학습되었으며, ImageNet에는 개와 고양이 관련 클래스(개: 151~268, 고양이: 281~285)가 포함되어 있어 이를 활용해 개/고양이 분류를 구현할 수 있습니다.

유튜브 동영상

2. 필요한 라이브러리:

  • TensorFlow (tensorflow): 모델 로드와 이미지 처리.
  • Pillow (PIL) 또는 tensorflow.io/tensorflow.image: 이미지 로드 및 전처리.
  • 설치: pip install tensorflow pillow (환경에 따라 생략 가능).

3. 개발 프로세스:

  • 모델 로드: MobileNetV2 모델을 weights='imagenet'으로 로드.
  • 이미지 전처리: 이미지를 224x224 크기로 조정하고, MobileNetV2에 맞게 정규화(tf.keras.applications.mobilenet_v2.preprocess_input).
  • 예측 수행: 모델로 이미지 예측 후, 클래스 인덱스를 확인.
  • 클래스 그룹화: ImageNet 클래스 인덱스를 "dog" 또는 "cat"으로 매핑.
  • 입력 처리: 명령줄 인수로 이미지 파일 경로를 받아 처리.
  • 에러 처리: 잘못된 이미지 파일 입력 시 예외 처리.

사용자가 입력하는 이미지는 TensorFlow 모델(특히 pre-trained 모델인 MobileNetV2 등)을 사용해 분류하기 전에 반드시 전처리 과정을 거쳐야 합니다. 이는 모델이 학습된 데이터 형식과 입력 이미지를 일치시키기 위해 필요합니다. 전처리를 하지 않으면 모델이 이미지를 올바르게 해석하지 못해 부정확한 결과를 내놓거나 에러가 발생할 수 있습니다.

한계와 개선:

  • pre-trained 모델은 품종별로 세분화된 결과를 주므로, 개/고양이 그룹화 로직 필요.
  • 더 높은 정확도를 위해, Kaggle의 Cats vs Dogs 데이터셋으로 fine-tuning 가능.
  • 실시간 처리(예: 웹캠)에는 OpenCV 추가.
  • TensorFlow Lite로 모바일 배포 가능.
 

08_개,고양이 구분 인공지능 구현

이번엔 개,고양이를 구분하는 인공지능을 직접 구현해보자. https://www.tensorflow.org/datasets/catalog/cats_vs_dogs 고양이 대 개 | TensorFlow Datasets TensorFlow.js의 새로운 온라인 과정에서 웹 ML을 통해 0에서 영

supersfel.tistory.com


▣ 훈련 모델 만들기 (model_trainer.py)

수동으로 데이터셋을 설정하는 방법

  1. 데이터셋 수동 다운로드: 아래 링크로 접속하여 cats_and_dogs_filtered.zip 파일을 직접 다운로드하세요. https://storage.googleapis.com/mledu-datasets/cats_and_dogs_filtered.zip
  2. 압축 해제: 다운로드한 cats_and_dogs_filtered.zip 파일의 압축을 해제합니다.
  3. 폴더 위치 지정: 압축 해제된 cats_and_dogs_filtered 폴더를 model_trainer.py 파일과 같은 위치에 옮겨놓으세요.
- python_project01/
  - myenv/
  - cats_and_dogs_filtered/
    - train/
      - cats/
      - dogs/
    - validation/
      - cats/
      - dogs/
  - main.py
  - model_trainer.py
  - main_window.ui

 

모델 학습 및 저장 (model_trainer.py)

  • 데이터셋 준비: cats_and_dogs_filtered 데이터셋 폴더를 찾아 train과 validation 디렉토리의 이미지 파일을 불러옵니다. 이 데이터셋은 개와 고양이 이미지로 구성되어 있습니다.
  • 모델 구축: 개와 고양이를 분류하기 위한 합성곱 신경망(CNN) 모델을 만듭니다. 이 모델은 이미지의 특징을 추출하고 학습하여 최종적으로 이미지가 개인지 고양이인지 예측합니다.
  • 모델 학습: 준비된 데이터셋으로 모델을 훈련시킵니다. 이 과정을 통해 모델은 이미지의 특징을 학습하여 분류 정확도를 높입니다.
  • 모델 저장: 학습이 완료된 모델을 cats_vs_dogs_classifier.h5라는 파일로 저장합니다. 이렇게 저장된 모델은 나중에 GUI 애플리케이션에서 다시 불러와 사용할 수 있습니다.

▶ model_trainer.py   코드

model_trainer.py는 기계 학습 모델을 만들고 훈련시키는 역할 입니다

import tensorflow as tf
from tensorflow.keras.preprocessing import image_dataset_from_directory
import os

# 모델 저장 경로 설정
MODEL_PATH = 'cats_vs_dogs_classifier.h5'
DATASET_PATH = 'cats_and_dogs_filtered' # 수동으로 압축 해제한 폴더명

def get_datasets(base_dir):
    """파일 시스템에서 데이터셋 로드"""
    if not os.path.exists(base_dir):
        raise FileNotFoundError(f"데이터셋 디렉토리 '{base_dir}'를 찾을 수 없습니다. 수동으로 다운로드 후 압축 해제하여 이 스크립트와 같은 위치에 놓아주세요.")
        
    train_dir = os.path.join(base_dir, 'train')
    validation_dir = os.path.join(base_dir, 'validation')
    
    # 훈련 및 검증 데이터셋 폴더가 존재하는지 확인
    if not os.path.exists(train_dir) or not os.path.exists(validation_dir):
        raise FileNotFoundError(f"훈련 또는 검증 데이터셋 디렉토리({train_dir}, {validation_dir})를 찾을 수 없습니다. 다운로드된 파일 구조를 확인해주세요.")

    train_dataset = image_dataset_from_directory(
        train_dir,
        labels='inferred',
        label_mode='binary',
        image_size=(150, 150),
        batch_size=32,
        seed=123,
    )

    validation_dataset = image_dataset_from_directory(
        validation_dir,
        labels='inferred',
        label_mode='binary',
        image_size=(150, 150),
        batch_size=32,
        seed=123,
    )
    return train_dataset, validation_dataset

def build_model():
    """CNN 모델 구축"""
    model = tf.keras.Sequential([
        tf.keras.layers.Rescaling(1./255, input_shape=(150, 150, 3)),
        tf.keras.layers.Conv2D(32, (3, 3), activation='relu'),
        tf.keras.layers.MaxPooling2D(2, 2),
        tf.keras.layers.Conv2D(64, (3, 3), activation='relu'),
        tf.keras.layers.MaxPooling2D(2, 2),
        tf.keras.layers.Conv2D(128, (3, 3), activation='relu'),
        tf.keras.layers.MaxPooling2D(2, 2),
        tf.keras.layers.Flatten(),
        tf.keras.layers.Dense(512, activation='relu'),
        tf.keras.layers.Dense(1, activation='sigmoid')
    ])

    model.compile(optimizer='adam',
                  loss='binary_crossentropy',
                  metrics=['accuracy'])

    return model

def train_and_save_model():
    """모델 학습 및 저장"""
    if os.path.exists(MODEL_PATH):
        print("기존 모델 파일이 존재하여 학습을 건너뜁니다.")
        return

    print("모델 학습을 시작합니다. 이 과정은 시간이 다소 소요될 수 있습니다.")
    try:
        train_dataset, validation_dataset = get_datasets(DATASET_PATH)
        model = build_model()
        model.fit(train_dataset, epochs=10, validation_data=validation_dataset)
        model.save(MODEL_PATH)
        print(f"모델이 성공적으로 '{MODEL_PATH}'에 저장되었습니다.")
    except FileNotFoundError as e:
        print(f"오류: {e}")
        print("데이터셋 폴더가 올바른 위치에 있는지 확인해주세요.")


if __name__ == '__main__':
    train_and_save_model()

 

model_trainer.py
0.00MB

 

프로그램 실행 결과 : cats_vs_dogs_classifier.h5 생성 

 


▣ 개와 고양이 분류 애플리케이션 (main.py)

  • UI 로드:
    Qt Designer로 만든 main_window.ui 파일을 불러와 사용자 인터페이스를 만듭니다.
    이 UI에는 이미지를 선택하는 버튼, 선택된 이미지를 표시하는 공간, 그리고 예측 결과를 보여주는 공간이 있습니다.
  • 모델 로드:
    model_trainer.py에서 저장한 cats_vs_dogs_classifier.h5 파일을 불러와 모델을 메모리에 로드합니다.
  • 이미지 분류:
    사용자가 "이미지 선택" 버튼을 눌러 이미지를 선택하면, 해당 이미지를 모델이 분류할 수 있는 형태로 전처리합니다.
  • 결과 표시:
    전처리된 이미지를 불러온 모델에 넣어 예측을 수행하고, "개" 또는 "고양이"라는 예측 결과를 GUI에 표시합니다.
python -m PyQt6.uic.pyuic -x main_window.ui -o main_window.py

 

▶ 뷴류 프로그램 코드 (main.py)

main_window.py가 main.py와 같은 디렉토리에 있다고 가정합니다. main.py를 실행하기 전에 main_window.py 파일이 반드시 존재해야 합니다.

import sys
import os
import cv2
import numpy as np
import tensorflow as tf
from PyQt6.QtWidgets import QApplication, QMainWindow, QFileDialog
from PyQt6.QtGui import QPixmap
from PyQt6.QtCore import Qt

# 별도의 파일로 생성된 UI 클래스를 불러옵니다.
from main_window import Ui_MainWindow 

# 모델 경로
MODEL_PATH = 'cats_vs_dogs_classifier.h5'

class CatDogClassifierApp(QMainWindow):
    def __init__(self):
        super().__init__()
        
        # UI 클래스의 인스턴스를 생성하고 setupUi 메서드를 호출하여 UI를 설정합니다.
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        
        # 모델 로드
        self.model = self.load_model()
        
        # UI 요소 연결 (self.ui 객체를 통해 접근)
        self.ui.pushButton.clicked.connect(self.select_image)
        
    def load_model(self):
        """저장된 모델을 로드"""
        if os.path.exists(MODEL_PATH):
            print(f"'{MODEL_PATH}' 모델을 로드합니다.")
            return tf.keras.models.load_model(MODEL_PATH)
        else:
            print("모델 파일이 존재하지 않습니다. model_trainer.py를 먼저 실행하여 모델을 학습시키세요.")
            return None

    def select_image(self):
        """이미지 파일을 선택하고 분류"""
        if not self.model:
            return

        file_path, _ = QFileDialog.getOpenFileName(self, "이미지 선택", "", "Image Files (*.png *.jpg *.jpeg)")
        
        if file_path:
            # 선택된 이미지 경로를 QLineEdit에 표시
            self.ui.lineEdit.setText(file_path)
            
            # 선택된 이미지 표시
            self.display_image(file_path)
            
            # 이미지 분류
            self.classify_image(file_path)

    def display_image(self, file_path):
        """GUI에 이미지 표시"""
        pixmap = QPixmap(file_path)
        # QLabel 크기에 맞게 이미지 조정 (self.ui 객체 사용)
        self.ui.labelImage.setPixmap(pixmap.scaled(self.ui.labelImage.width(), self.ui.labelImage.height(), aspectRatioMode=Qt.AspectRatioMode.KeepAspectRatio))
        
    def classify_image(self, file_path):
        """이미지를 모델에 입력하여 분류"""
        image = cv2.imread(file_path)
        if image is None:
            self.ui.labelValue.setText("이미지 로드 실패!")
            return
            
        # OpenCV는 BGR 순서이므로 RGB로 변환
        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        
        # 모델 입력에 맞게 이미지 전처리
        image = cv2.resize(image, (150, 150))
        image = image / 255.0
        image = np.expand_dims(image, axis=0) # 배치 차원 추가

        # 예측
        prediction = self.model.predict(image)[0][0]
        
        # 결과 표시 (self.ui 객체 사용)
        if prediction > 0.5:
            result = f"개(Dog)\n({prediction*100:.2f}%)"
        else:
            result = f"고양이(Cat)\n({(1-prediction)*100:.2f}%)"
            
        self.ui.labelValue.setText(result)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = CatDogClassifierApp()
    window.show()
    sys.exit(app.exec())

main.py
0.00MB
main_window.py
0.00MB
main_window.ui
0.00MB

 

프로그램 실행 결과

[분류 프로그램]

 

by korealionkk@gmail.com


반응형