{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "intro",
   "metadata": {},
   "source": [
    "# 09　画像を小さな窓で見る\n",
    "\n",
    "FUJIMOTO LAB 深層学習コース。Web教材の図と説明を読んでから実行してください。Pythonの計算はColabの実行環境で行います。\n",
    "\n",
    "**この回の目標**：カーネルをずらす計算と出力画像の意味を説明できる\n",
    "\n",
    "このノートブックは小さな合成データを使用し、元の教材の固定Driveパスや動画を必要としません。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "predict",
   "metadata": {},
   "source": [
    "## 1　まず予想する\n",
    "\n",
    "コードを実行する前に、表示される値や形を予想してください。"
   ]
  },
  {
   "cell_type": "code",
   "id": "demo-one",
   "metadata": {},
   "source": [
    "import torch\n",
    "import torch.nn.functional as F\n",
    "x = torch.zeros(1,1,5,5)\n",
    "x[0,0,2,2] = 9\n",
    "kernel = torch.ones(1,1,3,3)/9\n",
    "print(F.conv2d(x,kernel).squeeze())"
   ],
   "execution_count": null,
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "id": "explain-one",
   "metadata": {},
   "source": [
    "**確かめ方**：1か所の9が、周囲の3×3窓で平均されて広がります。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "part-two",
   "metadata": {},
   "source": [
    "## 2　端の画素はどうなる？\n",
    "\n",
    "パディングなしの3×3カーネルを5×5画像に使うと、出力は3×3に小さくなります。端に値を足してサイズを保つ方法もあります。"
   ]
  },
  {
   "cell_type": "code",
   "id": "demo-two",
   "metadata": {},
   "source": [
    "print(F.conv2d(x,kernel,padding=1).shape)"
   ],
   "execution_count": null,
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "id": "explain-two",
   "metadata": {},
   "source": [
    "**結果を読む**：周囲へ1画素分の0を補うことで、縦横のサイズが保たれます。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "experiment",
   "metadata": {},
   "source": [
    "## 3　値を変えて比べる\n",
    "\n",
    "次のセルでは、表示される値や条件を変えて、何が結果を決めるかを確かめます。長くかかる実験は、少数の合成データで行います。"
   ]
  },
  {
   "cell_type": "code",
   "id": "lab",
   "metadata": {},
   "source": [
    "# 横方向に値が変わる場所に反応するカーネル\n",
    "edge = torch.tensor([[[[-1.,0.,1.],[-1.,0.,1.],[-1.,0.,1.]]]])\n",
    "stripe = torch.zeros(1,1,5,5)\n",
    "stripe[:,:,:,3:] = 1\n",
    "print(F.conv2d(stripe,edge).squeeze())\n"
   ],
   "execution_count": null,
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "id": "extra-guide-1",
   "metadata": {},
   "source": [
    "## 追加実習 1　ぼかしの1マスを手計算\n",
    "\n",
    "中央の9の周りには0が8個あります。3×3の平均フィルタを重ねた中央の出力と比べましょう。\n",
    "\n",
    "**実行前に予想**：何が変わり、何が変わらないでしょうか。"
   ]
  },
  {
   "cell_type": "code",
   "id": "extra-code-1",
   "metadata": {},
   "source": [
    "filtered = F.conv2d(x, kernel, padding=1).squeeze()\n",
    "print('手計算: 9/9 =', 9/9)\n",
    "print('フィルタ中央:', filtered[2, 2].item())\n",
    "print('出力全体:\\n', filtered)\n"
   ],
   "execution_count": null,
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "id": "extra-reflect-1",
   "metadata": {},
   "source": [
    "**確認**：予想と違った点を一つ書き、値を一つ変えて再実行してください。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "reflection",
   "metadata": {},
   "source": [
    "## 自分の言葉で答えよう\n",
    "\n",
    "5×5画像へ3×3の窓を、パディングなし・1画素ずつ動かすと？\n",
    "\n",
    "- まず予想を書く\n",
    "- コードのどの行が答えを決めるか指す\n",
    "- 条件や値を1つ変えて、予想と実行結果を比べる\n",
    "\n",
    "**ヒント**：窓を置ける位置は縦横それぞれ3か所です。"
   ]
  }
 ],
 "metadata": {
  "colab": {
   "name": "09-filters.ipynb",
   "provenance": []
  },
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
