AI-For-Beginners/translations/hr/examples/03-image-classifier.ipynb

397 lines
13 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Jednostavni klasifikator slika\n",
"\n",
"Ovaj bilježnik pokazuje kako klasificirati slike koristeći unaprijed treniranu neuronsku mrežu.\n",
"\n",
"**Što ćete naučiti:**\n",
"- Kako učitati i koristiti unaprijed trenirani model\n",
"- Predobrada slika\n",
"- Predviđanje na slikama\n",
"- Razumijevanje rezultata pouzdanosti\n",
"\n",
"**Primjena:** Identifikacija objekata na slikama (poput \"mačka\", \"pas\", \"auto\", itd.)\n",
"\n",
"---\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Korak 1: Uvoz potrebnih biblioteka\n",
"\n",
"Uvezimo alate koji su nam potrebni. Ne brinite ako još ne razumijete sve ovo!\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": [
"## Korak 2: Učitavanje unaprijed treniranog modela\n",
"\n",
"Koristit ćemo **MobileNetV2**, neuronsku mrežu koja je već trenirana na milijunima slika.\n",
"\n",
"Ovo se naziva **Transfer Learning** - korištenje modela koji je netko drugi trenirao!\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": [
"## Korak 3: Pomoćne funkcije\n",
"\n",
"Napravimo funkcije za učitavanje i pripremu slika za naš model.\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": [
"## Korak 4: Testiranje na uzorcima slika\n",
"\n",
"Pokušajmo klasificirati neke slike s interneta!\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": [
"### Klasificirajte svaku sliku\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": [
"## Korak 5: Isprobajte vlastite slike!\n",
"\n",
"Zamijenite URL ispod bilo kojim URL-om slike koju želite klasificirati.\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": [
"## 💡 Što se upravo dogodilo?\n",
"\n",
"1. **Učitali smo unaprijed trenirani model** - MobileNetV2 je treniran na milijunima slika\n",
"2. **Predobradili smo slike** - Promijenili veličinu i formatirali ih za model\n",
"3. **Model je napravio predikcije** - Izračunao je vjerojatnosti za 1000 kategorija objekata\n",
"4. **Dekodirali smo rezultate** - Pretvorili brojeve u ljudima razumljive oznake\n",
"\n",
"### Razumijevanje razina pouzdanosti\n",
"\n",
"- **90-100%**: Vrlo pouzdano (gotovo sigurno točno)\n",
"- **70-90%**: Pouzdano (vjerojatno točno)\n",
"- **50-70%**: Djelomično pouzdano (možda točno)\n",
"- **Ispod 50%**: Nije jako pouzdano (neizvjesno)\n",
"\n",
"### Zašto predikcije mogu biti netočne?\n",
"\n",
"- **Neobičan kut ili osvjetljenje** - Model je treniran na tipičnim fotografijama\n",
"- **Više objekata** - Model očekuje jedan glavni objekt\n",
"- **Rijetki objekti** - Model poznaje samo 1000 kategorija\n",
"- **Slika niske kvalitete** - Zamućene ili pikselizirane slike su teže za analizu\n",
"\n",
"---\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 🚀 Sljedeći koraci\n",
"\n",
"1. **Isprobajte različite slike:**\n",
" - Pronađite slike na [Unsplash](https://unsplash.com)\n",
" - Desni klik → \"Kopiraj adresu slike\" za dobivanje URL-a\n",
"\n",
"2. **Eksperimentirajte:**\n",
" - Što se događa s apstraktnom umjetnošću?\n",
" - Može li prepoznati objekte iz različitih kutova?\n",
" - Kako se nosi s više objekata na slici?\n",
"\n",
"3. **Saznajte više:**\n",
" - Istražite [lekcije o računalnom vidu](../lessons/4-ComputerVision/README.md)\n",
" - Naučite kako trenirati vlastiti klasifikator slika\n",
" - Razumite kako funkcioniraju CNN-ovi (konvolucijske neuronske mreže)\n",
"\n",
"---\n",
"\n",
"## 🎉 Čestitamo!\n",
"\n",
"Upravo ste izradili klasifikator slika koristeći najmoderniju neuronsku mrežu!\n",
"\n",
"Ova ista tehnika pokreće:\n",
"- Google Photos (organiziranje vaših fotografija)\n",
"- Autonomna vozila (prepoznavanje objekata)\n",
"- Medicinsku dijagnostiku (analiza rendgenskih snimaka)\n",
"- Kontrolu kvalitete (otkrivanje nedostataka)\n",
"\n",
"Nastavite istraživati i učiti! 🚀\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Izjava o odricanju odgovornosti**: \nOvaj dokument je preveden pomoću AI usluge za prevođenje [Co-op Translator](https://github.com/Azure/co-op-translator). Iako nastojimo osigurati točnost, imajte na umu da automatski prijevodi mogu sadržavati pogreške ili netočnosti. Izvorni dokument na izvornom jeziku treba smatrati autoritativnim izvorom. Za ključne informacije preporučuje se profesionalni prijevod od strane ljudskog prevoditelja. Ne preuzimamo odgovornost za nesporazume ili pogrešna tumačenja koja mogu proizaći iz korištenja ovog prijevoda.\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:54:08+00:00",
"source_file": "examples/03-image-classifier.ipynb",
"language_code": "hr"
}
},
"nbformat": 4,
"nbformat_minor": 4
}