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

397 lines
13 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Enkel Billedklassificering\n",
"\n",
"Denne notebook viser dig, hvordan du klassificerer billeder ved hjælp af et forudtrænet neuralt netværk.\n",
"\n",
"**Hvad du vil lære:**\n",
"- Hvordan man indlæser og bruger en forudtrænet model\n",
"- Forbehandling af billeder\n",
"- At lave forudsigelser på billeder\n",
"- Forståelse af tillidsscorer\n",
"\n",
"**Anvendelse:** Identificer objekter i billeder (som \"kat\", \"hund\", \"bil\" osv.)\n",
"\n",
"---\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Trin 1: Importér nødvendige biblioteker\n",
"\n",
"Lad os importere de værktøjer, vi har brug for. Bare rolig, hvis du ikke forstår dem alle endnu!\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": [
"## Trin 2: Indlæs forudtrænet model\n",
"\n",
"Vi vil bruge **MobileNetV2**, et neuralt netværk, der allerede er trænet på millioner af billeder.\n",
"\n",
"Dette kaldes **Transfer Learning** - at bruge en model, som andre har trænet!\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": [
"## Trin 3: Hjælpefunktioner\n",
"\n",
"Lad os oprette funktioner til at indlæse og forberede billeder til vores 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": [
"## Trin 4: Test på eksempler fra billeder\n",
"\n",
"Lad os prøve at klassificere nogle billeder fra internettet!\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": [
"### Klassificer Hvert Billede\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": [
"## Trin 5: Prøv dine egne billeder!\n",
"\n",
"Erstat URL'en nedenfor med en hvilken som helst billed-URL, du ønsker at klassificere.\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": [
"## 💡 Hvad skete der lige?\n",
"\n",
"1. **Vi indlæste en forudtrænet model** - MobileNetV2 blev trænet på millioner af billeder\n",
"2. **Vi forbehandlede billeder** - Ændrede størrelse og formaterede dem til modellen\n",
"3. **Modellen lavede forudsigelser** - Den gav sandsynligheder for 1000 objektklasser\n",
"4. **Vi dekodede resultaterne** - Konverterede tal til menneskelæselige etiketter\n",
"\n",
"### Forståelse af tillidsscores\n",
"\n",
"- **90-100%**: Meget sikker (næsten helt korrekt)\n",
"- **70-90%**: Sikker (sandsynligvis korrekt)\n",
"- **50-70%**: Noget sikker (kan være korrekt)\n",
"- **Under 50%**: Ikke særlig sikker (usikker)\n",
"\n",
"### Hvorfor kan forudsigelser være forkerte?\n",
"\n",
"- **Usædvanlig vinkel eller belysning** - Modellen blev trænet på typiske fotos\n",
"- **Flere objekter** - Modellen forventer ét hovedobjekt\n",
"- **Sjældne objekter** - Modellen kender kun 1000 kategorier\n",
"- **Lav kvalitet billede** - Slørede eller pixelerede billeder er sværere at analysere\n",
"\n",
"---\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 🚀 Næste skridt\n",
"\n",
"1. **Prøv forskellige billeder:**\n",
" - Find billeder på [Unsplash](https://unsplash.com)\n",
" - Højreklik → \"Kopiér billedadresse\" for at få URL'en\n",
"\n",
"2. **Eksperimentér:**\n",
" - Hvad sker der med abstrakt kunst?\n",
" - Kan det genkende objekter fra forskellige vinkler?\n",
" - Hvordan håndterer det flere objekter?\n",
"\n",
"3. **Lær mere:**\n",
" - Udforsk [Computer Vision-lektioner](../lessons/4-ComputerVision/README.md)\n",
" - Lær at træne din egen billedklassifikator\n",
" - Forstå hvordan CNN'er (Convolutional Neural Networks) fungerer\n",
"\n",
"---\n",
"\n",
"## 🎉 Tillykke!\n",
"\n",
"Du har lige bygget en billedklassifikator ved hjælp af et avanceret neuralt netværk!\n",
"\n",
"Denne samme teknik driver:\n",
"- Google Photos (organisering af dine billeder)\n",
"- Selvkørende biler (genkendelse af objekter)\n",
"- Medicinsk diagnose (analyse af røntgenbilleder)\n",
"- Kvalitetskontrol (detektering af fejl)\n",
"\n",
"Bliv ved med at udforske og lære! 🚀\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Ansvarsfraskrivelse**: \nDette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på at sikre nøjagtighed, skal det bemærkes, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os ikke ansvar for misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.\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:47:27+00:00",
"source_file": "examples/03-image-classifier.ipynb",
"language_code": "da"
}
},
"nbformat": 4,
"nbformat_minor": 4
}