250 lines
8.1 KiB
Plaintext
250 lines
8.1 KiB
Plaintext
{
|
||
"cells": [
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"# 04 — Sestavení velké mapy\n",
|
||
"\n",
|
||
"Složíme otagované dlaždice (z notebooku 03) do jednoho velkého leteckého snímku HK\n",
|
||
"se zakreslenými detekcemi vozidel.\n",
|
||
"\n",
|
||
"Výsledná mapa: **74 × 69 dlaždic × 256 px = 18 944 × 17 664 px**\n",
|
||
"(přibližně 90 MB PNG nebo 15 MB JPEG)."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"from pathlib import Path\n",
|
||
"from PIL import Image\n",
|
||
"import numpy as np\n",
|
||
"import re\n",
|
||
"from tqdm.notebook import tqdm\n",
|
||
"import json\n",
|
||
"\n",
|
||
"ANNOTATED_DIR = Path(\"tiles_annotated\")\n",
|
||
"assert ANNOTATED_DIR.exists(), \"Nejprve spusť 03_inference_tiles.ipynb!\"\n",
|
||
"\n",
|
||
"TILE_SIZE = 256\n",
|
||
"\n",
|
||
"# Zjistíme rozsah mřížky\n",
|
||
"tile_files = sorted(ANNOTATED_DIR.glob(\"18_*.jpg\"))\n",
|
||
"xs = []; ys = []\n",
|
||
"for f in tile_files:\n",
|
||
" m = re.match(r\"18_(\\d+)_(\\d+)\\.jpg\", f.name)\n",
|
||
" if m:\n",
|
||
" xs.append(int(m.group(1)))\n",
|
||
" ys.append(int(m.group(2)))\n",
|
||
"\n",
|
||
"x_min, x_max = min(xs), max(xs)\n",
|
||
"y_min, y_max = min(ys), max(ys)\n",
|
||
"cols = x_max - x_min + 1\n",
|
||
"rows = y_max - y_min + 1\n",
|
||
"\n",
|
||
"W = cols * TILE_SIZE\n",
|
||
"H = rows * TILE_SIZE\n",
|
||
"\n",
|
||
"print(f\"Mřížka: {cols} × {rows} dlaždic\")\n",
|
||
"print(f\"Výsledná mapa: {W} × {H} px\")\n",
|
||
"print(f\"Odhadovaná velikost (JPEG 85%): ~{W*H*3/1e6/10:.0f} MB\")"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"# Sestavení mapy — plná rozlišení\n",
|
||
"# Poznámka: ~18k × 17k px = ~3 GB v RAM → použijeme chunky nebo zmenšenou verzi\n",
|
||
"\n",
|
||
"OUTPUT_FULL = Path(\"hk_annotated_full.jpg\")\n",
|
||
"OUTPUT_PREVIEW = Path(\"hk_annotated_preview.jpg\")\n",
|
||
"PREVIEW_SCALE = 4 # 1/4 rozlišení pro preview\n",
|
||
"\n",
|
||
"# Zkontroluj dostupnou RAM\n",
|
||
"import psutil\n",
|
||
"ram_gb = psutil.virtual_memory().available / 1e9\n",
|
||
"needed_gb = W * H * 3 / 1e9\n",
|
||
"print(f\"Dostupná RAM: {ram_gb:.1f} GB, potřeba pro plnou mapu: {needed_gb:.1f} GB\")\n",
|
||
"\n",
|
||
"if needed_gb > ram_gb * 0.8:\n",
|
||
" print(\"⚠ Nedostatek RAM pro plnou mapu — generuji pouze preview\")\n",
|
||
" BUILD_FULL = False\n",
|
||
"else:\n",
|
||
" print(\"RAM dostačuje — generuji plnou mapu\")\n",
|
||
" BUILD_FULL = True"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"# Sestavení preview mapy (vždy)\n",
|
||
"pw = W // PREVIEW_SCALE\n",
|
||
"ph = H // PREVIEW_SCALE\n",
|
||
"ts_small = TILE_SIZE // PREVIEW_SCALE\n",
|
||
"\n",
|
||
"canvas_preview = Image.new(\"RGB\", (pw, ph), (30, 30, 30))\n",
|
||
"\n",
|
||
"missing = 0\n",
|
||
"for f in tqdm(tile_files, desc=\"Preview\"):\n",
|
||
" m = re.match(r\"18_(\\d+)_(\\d+)\\.jpg\", f.name)\n",
|
||
" if not m:\n",
|
||
" continue\n",
|
||
" xi = int(m.group(1)) - x_min\n",
|
||
" yi = int(m.group(2)) - y_min\n",
|
||
" try:\n",
|
||
" tile = Image.open(f).resize((ts_small, ts_small), Image.LANCZOS)\n",
|
||
" canvas_preview.paste(tile, (xi * ts_small, yi * ts_small))\n",
|
||
" except Exception as e:\n",
|
||
" missing += 1\n",
|
||
"\n",
|
||
"canvas_preview.save(OUTPUT_PREVIEW, quality=88, optimize=True)\n",
|
||
"print(f\"Preview mapa: {OUTPUT_PREVIEW} ({pw}×{ph} px)\")\n",
|
||
"if missing:\n",
|
||
" print(f\" Chybějící dlaždice: {missing}\")"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"# Sestavení plné mapy (pokud je dost RAM)\n",
|
||
"if BUILD_FULL:\n",
|
||
" canvas = Image.new(\"RGB\", (W, H), (30, 30, 30))\n",
|
||
"\n",
|
||
" for f in tqdm(tile_files, desc=\"Plná mapa\"):\n",
|
||
" m = re.match(r\"18_(\\d+)_(\\d+)\\.jpg\", f.name)\n",
|
||
" if not m:\n",
|
||
" continue\n",
|
||
" xi = int(m.group(1)) - x_min\n",
|
||
" yi = int(m.group(2)) - y_min\n",
|
||
" try:\n",
|
||
" tile = Image.open(f)\n",
|
||
" canvas.paste(tile, (xi * TILE_SIZE, yi * TILE_SIZE))\n",
|
||
" except Exception:\n",
|
||
" pass\n",
|
||
"\n",
|
||
" canvas.save(OUTPUT_FULL, quality=88, optimize=True)\n",
|
||
" print(f\"Plná mapa: {OUTPUT_FULL} ({W}×{H} px)\")\n",
|
||
" del canvas\n",
|
||
"else:\n",
|
||
" print(\"Plná mapa přeskočena (nedostatek RAM).\")\n",
|
||
" print(f\"Pro generování použij: python3 assemble_map.py\")"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"# Zobrazení preview mapy v notebooku\n",
|
||
"import matplotlib.pyplot as plt\n",
|
||
"import matplotlib.patches as mpatches\n",
|
||
"\n",
|
||
"preview = Image.open(OUTPUT_PREVIEW)\n",
|
||
"\n",
|
||
"fig, ax = plt.subplots(figsize=(16, 14))\n",
|
||
"ax.imshow(preview)\n",
|
||
"ax.set_title(f\"Hradec Králové — detekovaná vozidla\\n(preview {pw}×{ph} px)\", fontsize=14)\n",
|
||
"ax.axis(\"off\")\n",
|
||
"\n",
|
||
"# Legenda\n",
|
||
"legend_elements = [\n",
|
||
" mpatches.Patch(facecolor='#00DC00', edgecolor='white', label='car'),\n",
|
||
" mpatches.Patch(facecolor='#FFDC00', edgecolor='white', label='van'),\n",
|
||
" mpatches.Patch(facecolor='#DC0000', edgecolor='white', label='truck'),\n",
|
||
" mpatches.Patch(facecolor='#0078FF', edgecolor='white', label='bus'),\n",
|
||
"]\n",
|
||
"ax.legend(handles=legend_elements, loc='lower right', fontsize=12,\n",
|
||
" framealpha=0.8, title='Typy vozidel')\n",
|
||
"\n",
|
||
"plt.tight_layout()\n",
|
||
"plt.savefig(\"hk_map_overview.png\", dpi=100, bbox_inches=\"tight\")\n",
|
||
"plt.show()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"# Souhrn výsledků\n",
|
||
"with open(\"detections.json\") as f:\n",
|
||
" all_detections = json.load(f)\n",
|
||
"\n",
|
||
"from collections import Counter\n",
|
||
"CLASS_NAMES = [\"car\", \"van\", \"truck\", \"bus\"]\n",
|
||
"counts = Counter()\n",
|
||
"tiles_with_vehicles = 0\n",
|
||
"\n",
|
||
"for name, dets in all_detections.items():\n",
|
||
" if dets:\n",
|
||
" tiles_with_vehicles += 1\n",
|
||
" for d in dets:\n",
|
||
" counts[CLASS_NAMES[d[\"cls\"]]] += 1\n",
|
||
"\n",
|
||
"print(\"=\" * 40)\n",
|
||
"print(\"SOUHRN — Hradec Králové\")\n",
|
||
"print(\"=\" * 40)\n",
|
||
"print(f\"Zpracované dlaždice: {len(all_detections):6d}\")\n",
|
||
"print(f\"Dlaždice s vozidly: {tiles_with_vehicles:6d}\")\n",
|
||
"print()\n",
|
||
"print(\"Detekovaná vozidla:\")\n",
|
||
"for cls in CLASS_NAMES:\n",
|
||
" print(f\" {cls:10s}: {counts[cls]:6d}\")\n",
|
||
"print(f\" {'CELKEM':10s}: {sum(counts.values()):6d}\")\n",
|
||
"print(\"=\" * 40)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"# Sloupcový graf celkových počtů\n",
|
||
"fig, ax = plt.subplots(figsize=(8, 5))\n",
|
||
"\n",
|
||
"bar_colors = [\"#00DC00\", \"#FFDC00\", \"#DC0000\", \"#0078FF\"]\n",
|
||
"bars = ax.bar(CLASS_NAMES, [counts[c] for c in CLASS_NAMES], color=bar_colors, edgecolor=\"black\")\n",
|
||
"\n",
|
||
"for bar, cls in zip(bars, CLASS_NAMES):\n",
|
||
" ax.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 5,\n",
|
||
" str(counts[cls]), ha=\"center\", va=\"bottom\", fontsize=12, fontweight=\"bold\")\n",
|
||
"\n",
|
||
"ax.set_title(\"Počet detekovaných vozidel — Hradec Králové\", fontsize=14)\n",
|
||
"ax.set_ylabel(\"Počet vozidel\")\n",
|
||
"ax.set_xlabel(\"Typ vozidla\")\n",
|
||
"plt.tight_layout()\n",
|
||
"plt.savefig(\"vehicle_counts_chart.png\", dpi=150, bbox_inches=\"tight\")\n",
|
||
"plt.show()"
|
||
]
|
||
}
|
||
],
|
||
"metadata": {
|
||
"kernelspec": {
|
||
"display_name": "Python 3",
|
||
"language": "python",
|
||
"name": "python3"
|
||
},
|
||
"language_info": {
|
||
"name": "python",
|
||
"version": "3.10.0"
|
||
}
|
||
},
|
||
"nbformat": 4,
|
||
"nbformat_minor": 4
|
||
}
|