{
 "nbformat": 4,
 "nbformat_minor": 5,
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python",
   "version": "3.10.12"
  },
  "colab": {
   "provenance": [],
   "gpuType": "T4"
  },
  "accelerator": "GPU"
 },
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "tI2vuAiucSRx"
   },
   "source": "# 🍅 Topraksız Tarım Domates Üretiminde Böcek ve Parazit Tespiti\n## Google Colab + RTSP Kamera + YOLOv8\n\nBu notebook, topraksız (hidroponik) domates üretim tesislerinde **RTSP kamera akışından** gerçek zamanlı böcek ve parazit tespiti yapmak için hazırlanmıştır.\n\n**Özellikler:**\n- RTSP stream desteği (yeniden bağlanma mekanizmalı)\n- Ultralytics YOLOv8 / YOLOv11 modeli\n- Colab uyumlu görüntü gösterimi\n- Tespit loglama ve görüntü kaydetme\n- GPU desteği\n\n**Kullanım Öncesi:**\n1. Runtime → Change runtime type → **GPU** (T4 önerilir) seçin\n2. Aşağıdaki ayarlar hücresinde RTSP adresinizi ve model yolunu güncelleyin\n3. Kendi eğittiğiniz modeliniz varsa yükleyin\n\n---",
   "id": "tI2vuAiucSRx"
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "Xoeo_qMxcSR0"
   },
   "source": "## 1. Gerekli Kütüphanelerin Kurulumu",
   "id": "Xoeo_qMxcSR0"
  },
  {
   "cell_type": "code",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "h7u3ZR3icSR2",
    "executionInfo": {
     "status": "ok",
     "timestamp": 1786965529677,
     "user_tz": -180,
     "elapsed": 9141,
     "user": {
      "displayName": "Joseph Volkan ÖZCAN",
      "userId": "11389530967736397480"
     }
    },
    "outputId": "e58f57d4-eab1-4ced-b497-af533246dc41"
   },
   "source": "# Ultralytics YOLO ve diğer gerekli paketler\n!pip install -q ultralytics opencv-python-headless pillow\n\nprint(\"Kurulum tamamlandı.\")",
   "execution_count": 1,
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m45.5/45.5 kB\u001b[0m \u001b[31m2.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.4/1.4 MB\u001b[0m \u001b[31m24.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m63.9/63.9 kB\u001b[0m \u001b[31m6.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[?25hKurulum tamamlandı.\n"
     ]
    }
   ],
   "id": "h7u3ZR3icSR2"
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "6yGyFpE4cSR3"
   },
   "source": "## 2. Kütüphaneleri İçe Aktarma ve Ayarlar",
   "id": "6yGyFpE4cSR3"
  },
  {
   "cell_type": "code",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "Tes0Z_zvcSR4",
    "executionInfo": {
     "status": "ok",
     "timestamp": 1786965539133,
     "user_tz": -180,
     "elapsed": 9420,
     "user": {
      "displayName": "Joseph Volkan ÖZCAN",
      "userId": "11389530967736397480"
     }
    },
    "outputId": "6c419bcc-a4b5-4b18-a595-50eb26f1b49f"
   },
   "source": "import cv2\nimport time\nimport os\nfrom datetime import datetime\nfrom ultralytics import YOLO\nfrom IPython.display import display, clear_output\nfrom PIL import Image as PILImage\nimport numpy as np\n\n# ====================== AYARLAR ======================\nRTSP_URL = \"rtsp://kullanici:sifre@ip_adresi:554/stream1\"   # ← KENDİ RTSP ADRESİNİZİ YAZIN\n\n# Örnek RTSP formatları:\n# RTSP_URL = \"rtsp://admin:12345@192.168.1.100:554/Streaming/Channels/101\"\n# RTSP_URL = \"rtsp://192.168.1.50:8554/live\"\n\nMODEL_PATH = \"yolov8n.pt\"          # Kendi modeliniz varsa: \"best.pt\" veya \"tomato_pests.pt\"\nCONF_THRESHOLD = 0.45              # Güven eşiği (0.3 - 0.6 arası deneyin)\nIMGSZ = 640                        # Görüntü boyutu (küçük zararlılar için 1280 deneyebilirsiniz)\nSAVE_DETECTIONS = True             # Tespit edilen kareleri kaydet\nLOG_FILE = \"pest_log.txt\"\nDISPLAY_EVERY_N_FRAMES = 3         # Her kaç karede bir ekranda gösterilsin\nMAX_RUNTIME_MINUTES = 30           # Maksimum çalışma süresi (dakika)\n\n# Klasörleri oluştur\nos.makedirs(\"detections\", exist_ok=True)\n\nprint(\"Ayarlar yüklendi.\")\nprint(f\"RTSP: {RTSP_URL}\")\nprint(f\"Model: {MODEL_PATH}\")",
   "execution_count": 2,
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "Creating new Ultralytics Settings v0.0.7 file ✅ \n",
      "View Ultralytics Settings with 'yolo settings' or at '/root/.config/Ultralytics/settings.json'\n",
      "Update Settings with 'yolo settings key=value', i.e. 'yolo settings runs_dir=path/to/dir'. For help see https://docs.ultralytics.com/quickstart/#ultralytics-settings.\n",
      "Ayarlar yüklendi.\n",
      "RTSP: rtsp://kullanici:sifre@ip_adresi:554/stream1\n",
      "Model: yolov8n.pt\n"
     ]
    }
   ],
   "id": "Tes0Z_zvcSR4"
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "JY_rOpYbcSR5"
   },
   "source": "## 3. (Opsiyonel) Kendi Eğitilmiş Modelinizi Yükleyin\n\nEğer daha önce eğittiğiniz bir `.pt` dosyanız varsa bu hücreyi çalıştırarak yükleyebilirsiniz.",
   "id": "JY_rOpYbcSR5"
  },
  {
   "cell_type": "code",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 69
    },
    "id": "6hRtGUMTcSR6",
    "executionInfo": {
     "status": "ok",
     "timestamp": 1786965585128,
     "user_tz": -180,
     "elapsed": 45990,
     "user": {
      "displayName": "Joseph Volkan ÖZCAN",
      "userId": "11389530967736397480"
     }
    },
    "outputId": "77bf6186-797e-469a-cb15-45de5a2343cb"
   },
   "source": "# Kendi modelinizi yüklemek için bu hücreyi çalıştırın\nfrom google.colab import files\n\nprint(\"Model dosyanızı seçin (.pt uzantılı)...\")\nuploaded = files.upload()\n\n# Yüklenen dosya adını otomatik al\nif uploaded:\n    MODEL_PATH = list(uploaded.keys())[0]\n    print(f\"Model yüklendi: {MODEL_PATH}\")\nelse:\n    print(\"Dosya yüklenmedi. Varsayılan model kullanılacak.\")",
   "execution_count": 3,
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "Model dosyanızı seçin (.pt uzantılı)...\n"
     ]
    },
    {
     "output_type": "display_data",
     "data": {
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ],
      "text/html": [
       "\n",
       "     <input type=\"file\" id=\"files-90403c22-3423-4b23-8ce7-c96ed9038372\" name=\"files[]\" multiple disabled\n",
       "        style=\"border:none\" />\n",
       "     <output id=\"result-90403c22-3423-4b23-8ce7-c96ed9038372\">\n",
       "      Upload widget is only available when the cell has been executed in the\n",
       "      current browser session. Please rerun this cell to enable.\n",
       "      </output>\n",
       "      <script>// Copyright 2017 Google LLC\n",
       "//\n",
       "// Licensed under the Apache License, Version 2.0 (the \"License\");\n",
       "// you may not use this file except in compliance with the License.\n",
       "// You may obtain a copy of the License at\n",
       "//\n",
       "//      http://www.apache.org/licenses/LICENSE-2.0\n",
       "//\n",
       "// Unless required by applicable law or agreed to in writing, software\n",
       "// distributed under the License is distributed on an \"AS IS\" BASIS,\n",
       "// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
       "// See the License for the specific language governing permissions and\n",
       "// limitations under the License.\n",
       "\n",
       "/**\n",
       " * @fileoverview Helpers for google.colab Python module.\n",
       " */\n",
       "(function(scope) {\n",
       "function span(text, styleAttributes = {}) {\n",
       "  const element = document.createElement('span');\n",
       "  element.textContent = text;\n",
       "  for (const key of Object.keys(styleAttributes)) {\n",
       "    element.style[key] = styleAttributes[key];\n",
       "  }\n",
       "  return element;\n",
       "}\n",
       "\n",
       "// Max number of bytes which will be uploaded at a time.\n",
       "const MAX_PAYLOAD_SIZE = 100 * 1024;\n",
       "\n",
       "function _uploadFiles(inputId, outputId) {\n",
       "  const steps = uploadFilesStep(inputId, outputId);\n",
       "  const outputElement = document.getElementById(outputId);\n",
       "  // Cache steps on the outputElement to make it available for the next call\n",
       "  // to uploadFilesContinue from Python.\n",
       "  outputElement.steps = steps;\n",
       "\n",
       "  return _uploadFilesContinue(outputId);\n",
       "}\n",
       "\n",
       "// This is roughly an async generator (not supported in the browser yet),\n",
       "// where there are multiple asynchronous steps and the Python side is going\n",
       "// to poll for completion of each step.\n",
       "// This uses a Promise to block the python side on completion of each step,\n",
       "// then passes the result of the previous step as the input to the next step.\n",
       "function _uploadFilesContinue(outputId) {\n",
       "  const outputElement = document.getElementById(outputId);\n",
       "  const steps = outputElement.steps;\n",
       "\n",
       "  const next = steps.next(outputElement.lastPromiseValue);\n",
       "  return Promise.resolve(next.value.promise).then((value) => {\n",
       "    // Cache the last promise value to make it available to the next\n",
       "    // step of the generator.\n",
       "    outputElement.lastPromiseValue = value;\n",
       "    return next.value.response;\n",
       "  });\n",
       "}\n",
       "\n",
       "/**\n",
       " * Generator function which is called between each async step of the upload\n",
       " * process.\n",
       " * @param {string} inputId Element ID of the input file picker element.\n",
       " * @param {string} outputId Element ID of the output display.\n",
       " * @return {!Iterable<!Object>} Iterable of next steps.\n",
       " */\n",
       "function* uploadFilesStep(inputId, outputId) {\n",
       "  const inputElement = document.getElementById(inputId);\n",
       "  inputElement.disabled = false;\n",
       "\n",
       "  const outputElement = document.getElementById(outputId);\n",
       "  outputElement.innerHTML = '';\n",
       "\n",
       "  const pickedPromise = new Promise((resolve) => {\n",
       "    inputElement.addEventListener('change', (e) => {\n",
       "      resolve(e.target.files);\n",
       "    });\n",
       "  });\n",
       "\n",
       "  const cancel = document.createElement('button');\n",
       "  inputElement.parentElement.appendChild(cancel);\n",
       "  cancel.textContent = 'Cancel upload';\n",
       "  const cancelPromise = new Promise((resolve) => {\n",
       "    cancel.onclick = () => {\n",
       "      resolve(null);\n",
       "    };\n",
       "  });\n",
       "\n",
       "  // Wait for the user to pick the files.\n",
       "  const files = yield {\n",
       "    promise: Promise.race([pickedPromise, cancelPromise]),\n",
       "    response: {\n",
       "      action: 'starting',\n",
       "    }\n",
       "  };\n",
       "\n",
       "  cancel.remove();\n",
       "\n",
       "  // Disable the input element since further picks are not allowed.\n",
       "  inputElement.disabled = true;\n",
       "\n",
       "  if (!files) {\n",
       "    return {\n",
       "      response: {\n",
       "        action: 'complete',\n",
       "      }\n",
       "    };\n",
       "  }\n",
       "\n",
       "  for (const file of files) {\n",
       "    const li = document.createElement('li');\n",
       "    li.append(span(file.name, {fontWeight: 'bold'}));\n",
       "    li.append(span(\n",
       "        `(${file.type || 'n/a'}) - ${file.size} bytes, ` +\n",
       "        `last modified: ${\n",
       "            file.lastModifiedDate ? file.lastModifiedDate.toLocaleDateString() :\n",
       "                                    'n/a'} - `));\n",
       "    const percent = span('0% done');\n",
       "    li.appendChild(percent);\n",
       "\n",
       "    outputElement.appendChild(li);\n",
       "\n",
       "    const fileDataPromise = new Promise((resolve) => {\n",
       "      const reader = new FileReader();\n",
       "      reader.onload = (e) => {\n",
       "        resolve(e.target.result);\n",
       "      };\n",
       "      reader.readAsArrayBuffer(file);\n",
       "    });\n",
       "    // Wait for the data to be ready.\n",
       "    let fileData = yield {\n",
       "      promise: fileDataPromise,\n",
       "      response: {\n",
       "        action: 'continue',\n",
       "      }\n",
       "    };\n",
       "\n",
       "    // Use a chunked sending to avoid message size limits. See b/62115660.\n",
       "    let position = 0;\n",
       "    do {\n",
       "      const length = Math.min(fileData.byteLength - position, MAX_PAYLOAD_SIZE);\n",
       "      const chunk = new Uint8Array(fileData, position, length);\n",
       "      position += length;\n",
       "\n",
       "      const base64 = btoa(String.fromCharCode.apply(null, chunk));\n",
       "      yield {\n",
       "        response: {\n",
       "          action: 'append',\n",
       "          file: file.name,\n",
       "          data: base64,\n",
       "        },\n",
       "      };\n",
       "\n",
       "      let percentDone = fileData.byteLength === 0 ?\n",
       "          100 :\n",
       "          Math.round((position / fileData.byteLength) * 100);\n",
       "      percent.textContent = `${percentDone}% done`;\n",
       "\n",
       "    } while (position < fileData.byteLength);\n",
       "  }\n",
       "\n",
       "  // All done.\n",
       "  yield {\n",
       "    response: {\n",
       "      action: 'complete',\n",
       "    }\n",
       "  };\n",
       "}\n",
       "\n",
       "scope.google = scope.google || {};\n",
       "scope.google.colab = scope.google.colab || {};\n",
       "scope.google.colab._files = {\n",
       "  _uploadFiles,\n",
       "  _uploadFilesContinue,\n",
       "};\n",
       "})(self);\n",
       "</script> "
      ]
     },
     "metadata": {}
    },
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "Dosya yüklenmedi. Varsayılan model kullanılacak.\n"
     ]
    }
   ],
   "id": "6hRtGUMTcSR6"
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "nxlPymZ3cSR7"
   },
   "source": "## 4. YOLO Modelini Yükle",
   "id": "nxlPymZ3cSR7"
  },
  {
   "cell_type": "code",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "2MSvSQ7mcSR7",
    "executionInfo": {
     "status": "ok",
     "timestamp": 1786965585551,
     "user_tz": -180,
     "elapsed": 418,
     "user": {
      "displayName": "Joseph Volkan ÖZCAN",
      "userId": "11389530967736397480"
     }
    },
    "outputId": "d1321006-3403-48d9-a273-244b036eb24a"
   },
   "source": "print(\"Model yükleniyor...\")\nmodel = YOLO(MODEL_PATH)\nprint(f\"Model başarıyla yüklendi.\")\nprint(f\"Sınıflar: {model.names}\")",
   "execution_count": 4,
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "Model yükleniyor...\n",
      "\u001b[KDownloading https://github.com/ultralytics/assets/releases/download/v8.4.0/yolov8n.pt to 'yolov8n.pt': 100% ━━━━━━━━━━━━ 6.2MB 79.8MB/s 0.1s\n",
      "Model başarıyla yüklendi.\n",
      "Sınıflar: {0: 'person', 1: 'bicycle', 2: 'car', 3: 'motorcycle', 4: 'airplane', 5: 'bus', 6: 'train', 7: 'truck', 8: 'boat', 9: 'traffic light', 10: 'fire hydrant', 11: 'stop sign', 12: 'parking meter', 13: 'bench', 14: 'bird', 15: 'cat', 16: 'dog', 17: 'horse', 18: 'sheep', 19: 'cow', 20: 'elephant', 21: 'bear', 22: 'zebra', 23: 'giraffe', 24: 'backpack', 25: 'umbrella', 26: 'handbag', 27: 'tie', 28: 'suitcase', 29: 'frisbee', 30: 'skis', 31: 'snowboard', 32: 'sports ball', 33: 'kite', 34: 'baseball bat', 35: 'baseball glove', 36: 'skateboard', 37: 'surfboard', 38: 'tennis racket', 39: 'bottle', 40: 'wine glass', 41: 'cup', 42: 'fork', 43: 'knife', 44: 'spoon', 45: 'bowl', 46: 'banana', 47: 'apple', 48: 'sandwich', 49: 'orange', 50: 'broccoli', 51: 'carrot', 52: 'hot dog', 53: 'pizza', 54: 'donut', 55: 'cake', 56: 'chair', 57: 'couch', 58: 'potted plant', 59: 'bed', 60: 'dining table', 61: 'toilet', 62: 'tv', 63: 'laptop', 64: 'mouse', 65: 'remote', 66: 'keyboard', 67: 'cell phone', 68: 'microwave', 69: 'oven', 70: 'toaster', 71: 'sink', 72: 'refrigerator', 73: 'book', 74: 'clock', 75: 'vase', 76: 'scissors', 77: 'teddy bear', 78: 'hair drier', 79: 'toothbrush'}\n"
     ]
    }
   ],
   "id": "2MSvSQ7mcSR7"
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "YHV5AJ6AcSR8"
   },
   "source": "## 5. RTSP Bağlantı ve Tespit Fonksiyonları",
   "id": "YHV5AJ6AcSR8"
  },
  {
   "cell_type": "code",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "TXNCWPJFcSR8",
    "executionInfo": {
     "status": "ok",
     "timestamp": 1786965585623,
     "user_tz": -180,
     "elapsed": 67,
     "user": {
      "displayName": "Joseph Volkan ÖZCAN",
      "userId": "11389530967736397480"
     }
    },
    "outputId": "ef3bc477-5e5f-4193-abd7-1e0d63faeabb"
   },
   "source": "def connect_rtsp(url, max_retries=5):\n    \"\"\"RTSP bağlantısını dener, başarısız olursa yeniden dener\"\"\"\n    for attempt in range(max_retries):\n        print(f\"RTSP bağlantısı deneniyor... ({attempt+1}/{max_retries})\")\n        cap = cv2.VideoCapture(url)\n        # RTSP için önemli ayarlar - gecikmeyi azaltır\n        cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)\n        cap.set(cv2.CAP_PROP_FPS, 15)\n\n        if cap.isOpened():\n            print(\"✅ RTSP bağlantısı başarılı!\")\n            return cap\n        time.sleep(2)\n\n    raise ConnectionError(\"❌ RTSP kameraya bağlanılamadı. URL, kullanıcı adı/şifre veya ağı kontrol edin.\")\n\n\ndef log_detection(frame, results, timestamp):\n    \"\"\"Tespit edilen zararlıları loglar ve görüntüyü kaydeder\"\"\"\n    detected = []\n    for r in results:\n        for box in r.boxes:\n            conf = float(box.conf[0])\n            if conf >= CONF_THRESHOLD:\n                cls_id = int(box.cls[0])\n                name = model.names[cls_id]\n                detected.append(f\"{name}:{conf:.2f}\")\n\n    if detected:\n        log_line = f\"{timestamp} | {', '.join(detected)}\\n\"\n        with open(LOG_FILE, \"a\", encoding=\"utf-8\") as f:\n            f.write(log_line)\n\n        if SAVE_DETECTIONS:\n            filename = f\"detections/{timestamp.replace(':', '-').replace(' ', '_')}.jpg\"\n            cv2.imwrite(filename, frame)\n\n        print(f\"⚠️  [UYARI] {timestamp} → {detected}\")\n    return len(detected) > 0\n\nprint(\"Fonksiyonlar hazır.\")",
   "execution_count": 5,
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "Fonksiyonlar hazır.\n"
     ]
    }
   ],
   "id": "TXNCWPJFcSR8"
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "Z6UJtXczcSR9"
   },
   "source": "## 6. Ana Tespit Döngüsü (RTSP + YOLO)\n\n**Önemli:**\n- Çalıştırmadan önce RTSP_URL değişkeninin doğru olduğundan emin olun.\n- Durdurmak için: Runtime → Interrupt execution\n- Colab oturumu uzun süre açık kalırsa kesilebilir. MAX_RUNTIME_MINUTES ile sınır koyabilirsiniz.",
   "id": "Z6UJtXczcSR9"
  },
  {
   "cell_type": "code",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 411
    },
    "id": "MsPr19z8cSR9",
    "executionInfo": {
     "status": "error",
     "timestamp": 1786965595766,
     "user_tz": -180,
     "elapsed": 10141,
     "user": {
      "displayName": "Joseph Volkan ÖZCAN",
      "userId": "11389530967736397480"
     }
    },
    "outputId": "26abfd6a-383a-464c-ebca-45fd376d478c"
   },
   "source": "# ---- Ana Döngü ----\ncap = connect_rtsp(RTSP_URL)\n\nstart_time = time.time()\nframe_count = 0\n\nprint(\"\\n🚀 Analiz başladı. Durdurmak için Runtime → Interrupt execution kullanın.\\n\")\n\ntry:\n    while True:\n        # Maksimum süre kontrolü\n        if (time.time() - start_time) > MAX_RUNTIME_MINUTES * 60:\n            print(\"⏱️  Maksimum çalışma süresine ulaşıldı.\")\n            break\n\n        ret, frame = cap.read()\n        if not ret:\n            print(\"⚠️  Kare alınamadı, yeniden bağlanılıyor...\")\n            cap.release()\n            time.sleep(2)\n            cap = connect_rtsp(RTSP_URL)\n            continue\n\n        frame_count += 1\n\n        # YOLO tespiti\n        results = model.predict(\n            frame,\n            conf=CONF_THRESHOLD,\n            imgsz=IMGSZ,\n            verbose=False,\n            device=0          # GPU kullan\n        )\n\n        # Sonuçları çiz\n        annotated = results[0].plot()\n\n        # Tarih-saat ve FPS bilgisi\n        timestamp = datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\")\n        fps = frame_count / (time.time() - start_time + 1e-6)\n        cv2.putText(annotated, f\"{timestamp} | FPS: {fps:.1f}\", (10, 30),\n                    cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)\n\n        # Tespit logla\n        has_detection = log_detection(frame, results, timestamp)\n\n        # Colab'da görüntü göster (her N karede bir veya tespit olduğunda)\n        if frame_count % DISPLAY_EVERY_N_FRAMES == 0 or has_detection:\n            clear_output(wait=True)\n\n            # Küçültülmüş gösterim (Colab çıktısını şişirmemek için)\n            display_frame = cv2.resize(annotated, (960, 540))\n            display_frame = cv2.cvtColor(display_frame, cv2.COLOR_BGR2RGB)\n\n            pil_img = PILImage.fromarray(display_frame)\n            display(pil_img)\n\n            print(f\"Kare: {frame_count} | Zaman: {timestamp} | Tespit: {'EVET ⚠️' if has_detection else 'Yok'}\")\n\n        # Döngüyü biraz yavaşlat (kaynak kullanımı için)\n        time.sleep(0.03)\n\nexcept KeyboardInterrupt:\n    print(\"\\n🛑 Kullanıcı tarafından durduruldu.\")\nfinally:\n    cap.release()\n    print(f\"\\n✅ Toplam işlenen kare: {frame_count}\")\n    print(f\"📄 Log dosyası: {LOG_FILE}\")\n    print(\"Program sonlandırıldı.\")",
   "execution_count": 6,
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "RTSP bağlantısı deneniyor... (1/5)\n",
      "RTSP bağlantısı deneniyor... (2/5)\n",
      "RTSP bağlantısı deneniyor... (3/5)\n",
      "RTSP bağlantısı deneniyor... (4/5)\n",
      "RTSP bağlantısı deneniyor... (5/5)\n"
     ]
    },
    {
     "output_type": "error",
     "ename": "ConnectionError",
     "evalue": "❌ RTSP kameraya bağlanılamadı. URL, kullanıcı adı/şifre veya ağı kontrol edin.",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mConnectionError\u001b[0m                           Traceback (most recent call last)",
      "\u001b[0;32m/tmp/ipykernel_1497/3498499944.py\u001b[0m in \u001b[0;36m<cell line: 0>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0;31m# ---- Ana Döngü ----\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mcap\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mconnect_rtsp\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mRTSP_URL\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      3\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      4\u001b[0m \u001b[0mstart_time\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtime\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtime\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      5\u001b[0m \u001b[0mframe_count\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/tmp/ipykernel_1497/1065318422.py\u001b[0m in \u001b[0;36mconnect_rtsp\u001b[0;34m(url, max_retries)\u001b[0m\n\u001b[1;32m     13\u001b[0m         \u001b[0mtime\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msleep\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     14\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 15\u001b[0;31m     \u001b[0;32mraise\u001b[0m \u001b[0mConnectionError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"❌ RTSP kameraya bağlanılamadı. URL, kullanıcı adı/şifre veya ağı kontrol edin.\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     16\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     17\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mConnectionError\u001b[0m: ❌ RTSP kameraya bağlanılamadı. URL, kullanıcı adı/şifre veya ağı kontrol edin."
     ]
    }
   ],
   "id": "MsPr19z8cSR9"
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "P3ctfqfccSR-"
   },
   "source": "## 7. Sonuçları İndirme\n\nTespit edilen görüntüleri ve log dosyasını bilgisayarınıza indirmek için aşağıdaki hücreleri kullanın.",
   "id": "P3ctfqfccSR-"
  },
  {
   "cell_type": "code",
   "metadata": {
    "id": "GGdtoBzUcSR_",
    "executionInfo": {
     "status": "aborted",
     "timestamp": 1786965595739,
     "user_tz": -180,
     "elapsed": 75381,
     "user": {
      "displayName": "Joseph Volkan ÖZCAN",
      "userId": "11389530967736397480"
     }
    }
   },
   "source": "# Tespit edilen görüntüleri zipleyip indir\nfrom google.colab import files\nimport shutil\n\nif os.path.exists(\"detections\") and len(os.listdir(\"detections\")) > 0:\n    shutil.make_archive(\"detections\", \"zip\", \"detections\")\n    files.download(\"detections.zip\")\n    print(\"detections.zip indirildi.\")\nelse:\n    print(\"Henüz kaydedilmiş tespit görüntüsü yok.\")",
   "execution_count": null,
   "outputs": [],
   "id": "GGdtoBzUcSR_"
  },
  {
   "cell_type": "code",
   "metadata": {
    "id": "Ujazi9P9cSR_",
    "executionInfo": {
     "status": "aborted",
     "timestamp": 1786965595762,
     "user_tz": -180,
     "elapsed": 75403,
     "user": {
      "displayName": "Joseph Volkan ÖZCAN",
      "userId": "11389530967736397480"
     }
    }
   },
   "source": "# Log dosyasını indir\nif os.path.exists(LOG_FILE):\n    files.download(LOG_FILE)\n    print(f\"{LOG_FILE} indirildi.\")\nelse:\n    print(\"Log dosyası henüz oluşturulmadı.\")",
   "execution_count": null,
   "outputs": [],
   "id": "Ujazi9P9cSR_"
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "a1CdKrupcSSA"
   },
   "source": "## 8. Ek Bilgiler ve İpuçları\n\n### RTSP Bağlantı Sorunları\n- RTSP adresini önce VLC Media Player ile test edin.\n- Kullanıcı adı, şifre ve portun doğru olduğundan emin olun.\n- Yerel ağdaysanız Colab’ın internet erişimi olduğunu unutmayın (bazı kameralar sadece LAN’da çalışır → port yönlendirme veya VPN gerekebilir).\n\n### Model Performansı\n- `yolov8n.pt` → Hızlı ama daha az doğru\n- `yolov8s.pt` / `yolov8m.pt` → Daha yüksek doğruluk, biraz yavaş\n- Kendi verinizle eğittiğiniz model en iyi sonucu verir.\n\n### Küçük Zararlılar İçin\n- `IMGSZ = 1280` deneyin\n- `CONF_THRESHOLD` değerini 0.35–0.40’a düşürebilirsiniz\n- Sticky trap (sarı yapışkan tuzak) kullanımı doğruluğu önemli ölçüde artırır.\n\n### Geliştirme Önerileri\n- Telegram bot ile anlık uyarı\n- Belirli sınıfları filtreleme (sadece whitefly, tuta vb.)\n- Tracking ekleyerek aynı böceği takip etme\n- Edge cihazda (Jetson / Raspberry Pi) çalışacak hafif versiyon\n\n---\n**Hazırlayan:** Grok (xAI) – Topraksız tarım domates böcek/parazit tespit sistemi  \nSorularınız için notebook’u güncelleyebilirim.",
   "id": "a1CdKrupcSSA"
  }
 ]
}