397 lines
14 KiB
Plaintext
397 lines
14 KiB
Plaintext
{
|
||
"cells": [
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"# מסווג תמונות פשוט\n",
|
||
"\n",
|
||
"מחברת זו מראה כיצד לסווג תמונות באמצעות רשת עצבית מאומנת מראש.\n",
|
||
"\n",
|
||
"**מה תלמדו:**\n",
|
||
"- כיצד לטעון ולהשתמש במודל מאומן מראש\n",
|
||
"- עיבוד מקדים של תמונות\n",
|
||
"- ביצוע תחזיות על תמונות\n",
|
||
"- הבנת ציוני ביטחון\n",
|
||
"\n",
|
||
"**שימוש:** זיהוי אובייקטים בתמונות (כמו \"חתול\", \"כלב\", \"מכונית\" וכו') \n",
|
||
"\n",
|
||
"---\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## שלב 1: ייבוא ספריות נדרשות\n",
|
||
"\n",
|
||
"בואו נייבא את הכלים שאנחנו צריכים. אל תדאגו אם אתם עדיין לא מבינים את כולם!\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": [
|
||
"## שלב 2: טעינת מודל מאומן מראש\n",
|
||
"\n",
|
||
"נשתמש ב-**MobileNetV2**, רשת נוירונים שכבר אומנה על מיליוני תמונות.\n",
|
||
"\n",
|
||
"זה נקרא **למידה מעבירה** - שימוש במודל שמישהו אחר כבר אימן!\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": [
|
||
"## שלב 3: פונקציות עזר\n",
|
||
"\n",
|
||
"בואו ניצור פונקציות לטעינת תמונות ולהכנתן עבור המודל שלנו.\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": [
|
||
"## שלב 4: בדיקה על תמונות לדוגמה\n",
|
||
"\n",
|
||
"בואו ננסה לסווג כמה תמונות מהאינטרנט!\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": [
|
||
"### סווג כל תמונה\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": [
|
||
"## שלב 5: נסו תמונות משלכם!\n",
|
||
"\n",
|
||
"החליפו את כתובת ה-URL למטה בכל כתובת URL של תמונה שתרצו לסווג.\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": [
|
||
"## 💡 מה קרה עכשיו?\n",
|
||
"\n",
|
||
"1. **טענו מודל מאומן מראש** - MobileNetV2 אומן על מיליוני תמונות \n",
|
||
"2. **עיבדנו תמונות** - שינינו גודל ועיצבנו אותן עבור המודל \n",
|
||
"3. **המודל ביצע תחזיות** - הוא הפיק הסתברויות עבור 1000 קטגוריות של אובייקטים \n",
|
||
"4. **פענחנו את התוצאות** - המרה של מספרים לתוויות קריאות לבני אדם \n",
|
||
"\n",
|
||
"### הבנת ציוני ביטחון\n",
|
||
"\n",
|
||
"- **90-100%**: ביטחון גבוה מאוד (כמעט בוודאות נכון) \n",
|
||
"- **70-90%**: ביטחון גבוה (כנראה נכון) \n",
|
||
"- **50-70%**: ביטחון מסוים (אולי נכון) \n",
|
||
"- **מתחת ל-50%**: ביטחון נמוך (לא בטוח) \n",
|
||
"\n",
|
||
"### למה התחזיות עשויות להיות שגויות?\n",
|
||
"\n",
|
||
"- **זווית או תאורה לא שגרתית** - המודל אומן על תמונות טיפוסיות \n",
|
||
"- **אובייקטים מרובים** - המודל מצפה לאובייקט עיקרי אחד \n",
|
||
"- **אובייקטים נדירים** - המודל מכיר רק 1000 קטגוריות \n",
|
||
"- **תמונה באיכות נמוכה** - תמונות מטושטשות או מפוקסלות קשות יותר לזיהוי \n",
|
||
"\n",
|
||
"---\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## 🚀 צעדים הבאים\n",
|
||
"\n",
|
||
"1. **נסו תמונות שונות:**\n",
|
||
" - מצאו תמונות ב-[Unsplash](https://unsplash.com)\n",
|
||
" - לחצו לחיצה ימנית → \"העתק כתובת תמונה\" כדי לקבל את ה-URL\n",
|
||
"\n",
|
||
"2. **התנסו:**\n",
|
||
" - מה קורה עם אמנות מופשטת?\n",
|
||
" - האם ניתן לזהות אובייקטים מזוויות שונות?\n",
|
||
" - איך המערכת מתמודדת עם מספר אובייקטים?\n",
|
||
"\n",
|
||
"3. **למדו עוד:**\n",
|
||
" - חקרו את [השיעורים על ראייה ממוחשבת](../lessons/4-ComputerVision/README.md)\n",
|
||
" - למדו איך לאמן מסווג תמונות משלכם\n",
|
||
" - הבינו איך CNNs (רשתות עצביות קונבולוציוניות) פועלות\n",
|
||
"\n",
|
||
"---\n",
|
||
"\n",
|
||
"## 🎉 מזל טוב!\n",
|
||
"\n",
|
||
"הרגע בניתם מסווג תמונות באמצעות רשת עצבית מתקדמת!\n",
|
||
"\n",
|
||
"אותה טכניקה משמשת ל:\n",
|
||
"- Google Photos (ארגון התמונות שלכם)\n",
|
||
"- מכוניות אוטונומיות (זיהוי אובייקטים)\n",
|
||
"- אבחון רפואי (ניתוח צילומי רנטגן)\n",
|
||
"- בקרת איכות (זיהוי פגמים)\n",
|
||
"\n",
|
||
"המשיכו לחקור וללמוד! 🚀\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"\n---\n\n**כתב ויתור**: \nמסמך זה תורגם באמצעות שירות תרגום מבוסס AI [Co-op Translator](https://github.com/Azure/co-op-translator). למרות שאנו שואפים לדיוק, יש לקחת בחשבון שתרגומים אוטומטיים עשויים להכיל שגיאות או אי דיוקים. המסמך המקורי בשפתו המקורית צריך להיחשב כמקור סמכותי. עבור מידע קריטי, מומלץ להשתמש בתרגום מקצועי על ידי אדם. איננו נושאים באחריות לאי הבנות או לפרשנויות שגויות הנובעות משימוש בתרגום זה.\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:49:03+00:00",
|
||
"source_file": "examples/03-image-classifier.ipynb",
|
||
"language_code": "he"
|
||
}
|
||
},
|
||
"nbformat": 4,
|
||
"nbformat_minor": 4
|
||
} |