{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 간단한 이미지 분류기\n", "\n", "이 노트북은 사전 학습된 신경망을 사용하여 이미지를 분류하는 방법을 보여줍니다.\n", "\n", "**배울 내용:**\n", "- 사전 학습된 모델을 로드하고 사용하는 방법\n", "- 이미지 전처리\n", "- 이미지에 대한 예측 수행\n", "- 신뢰도 점수 이해하기\n", "\n", "**사용 사례:** 이미지에서 객체 식별 (예: \"고양이\", \"강아지\", \"자동차\" 등)\n", "\n", "---\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1단계: 필요한 라이브러리 가져오기\n", "\n", "필요한 도구를 가져와 봅시다. 아직 모든 것을 이해하지 못해도 걱정하지 마세요!\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Core libraries\n", "import numpy as np\n", "from PIL import Image\n", "import requests\n", "from io import BytesIO\n", "\n", "# TensorFlow for deep learning\n", "try:\n", " import tensorflow as tf\n", " from tensorflow.keras.applications import MobileNetV2\n", " from tensorflow.keras.applications.mobilenet_v2 import preprocess_input, decode_predictions\n", " print(\"✅ TensorFlow loaded successfully!\")\n", " print(f\" Version: {tf.__version__}\")\n", "except ImportError:\n", " print(\"❌ Please install TensorFlow: pip install tensorflow\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2단계: 사전 학습된 모델 로드하기\n", "\n", "우리는 **MobileNetV2**를 사용할 것입니다. 이 신경망은 이미 수백만 개의 이미지로 학습되었습니다.\n", "\n", "이것을 **전이 학습**이라고 합니다 - 다른 사람이 학습시킨 모델을 사용하는 것이죠!\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(\"📦 Loading pre-trained MobileNetV2 model...\")\n", "print(\" This may take a minute on first run (downloading weights)...\")\n", "\n", "# Load the model\n", "# include_top=True means we use the classification layer\n", "# weights='imagenet' means it was trained on ImageNet dataset\n", "model = MobileNetV2(weights='imagenet', include_top=True)\n", "\n", "print(\"✅ Model loaded!\")\n", "print(f\" The model can recognize 1000 different object categories\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 3단계: 헬퍼 함수\n", "\n", "모델에 사용할 이미지를 로드하고 준비하는 함수를 만들어봅시다.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def load_image_from_url(url):\n", " \"\"\"\n", " Load an image from a URL.\n", " \n", " Args:\n", " url: Web address of the image\n", " \n", " Returns:\n", " PIL Image object\n", " \"\"\"\n", " response = requests.get(url)\n", " img = Image.open(BytesIO(response.content))\n", " return img\n", "\n", "\n", "def prepare_image(img):\n", " \"\"\"\n", " Prepare an image for the model.\n", " \n", " Steps:\n", " 1. Resize to 224x224 (model's expected size)\n", " 2. Convert to array\n", " 3. Add batch dimension\n", " 4. Preprocess for MobileNetV2\n", " \n", " Args:\n", " img: PIL Image\n", " \n", " Returns:\n", " Preprocessed image array\n", " \"\"\"\n", " # Resize to 224x224 pixels\n", " img = img.resize((224, 224))\n", " \n", " # Convert to numpy array\n", " img_array = np.array(img)\n", " \n", " # Add batch dimension (model expects multiple images)\n", " img_array = np.expand_dims(img_array, axis=0)\n", " \n", " # Preprocess for MobileNetV2\n", " img_array = preprocess_input(img_array)\n", " \n", " return img_array\n", "\n", "\n", "def classify_image(img):\n", " \"\"\"\n", " Classify an image and return top predictions.\n", " \n", " Args:\n", " img: PIL Image\n", " \n", " Returns:\n", " List of (class_name, confidence) tuples\n", " \"\"\"\n", " # Prepare the image\n", " img_array = prepare_image(img)\n", " \n", " # Make prediction\n", " predictions = model.predict(img_array, verbose=0)\n", " \n", " # Decode predictions to human-readable labels\n", " # top=5 means we get the top 5 most likely classes\n", " decoded = decode_predictions(predictions, top=5)[0]\n", " \n", " # Convert to simpler format\n", " results = [(label, float(confidence)) for (_, label, confidence) in decoded]\n", " \n", " return results\n", "\n", "\n", "print(\"✅ Helper functions ready!\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 4단계: 샘플 이미지 테스트\n", "\n", "인터넷에서 가져온 몇 가지 이미지를 분류해 봅시다!\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Sample images to classify\n", "# These are from Unsplash (free stock photos)\n", "test_images = [\n", " {\n", " \"url\": \"https://images.unsplash.com/photo-1514888286974-6c03e2ca1dba?w=400\",\n", " \"description\": \"A cat\"\n", " },\n", " {\n", " \"url\": \"https://images.unsplash.com/photo-1552053831-71594a27632d?w=400\",\n", " \"description\": \"A dog\"\n", " },\n", " {\n", " \"url\": \"https://images.unsplash.com/photo-1511919884226-fd3cad34687c?w=400\",\n", " \"description\": \"A car\"\n", " },\n", "]\n", "\n", "print(f\"🧪 Testing on {len(test_images)} images...\")\n", "print(\"=\" * 70)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 각 이미지를 분류하세요\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for i, img_data in enumerate(test_images, 1):\n", " print(f\"\\n📸 Image {i}: {img_data['description']}\")\n", " print(\"-\" * 70)\n", " \n", " try:\n", " # Load image\n", " img = load_image_from_url(img_data['url'])\n", " \n", " # Display image\n", " display(img.resize((200, 200))) # Show smaller version\n", " \n", " # Classify\n", " results = classify_image(img)\n", " \n", " # Show predictions\n", " print(\"\\n🎯 Top 5 Predictions:\")\n", " for rank, (label, confidence) in enumerate(results, 1):\n", " # Create a visual bar\n", " bar_length = int(confidence * 50)\n", " bar = \"█\" * bar_length\n", " \n", " print(f\" {rank}. {label:20s} {confidence*100:5.2f}% {bar}\")\n", " \n", " except Exception as e:\n", " print(f\"❌ Error: {e}\")\n", "\n", "print(\"\\n\" + \"=\" * 70)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 5단계: 직접 이미지를 시도해보세요!\n", "\n", "아래 URL을 원하는 이미지 URL로 교체하여 분류를 시도해보세요.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Try your own image!\n", "# Replace this URL with any image URL\n", "custom_image_url = \"https://images.unsplash.com/photo-1472491235688-bdc81a63246e?w=400\" # A flower\n", "\n", "print(\"🖼️ Classifying your custom image...\")\n", "print(\"=\" * 70)\n", "\n", "try:\n", " # Load and show image\n", " img = load_image_from_url(custom_image_url)\n", " display(img.resize((300, 300)))\n", " \n", " # Classify\n", " results = classify_image(img)\n", " \n", " # Show results\n", " print(\"\\n🎯 Top 5 Predictions:\")\n", " print(\"-\" * 70)\n", " for rank, (label, confidence) in enumerate(results, 1):\n", " bar_length = int(confidence * 50)\n", " bar = \"█\" * bar_length\n", " print(f\" {rank}. {label:20s} {confidence*100:5.2f}% {bar}\")\n", " \n", " # Highlight top prediction\n", " top_label, top_confidence = results[0]\n", " print(\"\\n\" + \"=\" * 70)\n", " print(f\"\\n🏆 Best guess: {top_label} ({top_confidence*100:.2f}% confident)\")\n", " \n", "except Exception as e:\n", " print(f\"❌ Error: {e}\")\n", " print(\" Make sure the URL points to a valid image!\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 💡 방금 무슨 일이 있었나요?\n", "\n", "1. **사전 학습된 모델을 로드했습니다** - MobileNetV2는 수백만 개의 이미지로 학습되었습니다.\n", "2. **이미지를 전처리했습니다** - 모델에 맞게 크기를 조정하고 형식을 변환했습니다.\n", "3. **모델이 예측을 수행했습니다** - 1000개의 객체 클래스에 대한 확률을 출력했습니다.\n", "4. **결과를 디코딩했습니다** - 숫자를 사람이 읽을 수 있는 레이블로 변환했습니다.\n", "\n", "### 신뢰 점수 이해하기\n", "\n", "- **90-100%**: 매우 높은 신뢰도 (거의 확실히 정확함)\n", "- **70-90%**: 높은 신뢰도 (아마도 정확함)\n", "- **50-70%**: 어느 정도 신뢰도 있음 (정확할 가능성 있음)\n", "- **50% 미만**: 신뢰도 낮음 (불확실함)\n", "\n", "### 왜 예측이 틀릴 수 있을까요?\n", "\n", "- **특이한 각도나 조명** - 모델은 일반적인 사진으로 학습되었습니다.\n", "- **여러 객체가 있는 경우** - 모델은 주요 객체 하나를 예상합니다.\n", "- **드문 객체** - 모델은 1000개의 카테고리만 알고 있습니다.\n", "- **저화질 이미지** - 흐릿하거나 픽셀화된 이미지는 더 어렵습니다.\n", "\n", "---\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 🚀 다음 단계\n", "\n", "1. **다양한 이미지 시도하기:**\n", " - [Unsplash](https://unsplash.com)에서 이미지를 찾아보세요.\n", " - 마우스 오른쪽 클릭 → \"이미지 주소 복사\"로 URL 가져오기\n", "\n", "2. **실험해보기:**\n", " - 추상 예술 작품에서는 어떤 결과가 나올까요?\n", " - 다양한 각도에서 객체를 인식할 수 있을까요?\n", " - 여러 객체를 처리하는 방식은 어떨까요?\n", "\n", "3. **더 알아보기:**\n", " - [컴퓨터 비전 강의](../lessons/4-ComputerVision/README.md)를 탐색해보세요.\n", " - 직접 이미지 분류기를 학습시키는 방법을 배워보세요.\n", " - CNN(합성곱 신경망)이 어떻게 작동하는지 이해해보세요.\n", "\n", "---\n", "\n", "## 🎉 축하합니다!\n", "\n", "최첨단 신경망을 사용하여 이미지 분류기를 직접 구축하셨습니다!\n", "\n", "이 기술은 다음과 같은 분야에서 활용됩니다:\n", "- Google Photos (사진 정리)\n", "- 자율주행 자동차 (객체 인식)\n", "- 의료 진단 (X-ray 분석)\n", "- 품질 관리 (결함 감지)\n", "\n", "계속 탐구하고 배우세요! 🚀\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n---\n\n**면책 조항**: \n이 문서는 AI 번역 서비스 [Co-op Translator](https://github.com/Azure/co-op-translator)를 사용하여 번역되었습니다. 정확성을 위해 최선을 다하고 있으나, 자동 번역에는 오류나 부정확성이 포함될 수 있습니다. 원본 문서의 원어 버전이 권위 있는 출처로 간주되어야 합니다. 중요한 정보의 경우, 전문적인 인간 번역을 권장합니다. 이 번역 사용으로 인해 발생하는 오해나 잘못된 해석에 대해 당사는 책임을 지지 않습니다.\n" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.0" }, "coopTranslator": { "original_hash": "1d472141d9df46b751542b3c29f88677", "translation_date": "2025-10-03T11:41:28+00:00", "source_file": "examples/03-image-classifier.ipynb", "language_code": "ko" } }, "nbformat": 4, "nbformat_minor": 4 }