{
 "cells": [
  {
   "id": "c01",
   "cell_type": "markdown",
   "metadata": {},
   "source": "<div dir=\"rtl\" style=\"text-align:right\">\n<h1>تکلیف جلسه‌ی ۱: انتخاب k و پیدا کردن رقم‌ها در عکس</h1>\n<p>این تکلیف دو بخش دارد:</p>\n<ol>\n<li><b>انتخاب k (۴ نمره):</b> مدل KNN را روی دیتاست هدی با k از ۱ تا ۱۵ آموزش دهید، دقت هر k را روی داده‌ی آزمون حساب کنید، نمودار «دقت بر حسب k» را رسم کنید و kای را که بیشترین دقت را دارد گزارش کنید.</li>\n<li><b>پیدا کردن رقم‌ها در عکس (۴ نمره):</b> عکسی از یک برگه داریم که چهار رقم دست‌نویس رویش نوشته شده. عکس را دودویی و معکوس کنید، با مؤلفه‌های همبند رقم‌ها را جدا کنید و با همان مدل KNN تشخیص دهید.</li>\n</ol>\n<p>دو نمره‌ی دیگر برای این است که همه‌ی سلول‌ها به ترتیب و بدون خطا اجرا شده باشند.</p>\n<p>جاهایی که <code>...</code> نوشته شده را کامل کنید و اسم متغیرها را عوض نکنید.</p>\n<p><b>ارسال:</b> همه‌ی سلول‌ها را از اول اجرا کنید (Kernel ← Restart & Run All)، نوت‌بوک را <b>با خروجی‌ها</b> ذخیره کنید و فایل <code>.ipynb</code> را در سایت بارگذاری کنید. نوت‌بوک روی سرور اجرا نمی‌شود و همین خروجی‌ها بررسی می‌شوند.</p>\n</div>"
  },
  {
   "id": "c02",
   "cell_type": "markdown",
   "metadata": {},
   "source": "<div dir=\"rtl\" style=\"text-align:right\">\n<h2>آماده‌سازی</h2><p>اگر دیتاست و عکس کنار نوت‌بوک نباشند، از سایت دانلود می‌شوند. تابع <code>load_hoda</code> همان است که در کلاس نوشتیم.</p>\n</div>"
  },
  {
   "id": "c03",
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": "import os\nimport urllib.request\n\nimport numpy as np\nimport cv2\nfrom scipy import io\nfrom sklearn.neighbors import KNeighborsClassifier\nimport matplotlib.pyplot as plt\n\nfor f in [\"Data_hoda_full.mat\", \"persian-digits.jpg\"]:\n    if not os.path.exists(f):\n        urllib.request.urlretrieve(\"https://introtodeeplearning.ir/files/session-01/\" + f, f)\n\n\ndef load_hoda(training_sample_size=1000, test_sample_size=200, size=5):\n    trs, tes = training_sample_size, test_sample_size\n    dataset = io.loadmat(\"Data_hoda_full.mat\")\n    X_train_original = np.squeeze(dataset[\"Data\"][:trs])\n    y_train = np.squeeze(dataset[\"labels\"][:trs])\n    X_test_original = np.squeeze(dataset[\"Data\"][trs:trs + tes])\n    y_test = np.squeeze(dataset[\"labels\"][trs:trs + tes])\n    X_train = np.reshape([cv2.resize(img, (size, size)) for img in X_train_original], [-1, size ** 2])\n    X_test = np.reshape([cv2.resize(img, (size, size)) for img in X_test_original], [-1, size ** 2])\n    return X_train, y_train, X_test, y_test\n\n\nX_train, y_train, X_test, y_test = load_hoda()\nprint(X_train.shape, X_test.shape)"
  },
  {
   "id": "c04",
   "cell_type": "markdown",
   "metadata": {},
   "source": "<div dir=\"rtl\" style=\"text-align:right\">\n<h2>بخش ۱: بهترین k (۴ نمره)</h2>\n<p>برای هر k از ۱ تا ۱۵ یک <code>KNeighborsClassifier</code> بسازید، روی <code>X_train</code> آموزش دهید و دقت روی <code>X_test</code> را به ترتیب در لیست <code>accs</code> بریزید. نمودار را رسم کنید و kای را که بیشترین دقت را داده در <code>best_k</code> بگذارید.</p>\n</div>"
  },
  {
   "id": "c05",
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": "ks = list(range(1, 16))\naccs = []\nfor k in ks:\n    ...\n\nbest_k = ...\n\nplt.plot(ks, accs, marker=\"o\")\nplt.xlabel(\"k\")\nplt.ylabel(\"accuracy\")\nplt.show()\nprint(\"best k:\", best_k)"
  },
  {
   "id": "c06",
   "cell_type": "markdown",
   "metadata": {},
   "source": "<div dir=\"rtl\" style=\"text-align:right\">\n<h2>بخش ۲: پیدا کردن رقم‌ها در عکس (۴ نمره)</h2>\n<p>عکس را خاکستری خوانده‌ایم. آن را <b>دودویی</b> کنید (پیکسل‌های کمتر از ۱۲۷٫۵ صفر و بقیه ۲۵۵) و بعد <b>معکوس</b> کنید تا پس‌زمینه سیاه و رقم‌ها سفید شوند، مثل داده‌های هدی. نتیجه را در <code>g</code> بریزید.</p>\n</div>"
  },
  {
   "id": "c07",
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": "gray = cv2.imread(\"persian-digits.jpg\", 0)\n\ng = ...\n\nprint(\"values:\", np.unique(g), \"corner:\", g[0, 0])\nplt.imshow(g, cmap=\"gray\")\nplt.show()"
  },
  {
   "id": "c08",
   "cell_type": "markdown",
   "metadata": {},
   "source": "<div dir=\"rtl\" style=\"text-align:right\">\n<p>حالا با <code>cv2.connectedComponentsWithStats</code> مؤلفه‌ها را پیدا کنید. برای هر مؤلفه (به‌جز پس‌زمینه) اگر عرض و ارتفاعش بیشتر از ۵ پیکسل بود، آن را با برش تنگ از <code>g</code> جدا کنید و در لیست <code>crops</code> بگذارید؛ مختصاتش <code>(x, y, w, h)</code> را هم در <code>boxes</code>.</p>\n</div>"
  },
  {
   "id": "c09",
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": "n, labels_img, stats, centroids = ...\n\ncrops, boxes = [], []\nfor i in range(1, n):\n    x, y, w, h, area = stats[i]\n    ...\n\nprint(\"found:\", len(crops))"
  },
  {
   "id": "c10",
   "cell_type": "markdown",
   "metadata": {},
   "source": "<div dir=\"rtl\" style=\"text-align:right\">\n<p>این سلول را تغییر ندهید: رقم‌ها را با مدل KNN (k=3) تشخیص می‌دهد و نتیجه را روی عکس می‌کشد.</p>\n</div>"
  },
  {
   "id": "c11",
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": "model = KNeighborsClassifier(n_neighbors=3).fit(X_train, y_train)\npreds = [int(model.predict(cv2.resize(c, (5, 5)).reshape(1, 25))[0]) for c in crops]\n\nimg = cv2.imread(\"persian-digits.jpg\")\nfor (x, y, w, h), p in zip(boxes, preds):\n    cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 2)\n    cv2.putText(img, str(p), (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)\nplt.imshow(img[:, :, ::-1])\nplt.show()\nprint(\"digits:\", sorted(preds))"
  },
  {
   "id": "c12",
   "cell_type": "markdown",
   "metadata": {},
   "source": "<div dir=\"rtl\" style=\"text-align:right\">\n<h2>اختیاری: دست‌خط خودتان</h2>\n<p>یک عکس از چند رقم که خودتان نوشته‌اید بگیرید و همین مراحل را رویش امتحان کنید. این سلول تصحیح نمی‌شود.</p>\n</div>"
  },
  {
   "id": "c13",
   "cell_type": "code",
   "metadata": {
    "tags": [
     "no-grade"
    ]
   },
   "execution_count": null,
   "outputs": [],
   "source": "# @no-grade"
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}