{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 1차시 — 위성이 보는 것 + 첫 분류기\n",
    "\n",
    "**대성고 위성×AI · 4시간 · Lab B (60분)**\n",
    "\n",
    "---\n",
    "\n",
    "## 오늘 할 일\n",
    "\n",
    "1. **CODE 1** — 이미지 = 행렬 (PIL · numpy)\n",
    "2. **CODE 2** — RGB 채널 분리 + 평균 비교\n",
    "3. **CODE 3** — Gemini 와 함께 분류기 함수 작성\n",
    "4. **CHALLENGE** — 3-tier (최소·권장·도전)\n",
    "\n",
    "## Run All 먼저\n",
    "\n",
    "메뉴 → 런타임 → 모두 실행 (Ctrl/Cmd + F9). 결과부터 보고, 셀별 *왜* 는 그 다음에.\n",
    "\n",
    "## Gemini 가 옆에 있다\n",
    "\n",
    "[gemini.google.com](https://gemini.google.com) 옆 탭에 열어두세요. 막히면 *바로 물어봐요*.\n",
    "\n",
    "## 🚨 자주 막히는 곳\n",
    "\n",
    "| 증상 | 해결 |\n",
    "|---|---|\n",
    "| `ModuleNotFoundError` | 위 셀 (import) 다시 실행 |\n",
    "| 한글 깨짐 | 아래 NanumGothic 셀 실행 |\n",
    "| 그림이 안 보임 | `%matplotlib inline` 한 번 실행 |\n",
    "| 결과가 다름 | `np.random.seed(42)` 셀 다시 |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 0. 환경 셋업\n",
    "\n",
    "한글 폰트 + 라이브러리 import."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 한글 폰트 (Colab)\n",
    "!apt-get -qq install fonts-nanum > /dev/null\n",
    "import matplotlib.font_manager as fm\n",
    "fm.fontManager.addfont('/usr/share/fonts/truetype/nanum/NanumGothic.ttf')\n",
    "\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from PIL import Image\n",
    "\n",
    "plt.rcParams['font.family'] = 'NanumGothic'\n",
    "plt.rcParams['axes.unicode_minus'] = False\n",
    "print('환경 OK — 다음 셀로')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## CODE 1 — 이미지 = 행렬 (셀 1-6)\n",
    "\n",
    "**핵심**: 컴퓨터에게 이미지는 *숫자 격자*. (높이, 너비, 3채널).\n",
    "\n",
    "> ⚠️ **합성 데이터 안내**\n",
    "> 아래는 시각화·코드 학습용으로 *합성한* 위성 패치입니다 (외부 다운로드 없이 안전하게 실행되도록). 카테고리별로 색뿐 아니라 *질감 (텍스처)* 도 다르게 만들어서 진짜 위성 사진의 분위기를 흉내냈습니다.\n",
    "> 진짜 위성 사진은 **LEVEL 3 (CHALLENGE)** 에서 NASA Worldview 등에서 직접 다운로드해서 다뤄봅니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 위성 패치 합성기 — 카테고리별 색 + 텍스처\n",
    "def make_satellite(category, size=128, seed=42):\n",
    "    rs = np.random.RandomState(seed + abs(hash(category)) % 1000)\n",
    "\n",
    "    if category == '도시':\n",
    "        # 회색 베이스 + 도로 격자 + 건물 블록\n",
    "        base = np.full((size, size, 3), 130, dtype=np.int16)\n",
    "        # 도로 격자 (어두운 선)\n",
    "        for i in range(0, size, 16):\n",
    "            base[i:i+2, :] -= 40\n",
    "            base[:, i:i+2] -= 40\n",
    "        # 건물 (작은 밝은 블록)\n",
    "        for _ in range(18):\n",
    "            x = rs.randint(2, size - 10)\n",
    "            y = rs.randint(2, size - 10)\n",
    "            w = rs.randint(4, 10)\n",
    "            h = rs.randint(4, 10)\n",
    "            base[y:y+h, x:x+w] += rs.randint(15, 50)\n",
    "        noise = rs.randint(-25, 25, base.shape, dtype=np.int16)\n",
    "        return np.clip(base + noise, 0, 255).astype(np.uint8)\n",
    "\n",
    "    elif category == '농경지':\n",
    "        # 녹황 베이스 + 수직 고랑 줄무늬\n",
    "        base = np.zeros((size, size, 3), dtype=np.int16)\n",
    "        base[:, :, 0] = 100   # R\n",
    "        base[:, :, 1] = 145   # G\n",
    "        base[:, :, 2] = 65    # B\n",
    "        # 고랑 (밝은 녹색 수직 줄)\n",
    "        for x in range(0, size, 7):\n",
    "            base[:, x:x+3, 1] += 25\n",
    "            base[:, x:x+3, 0] += 10\n",
    "        # 밭 경계 (수평 한두 줄)\n",
    "        for y in [40, 90]:\n",
    "            base[y:y+2, :] -= 25\n",
    "        noise = rs.randint(-12, 12, base.shape, dtype=np.int16)\n",
    "        return np.clip(base + noise, 0, 255).astype(np.uint8)\n",
    "\n",
    "    elif category == '바다':\n",
    "        # 파랑 베이스 + y 그라데이션 + 잔물결\n",
    "        base = np.zeros((size, size, 3), dtype=np.int16)\n",
    "        for y in range(size):\n",
    "            base[y, :, 0] = 25 + y // 12\n",
    "            base[y, :, 1] = 70 + y // 8\n",
    "            base[y, :, 2] = 150 + y // 6\n",
    "        # 잔물결 (수평 밝은 선)\n",
    "        for y in range(0, size, 14):\n",
    "            base[y:y+1, :, 2] += 20\n",
    "            base[y:y+1, :, 1] += 10\n",
    "        noise = rs.randint(-10, 10, base.shape, dtype=np.int16)\n",
    "        return np.clip(base + noise, 0, 255).astype(np.uint8)\n",
    "\n",
    "    elif category == '산림':\n",
    "        # 진녹 베이스 + 나무 캐노피 점박이\n",
    "        base = np.zeros((size, size, 3), dtype=np.int16)\n",
    "        base[:, :, 0] = 40\n",
    "        base[:, :, 1] = 105\n",
    "        base[:, :, 2] = 50\n",
    "        # 나무 그림자 (어두운 원형 점)\n",
    "        ys, xs = np.ogrid[:size, :size]\n",
    "        for _ in range(90):\n",
    "            cx = rs.randint(0, size)\n",
    "            cy = rs.randint(0, size)\n",
    "            r = rs.randint(2, 5)\n",
    "            mask = (xs - cx) ** 2 + (ys - cy) ** 2 <= r * r\n",
    "            base[mask, 1] -= rs.randint(15, 35)\n",
    "        # 약간 밝은 단풍 점\n",
    "        for _ in range(20):\n",
    "            cx = rs.randint(0, size)\n",
    "            cy = rs.randint(0, size)\n",
    "            r = rs.randint(1, 3)\n",
    "            mask = (xs - cx) ** 2 + (ys - cy) ** 2 <= r * r\n",
    "            base[mask, 0] += rs.randint(20, 50)\n",
    "            base[mask, 1] += rs.randint(10, 25)\n",
    "        noise = rs.randint(-15, 15, base.shape, dtype=np.int16)\n",
    "        return np.clip(base + noise, 0, 255).astype(np.uint8)\n",
    "\n",
    "city   = make_satellite('도시')\n",
    "farm   = make_satellite('농경지')\n",
    "ocean  = make_satellite('바다')\n",
    "forest = make_satellite('산림')\n",
    "\n",
    "print('city  :', city.shape, city.dtype)\n",
    "print('farm  :', farm.shape, farm.dtype)\n",
    "print('ocean :', ocean.shape, ocean.dtype)\n",
    "print('forest:', forest.shape, forest.dtype)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> 💡 **예상 결과** — 4개 모두 `(128, 128, 3) uint8`. 즉 128×128 픽셀 × RGB 3채널.\n",
    "\n",
    "→ 컴퓨터가 보는 *이미지* = 숫자 격자."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 4장 한꺼번에 보기\n",
    "fig, ax = plt.subplots(1, 4, figsize=(14, 4))\n",
    "for a, img, name in zip(ax, [city, farm, ocean, forest], ['도시 (격자+건물)','농경지 (고랑)','바다 (그라데이션+물결)','산림 (나무 점박이)']):\n",
    "    a.imshow(img)\n",
    "    a.set_title(name, fontsize=12, fontweight='bold')\n",
    "    a.axis('off')\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> 💡 **예상 결과** — 4 패치가 각각 *다른 색* + *다른 텍스처*.\n",
    "> - 도시: 회색 + 도로 격자 + 작은 건물\n",
    "> - 농경지: 녹황 + 수직 고랑\n",
    "> - 바다: 파랑 + 그라데이션 + 잔물결\n",
    "> - 산림: 진녹 + 나무 캐노피 점\n",
    "\n",
    "→ 진짜 위성 사진도 비슷한 *질감* 차이가 있어요. 분류기는 이 *색과 질감* 을 단서로 카테고리를 구분합니다. 오늘은 *색* 만 다루고, 6차시 (C6) 에서 *질감* 까지 배웁니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 픽셀 1개 들여다보기\n",
    "print('city[64, 64]  =', city[64, 64])   # 가운데 픽셀의 (R, G, B)\n",
    "print('farm[64, 64]  =', farm[64, 64])\n",
    "print('ocean[64, 64] =', ocean[64, 64])\n",
    "print('forest[64, 64]=', forest[64, 64])\n",
    "print()\n",
    "print('R 채널 모양:', city[:, :, 0].shape)   # (128, 128)\n",
    "print('R 채널 평균:', city[:, :, 0].mean())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> 💡 **slicing**: `img[행, 열, 채널]`. 채널 = 0(R), 1(G), 2(B). 정수 하나를 빼면 *그 한 점의 RGB*, 슬라이스를 빼면 *영역의 값*."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## CODE 2 — RGB 채널 분리 + 평균 (셀 7-12)\n",
    "\n",
    "**핵심**: 카테고리마다 *평균 RGB 가 다르다*. → 이 차이를 단서로 분류 가능."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 도시 사진의 R, G, B 채널 따로 보기\n",
    "fig, ax = plt.subplots(1, 4, figsize=(14, 4))\n",
    "ax[0].imshow(city);                                         ax[0].set_title('원본 (RGB)',  fontweight='bold')\n",
    "ax[1].imshow(city[:,:,0], cmap='Reds',   vmin=0, vmax=255); ax[1].set_title('R 채널만',    fontweight='bold')\n",
    "ax[2].imshow(city[:,:,1], cmap='Greens', vmin=0, vmax=255); ax[2].set_title('G 채널만',    fontweight='bold')\n",
    "ax[3].imshow(city[:,:,2], cmap='Blues',  vmin=0, vmax=255); ax[3].set_title('B 채널만',    fontweight='bold')\n",
    "for a in ax: a.axis('off')\n",
    "plt.tight_layout(); plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> 💡 R/G/B 가 거의 비슷해 보이는 이유 — 도시는 *회색* 이라서. 세 채널 값이 비슷할 때 우리 눈에는 *무채색 (회색)* 으로 보입니다.\n",
    "\n",
    "→ 한 컬러 사진 안에 *3장의 흑백 사진* 이 겹쳐 있는 셈."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 카테고리별 평균 RGB 계산 — 분류의 기준\n",
    "categories = {'도시': city, '농경지': farm, '바다': ocean, '산림': forest}\n",
    "\n",
    "ref_rgb = {}\n",
    "for name, img in categories.items():\n",
    "    r = img[:, :, 0].mean()\n",
    "    g = img[:, :, 1].mean()\n",
    "    b = img[:, :, 2].mean()\n",
    "    ref_rgb[name] = np.array([r, g, b])\n",
    "    print(f'{name:>4}: R={r:5.1f}  G={g:5.1f}  B={b:5.1f}')\n",
    "\n",
    "print()\n",
    "print('→ 이 4개 RGB 가 우리 *분류기의 기준점*.')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> 💡 **예상 결과** (대략)\n",
    "> ```\n",
    "> 도시 : R=121  G=121  B=121\n",
    "> 농경지: R=103  G=155  B= 64\n",
    "> 바다 : R= 29  G= 78  B=161\n",
    "> 산림 : R= 40  G=101  B= 50\n",
    "> ```\n",
    "> *정확한 값은 합성기·노이즈에 따라 달라요. 위는 참고 범위.*\n",
    "\n",
    "→ 각 카테고리의 *지문* 같은 RGB."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 🤖 GEMINI 와 페어 작업 (필수)\n",
    "\n",
    "**[gemini.google.com](https://gemini.google.com) 열어서 아래 프롬프트를 그대로 복사해 붙여넣으세요**:\n",
    "\n",
    "```\n",
    "파이썬으로 함수를 짜줘.\n",
    "입력: numpy 배열 모양 (128, 128, 3) 의 위성 사진 이미지.\n",
    "출력: 4개 카테고리 ('도시', '농경지', '바다', '산림') 중 가장 가까운 카테고리 이름.\n",
    "\n",
    "기준 RGB 는 호출 시점에 동적으로 계산하지 말고,\n",
    "아래 dict 를 함수 안에 박아둬:\n",
    "refs = {\n",
    "    '도시':   (121, 121, 121),\n",
    "    '농경지': (103, 155,  64),\n",
    "    '바다':   ( 29,  78, 161),\n",
    "    '산림':   ( 40, 101,  50),\n",
    "}\n",
    "\n",
    "방법: 입력 이미지의 평균 RGB 와 4개 기준 RGB 사이 *유클리드 거리* 를 계산해서 가장 가까운 걸 반환.\n",
    "함수 이름: classify_satellite(img).\n",
    "코드만 한글 주석 없이 짧게.\n",
    "```\n",
    "\n",
    "→ Gemini 가 코드를 줄 거예요. 아래 *빈 셀에* 붙여넣고 실행하세요."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 여기에 Gemini 가 준 코드 붙여넣기.\n",
    "# 막히면 아래 *참고 답* 셀 펼쳐서 비교.\n",
    "\n",
    "# def classify_satellite(img):\n",
    "#     ...\n",
    "#     return ?"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 📌 참고 답 (Gemini 답이 안 좋으면 비교용)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 참고 답 — Gemini 의 답과 비교해보기\n",
    "def classify_satellite(img):\n",
    "    \"\"\"위성 사진 1장 → 4 카테고리 중 가장 가까운 것\"\"\"\n",
    "    mean_rgb = np.array([img[:,:,0].mean(), img[:,:,1].mean(), img[:,:,2].mean()])\n",
    "    refs = {\n",
    "        '도시':   np.array([121, 121, 121]),\n",
    "        '농경지': np.array([103, 155,  64]),\n",
    "        '바다':   np.array([ 29,  78, 161]),\n",
    "        '산림':   np.array([ 40, 101,  50]),\n",
    "    }\n",
    "    distances = {name: np.linalg.norm(mean_rgb - ref) for name, ref in refs.items()}\n",
    "    return min(distances, key=distances.get)\n",
    "\n",
    "print('함수 정의 완료')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 4장에 다 적용해보기 — 자기 카테고리 맞추는지\n",
    "for name, img in categories.items():\n",
    "    pred = classify_satellite(img)\n",
    "    mark = '✓' if pred == name else '✗'\n",
    "    print(f'{mark} 실제: {name:>4}  →  예측: {pred}')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> 💡 4개 모두 ✓ 가 나오면 LEVEL 1 통과입니다.\n",
    "> 가끔 1개 정도 ✗ 가 나올 수도 있어요 — 합성 노이즈 때문. 다시 한 번 셀들을 실행하면 보통 해결됩니다."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## ✓ 체크포인트 — LEVEL 1\n",
    "\n",
    "- [ ] 셀 모두 에러 없이 실행됐다\n",
    "- [ ] 4 카테고리 패치가 각각 *다른 텍스처* 로 보였다\n",
    "- [ ] 평균 RGB 4개 출력됐다\n",
    "- [ ] `classify_satellite()` 함수가 4장을 분류했다\n",
    "\n",
    "→ 다 ✓ 면 다음 (LEVEL 2) 으로."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 🎯 CHALLENGE\n",
    "\n",
    "### LEVEL 2 (권장) — 정확도 측정\n",
    "\n",
    "새 사진을 여러 장 만들어서 정확도 % 를 측정해봅니다.\n",
    "\n",
    "**🤖 Gemini 에게 이렇게 물어봐**:\n",
    "```\n",
    "위 make_satellite 와 classify_satellite 를 사용해서,\n",
    "4 카테고리 × 각 5장 = 20장의 새 사진을 (seed 를 매번 다르게 해서)\n",
    "만들고, classify_satellite 로 분류해서 전체 정확도 % 를 출력하는 코드를 짜줘.\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Gemini 답 붙여넣기. 또는 직접 작성. 참고 답:\n",
    "correct = 0\n",
    "total = 0\n",
    "for name in ['도시', '농경지', '바다', '산림']:\n",
    "    for i in range(5):\n",
    "        test_img = make_satellite(name, seed=100 + i)  # 학습 시드와 다르게\n",
    "        pred = classify_satellite(test_img)\n",
    "        if pred == name:\n",
    "            correct += 1\n",
    "        total += 1\n",
    "\n",
    "accuracy = correct / total * 100\n",
    "print(f'정확도: {correct}/{total} = {accuracy:.1f}%')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> 💡 **예상 결과** — 정확도 80% 이상 (보통 95~100%).\n",
    "> 카테고리별로 평균 RGB 차이가 충분히 커서 *색만으로도* 거의 다 맞춥니다.\n",
    "> 진짜 위성 사진에서는 도시·산림·농경지가 비슷한 회녹색일 때가 많아 정확도가 더 떨어집니다. 그래서 5차시·6차시에 *머신러닝·신경망* 으로 넘어가는 거예요."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### LEVEL 3 (도전) — 진짜 위성 사진 1장\n",
    "\n",
    "NASA Worldview ([worldview.earthdata.nasa.gov](https://worldview.earthdata.nasa.gov)) 또는 Google 이미지 검색 (`satellite city`, `satellite forest` 등) 에서 *진짜* 위성 사진 1장을 받아오세요.\n",
    "\n",
    "**업로드 방법**:\n",
    "1. Colab 화면 *좌측 폴더 아이콘* 클릭\n",
    "2. 파일 영역에 *드래그앤드롭* 으로 사진 업로드\n",
    "3. 파일 이름 확인 (예: `seoul.jpg`)\n",
    "4. 아래 셀의 `filename` 변수를 본인 파일 이름으로 변경"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# LEVEL 3 — 진짜 위성 사진으로 분류\n",
    "filename = 'my_image.jpg'   # ← 본인 업로드 파일명으로\n",
    "\n",
    "try:\n",
    "    img_pil = Image.open(filename).convert('RGB')\n",
    "    img_pil = img_pil.resize((128, 128))   # 모델 기준 크기\n",
    "    img_np = np.array(img_pil)\n",
    "\n",
    "    fig, ax = plt.subplots(1, 2, figsize=(10, 5))\n",
    "    ax[0].imshow(img_np)\n",
    "    ax[0].set_title(f'업로드한 사진: {filename}', fontweight='bold')\n",
    "    ax[0].axis('off')\n",
    "\n",
    "    # 합성 4장 비교\n",
    "    ref_imgs = [city, farm, ocean, forest]\n",
    "    ref_names = ['도시', '농경지', '바다', '산림']\n",
    "\n",
    "    result = classify_satellite(img_np)\n",
    "    mean_rgb = img_np.reshape(-1, 3).mean(axis=0)\n",
    "\n",
    "    ax[1].axis('off')\n",
    "    ax[1].text(0.05, 0.85, f'평균 RGB',\n",
    "               fontsize=14, fontweight='bold', transform=ax[1].transAxes)\n",
    "    ax[1].text(0.05, 0.70, f'  R = {mean_rgb[0]:.0f}', fontsize=13, transform=ax[1].transAxes)\n",
    "    ax[1].text(0.05, 0.60, f'  G = {mean_rgb[1]:.0f}', fontsize=13, transform=ax[1].transAxes)\n",
    "    ax[1].text(0.05, 0.50, f'  B = {mean_rgb[2]:.0f}', fontsize=13, transform=ax[1].transAxes)\n",
    "    ax[1].text(0.05, 0.30, f'→ 분류기 예측: {result}',\n",
    "               fontsize=16, fontweight='bold', color='#FF2E93', transform=ax[1].transAxes)\n",
    "    plt.tight_layout(); plt.show()\n",
    "\n",
    "    print()\n",
    "    print('☝️ 결과가 맞나요? 틀렸으면 *왜 틀렸을지* markdown 셀에 한 줄 적어보세요.')\n",
    "    print('   (힌트: 합성 데이터의 평균 RGB 와 진짜 사진의 평균 RGB 가 어떻게 다른지)')\n",
    "except FileNotFoundError:\n",
    "    print(f'❌ {filename} 못 찾음. 좌측 폴더 아이콘에서 업로드했는지 확인하세요.')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### LEVEL 3 결과 기록\n",
    "\n",
    "아래에 한 줄씩 적어두기 (다음 주 발표 때 사용):\n",
    "\n",
    "- 업로드한 사진: ___\n",
    "- 평균 RGB: R= ___ G= ___ B= ___\n",
    "- 예측 결과: ___\n",
    "- 실제 정답 (사진을 직접 보고): ___\n",
    "- 맞았나? ___\n",
    "- 틀렸다면 *왜* 라고 생각하나? ___"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## 📝 발표 준비 (B4 — 50분)\n",
    "\n",
    "### 페어 1분 설명 (짝과)\n",
    "\n",
    "다음 4 가지 순서로 1분:\n",
    "1. 내 TM 모델은 ___ 카테고리를 ___ % 정도 맞춥니다.\n",
    "2. Colab 노트북은 LEVEL ___ 까지 진행했습니다.\n",
    "3. 가장 흥미로웠던 점은 ___.\n",
    "4. 어디서 막혔는지: ___.\n",
    "\n",
    "### 노트북 저장\n",
    "\n",
    "파일 → 드라이브에 사본 저장 → 이름 `01_본인이름.ipynb` 로 변경.\n",
    "\n",
    "---\n",
    "\n",
    "## 🎉 1차시 완료\n",
    "\n",
    "오늘 정리:\n",
    "- 위성 종류 3가지 + 한국 위성 2개 + 세계 위성\n",
    "- Teachable Machine 으로 동작하는 분류기 1개\n",
    "- Colab + 이미지 = 행렬 직관\n",
    "- Gemini 와의 첫 페어 작업\n",
    "- 자기 분류기 함수 + 정확도 측정\n",
    "- (선택) 진짜 위성 사진 1장 적용\n",
    "\n",
    "**다음 주 — C2: 위성 텔레메트리 분석 (pandas + matplotlib)**\n",
    "\n",
    "🛰️ 수고하셨습니다."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python",
   "version": "3.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}