{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":19989,"databundleVersionId":1160143,"sourceType":"competition"},{"sourceId":8094053,"sourceType":"datasetVersion","datasetId":4611404}],"dockerImageVersionId":30919,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!pip install ultralytics matplotlib seaborn opencv-python pandas tqdm","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-02-25T09:48:25.250576Z","iopub.execute_input":"2025-02-25T09:48:25.250895Z","iopub.status.idle":"2025-02-25T09:48:28.745238Z","shell.execute_reply.started":"2025-02-25T09:48:25.250868Z","shell.execute_reply":"2025-02-25T09:48:28.744177Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os, shutil\n\n# Define input paths (these come from the Kaggle dataset)\ninput_train_dir = \"/kaggle/input/wheat-plant-diseases/data/train\"\ninput_valid_dir = \"/kaggle/input/wheat-plant-diseases/data/valid\"\ninput_test_dir  = \"/kaggle/input/wheat-plant-diseases/data/test\"\n\n# Define working directories\nbase_dir = \"/kaggle/working/datasets/GlobalWheat2021\"\ntrain_img_dir = os.path.join(base_dir, \"images\", \"train_flat\")\nvalid_img_dir = os.path.join(base_dir, \"images\", \"valid_flat\")\ntest_img_dir  = os.path.join(base_dir, \"images\", \"test\")\ntrain_lbl_dir = os.path.join(base_dir, \"labels\", \"train\")\nvalid_lbl_dir = os.path.join(base_dir, \"labels\", \"valid\")\n\nos.makedirs(train_img_dir, exist_ok=True)\nos.makedirs(valid_img_dir, exist_ok=True)\nos.makedirs(test_img_dir, exist_ok=True)\nos.makedirs(train_lbl_dir, exist_ok=True)\nos.makedirs(valid_lbl_dir, exist_ok=True)\n\n# Create a mapping from class names to numeric labels by listing subdirectories in input_train_dir\nclasses = sorted([d for d in os.listdir(input_train_dir) if os.path.isdir(os.path.join(input_train_dir, d))])\nif len(classes)==0:\n    classes = [\"wheat_disease\"]\nclass_to_id = {cls: i for i, cls in enumerate(classes)}\nprint(\"Class mapping:\", class_to_id)\n\n# Function to copy images from a source folder (which may contain subfolders) to a destination folder\n# and create a corresponding YOLO annotation (full image: 0.5,0.5,1.0,1.0) based on the folder (class) name.\ndef process_folder(src_folder, dest_img_dir, dest_lbl_dir):\n    for cls in os.listdir(src_folder):\n        cls_path = os.path.join(src_folder, cls)\n        if os.path.isdir(cls_path):\n            for file in os.listdir(cls_path):\n                if file.lower().endswith(('.jpg', '.jpeg', '.png')):\n                    # Copy image to destination (use the original filename)\n                    src_img = os.path.join(cls_path, file)\n                    dest_img = os.path.join(dest_img_dir, file)\n                    shutil.copy(src_img, dest_img)\n                    # Write label file: one line with <class_id> 0.5 0.5 1.0 1.0\n                    label_file = os.path.join(dest_lbl_dir, f\"{os.path.splitext(file)[0]}.txt\")\n                    with open(label_file, \"w\") as f:\n                        f.write(f\"{class_to_id.get(cls,0)} 0.5 0.5 1.0 1.0\\n\")\n        else:\n            # If no subfolders (flat structure), treat all images as class 0\n            if cls.lower().endswith(('.jpg', '.jpeg', '.png')):\n                src_img = os.path.join(src_folder, cls)\n                dest_img = os.path.join(dest_img_dir, cls)\n                shutil.copy(src_img, dest_img)\n                label_file = os.path.join(dest_lbl_dir, f\"{os.path.splitext(cls)[0]}.txt\")\n                with open(label_file, \"w\") as f:\n                    f.write(\"0 0.5 0.5 1.0 1.0\\n\")\n\n# Process training and validation sets\nprocess_folder(input_train_dir, train_img_dir, train_lbl_dir)\nprocess_folder(input_valid_dir, valid_img_dir, valid_lbl_dir)\n\n# For test images, we only need to copy them (no labels)\nif os.path.isdir(input_test_dir):\n    for file in os.listdir(input_test_dir):\n        if file.lower().endswith(('.jpg', '.jpeg', '.png')):\n            src_img = os.path.join(input_test_dir, file)\n            dest_img = os.path.join(test_img_dir, file)\n            shutil.copy(src_img, dest_img)\n            \nprint(\"Data copying and label creation complete.\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-25T09:48:28.746536Z","iopub.execute_input":"2025-02-25T09:48:28.746808Z","iopub.status.idle":"2025-02-25T09:50:55.188894Z","shell.execute_reply.started":"2025-02-25T09:48:28.746778Z","shell.execute_reply":"2025-02-25T09:50:55.188032Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"%%writefile GlobalWheat2021.yaml\npath: /kaggle/working/datasets/GlobalWheat2021\ntrain: images/train_flat\nval: images/valid_flat\ntest: images/test\n\nnames:\n  0: wheat_disease\n# If there are more classes, list them here (order according to class_to_id)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-25T09:50:55.190318Z","iopub.execute_input":"2025-02-25T09:50:55.190538Z","iopub.status.idle":"2025-02-25T09:50:55.196233Z","shell.execute_reply.started":"2025-02-25T09:50:55.190514Z","shell.execute_reply":"2025-02-25T09:50:55.195380Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import cv2\nimport matplotlib.pyplot as plt\nimport os\n\ndef show_image_with_annotation(img_path, lbl_path):\n    img = cv2.imread(img_path)\n    if img is None:\n        print(\"Image not found:\", img_path)\n        return\n    # Read the annotation\n    with open(lbl_path, \"r\") as f:\n        line = f.readline().strip().split()\n    # YOLO format: class x_center y_center width height (normalized)\n    cls, xc, yc, w, h = line\n    h_img, w_img = img.shape[:2]\n    # Denormalize box coordinates\n    xc, yc, w, h = float(xc)*w_img, float(yc)*h_img, float(w)*w_img, float(h)*h_img\n    x1 = int(xc - w/2)\n    y1 = int(yc - h/2)\n    x2 = int(xc + w/2)\n    y2 = int(yc + h/2)\n    # Draw rectangle\n    cv2.rectangle(img, (x1, y1), (x2, y2), (0,0,255), 2)\n    img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n    plt.figure(figsize=(8,6))\n    plt.imshow(img_rgb)\n    plt.title(f\"{os.path.basename(img_path)} | Class: {cls}\")\n    plt.axis('off')\n    plt.show()\n\n# Show 3 random training images with annotations\nimport random\ntrain_imgs = os.listdir(train_img_dir)\nfor img_file in random.sample(train_imgs, 3):\n    img_path = os.path.join(train_img_dir, img_file)\n    lbl_path = os.path.join(train_lbl_dir, f\"{os.path.splitext(img_file)[0]}.txt\")\n    if os.path.exists(lbl_path):\n        show_image_with_annotation(img_path, lbl_path)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-25T09:50:55.197348Z","iopub.execute_input":"2025-02-25T09:50:55.197657Z","iopub.status.idle":"2025-02-25T09:50:56.620680Z","shell.execute_reply.started":"2025-02-25T09:50:55.197628Z","shell.execute_reply":"2025-02-25T09:50:56.619714Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!wget -O yolov12n.pt https://github.com/yourusername/yolov12/releases/download/v1.0/yolov12n.pt\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-25T09:50:56.621520Z","iopub.execute_input":"2025-02-25T09:50:56.621774Z","iopub.status.idle":"2025-02-25T09:50:56.943891Z","shell.execute_reply.started":"2025-02-25T09:50:56.621753Z","shell.execute_reply":"2025-02-25T09:50:56.943034Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Download the YOLOv12 configuration file\n!wget -O yolo12.yaml https://raw.githubusercontent.com/ultralytics/ultralytics/main/ultralytics/cfg/models/12/yolo12.yaml\n\n# Import and instantiate the model using the config file\nfrom ultralytics import YOLO\nmodel = YOLO('yolo12.yaml')\n\n# Print model summary using the info() method\nmodel.info()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-25T09:50:56.944707Z","iopub.execute_input":"2025-02-25T09:50:56.944972Z","iopub.status.idle":"2025-02-25T09:51:02.160162Z","shell.execute_reply.started":"2025-02-25T09:50:56.944948Z","shell.execute_reply":"2025-02-25T09:51:02.159207Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(model)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-25T09:51:02.161283Z","iopub.execute_input":"2025-02-25T09:51:02.161777Z","iopub.status.idle":"2025-02-25T09:51:02.170790Z","shell.execute_reply.started":"2025-02-25T09:51:02.161733Z","shell.execute_reply":"2025-02-25T09:51:02.169930Z"},"collapsed":true,"jupyter":{"outputs_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os, cv2, shutil\nfrom tqdm import tqdm\n\n# Define input directories (as provided by the Kaggle dataset)\n# (These paths depend on the dataset structure on Kaggle.)\ninput_train_dir = \"/kaggle/input/wheat-plant-diseases/data/train\"\ninput_valid_dir = \"/kaggle/input/wheat-plant-diseases/data/valid\"\ninput_test_dir  = \"/kaggle/input/wheat-plant-diseases/data/test\"\n\n# Define working (output) directories in Kaggle working area\nbase_dir = \"/kaggle/working/datasets/GlobalWheat2021\"\ntrain_img_out = os.path.join(base_dir, \"images\", \"train_flat\")\nvalid_img_out = os.path.join(base_dir, \"images\", \"valid_flat\")\ntest_img_out  = os.path.join(base_dir, \"images\", \"test\")\n\ntrain_lbl_out = os.path.join(base_dir, \"labels\", \"train_flat\")\nvalid_lbl_out = os.path.join(base_dir, \"labels\", \"valid_flat\")\n\n# Create directories if they don't exist\nfor d in [train_img_out, valid_img_out, test_img_out, train_lbl_out, valid_lbl_out]:\n    os.makedirs(d, exist_ok=True)\n\n# Function to process a folder of images: copy valid images to a flat folder and generate a label file.\n# For each valid image, we generate a label with a full-image box: \"0 0.5 0.5 1.0 1.0\"\ndef process_images(input_dir, img_out_dir, lbl_out_dir):\n    # If images are organized in subfolders, traverse them\n    count = 0\n    for root, dirs, files in os.walk(input_dir):\n        for file in files:\n            if file.lower().endswith(('.jpg', '.jpeg', '.png', '.tiff', '.bmp')):\n                src = os.path.join(root, file)\n                # Try to read image using cv2; if not valid, skip.\n                img = cv2.imread(src)\n                if img is None:\n                    # Skip corrupt image formats (e.g. GIF) or unreadable files.\n                    continue\n                # Save to flat folder using the original filename.\n                dest_img = os.path.join(img_out_dir, file)\n                shutil.copy(src, dest_img)\n                # Generate label file (full image box)\n                # YOLO expects: <class> <x_center> <y_center> <width> <height> (all normalized)\n                # For a full image box, that is: \"0 0.5 0.5 1.0 1.0\"\n                label_filename = os.path.splitext(file)[0] + \".txt\"\n                dest_lbl = os.path.join(lbl_out_dir, label_filename)\n                with open(dest_lbl, \"w\") as f:\n                    f.write(\"0 0.5 0.5 1.0 1.0\\n\")\n                count += 1\n    print(f\"Processed {count} images from {input_dir}.\")\n\n# Process training, validation, and test images.\nprocess_images(input_train_dir, train_img_out, train_lbl_out)\nprocess_images(input_valid_dir, valid_img_out, valid_lbl_out)\n\n# For test images, we only need to copy them (no labels needed)\ndef process_test_images(input_dir, img_out_dir):\n    count = 0\n    for root, dirs, files in os.walk(input_dir):\n        for file in files:\n            if file.lower().endswith(('.jpg', '.jpeg', '.png', '.tiff', '.bmp')):\n                src = os.path.join(root, file)\n                img = cv2.imread(src)\n                if img is None:\n                    continue\n                dest_img = os.path.join(img_out_dir, file)\n                shutil.copy(src, dest_img)\n                count += 1\n    print(f\"Processed {count} test images from {input_dir}.\")\n\nprocess_test_images(input_test_dir, test_img_out)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-25T09:57:56.994553Z","iopub.status.idle":"2025-02-25T09:57:56.994892Z","shell.execute_reply":"2025-02-25T09:57:56.994774Z"},"jupyter":{"source_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import cv2\nimport matplotlib.pyplot as plt\nimport random\n\ndef show_image_with_label(img_path, lbl_path):\n    img = cv2.imread(img_path)\n    if img is None:\n        print(\"Image not found:\", img_path)\n        return\n    with open(lbl_path, \"r\") as f:\n        line = f.readline().strip().split()\n    # YOLO format: class x_center y_center width height (normalized)\n    cls, xc, yc, w, h = line\n    h_img, w_img = img.shape[:2]\n    # Denormalize bounding box coordinates\n    xc, yc, w, h = float(xc)*w_img, float(yc)*h_img, float(w)*w_img, float(h)*h_img\n    x1 = int(xc - w/2)\n    y1 = int(yc - h/2)\n    x2 = int(xc + w/2)\n    y2 = int(yc + h/2)\n    cv2.rectangle(img, (x1, y1), (x2, y2), (0,0,255), 2)\n    img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n    plt.figure(figsize=(8,6))\n    plt.imshow(img_rgb)\n    plt.title(f\"{os.path.basename(img_path)} | Label: {line}\")\n    plt.axis('off')\n    plt.show()\n\n# Get a few random training images\ntrain_imgs = os.listdir(train_img_out)\nfor file in random.sample(train_imgs, 3):\n    img_path = os.path.join(train_img_out, file)\n    lbl_path = os.path.join(train_lbl_out, os.path.splitext(file)[0] + \".txt\")\n    if os.path.exists(lbl_path):\n        show_image_with_label(img_path, lbl_path)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-25T09:58:05.422328Z","iopub.execute_input":"2025-02-25T09:58:05.422664Z","iopub.status.idle":"2025-02-25T09:58:06.324505Z","shell.execute_reply.started":"2025-02-25T09:58:05.422637Z","shell.execute_reply":"2025-02-25T09:58:06.323420Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport cv2\nimport shutil\nfrom tqdm import tqdm\n\n# Define input validation folder (from Kaggle dataset) and output folders for validation images/labels.\ninput_valid_dir = \"/kaggle/input/wheat-plant-diseases/data/valid\"\nvalid_img_out = \"/kaggle/working/datasets/GlobalWheat2021/images/valid_flat\"\nvalid_lbl_out = \"/kaggle/working/datasets/GlobalWheat2021/labels/valid_flat\"\n\nos.makedirs(valid_img_out, exist_ok=True)\nos.makedirs(valid_lbl_out, exist_ok=True)\n\n# Since this is a classification dataset, we create a pseudo-detection label for each image.\n# Each image gets a label file with a full-image bounding box: \"0 0.5 0.5 1.0 1.0\"\ndef process_valid_images(input_dir, dest_img_dir, dest_lbl_dir):\n    count = 0\n    for root, dirs, files in os.walk(input_dir):\n        for file in files:\n            if file.lower().endswith(('.jpg', '.jpeg', '.png', '.tiff', '.bmp')):\n                src_img = os.path.join(root, file)\n                # Attempt to read image to skip corrupt ones\n                img = cv2.imread(src_img)\n                if img is None:\n                    continue\n                # Copy the image to the flat destination\n                dest_img = os.path.join(dest_img_dir, file)\n                shutil.copy(src_img, dest_img)\n                # Write label file: a full-image bounding box for class 0.\n                label_filename = os.path.splitext(file)[0] + \".txt\"\n                dest_lbl = os.path.join(dest_lbl_dir, label_filename)\n                with open(dest_lbl, \"w\") as f:\n                    f.write(\"0 0.5 0.5 1.0 1.0\\n\")\n                count += 1\n    print(f\"Processed {count} validation images.\")\n\nprocess_valid_images(input_valid_dir, valid_img_out, valid_lbl_out)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-25T09:58:14.587193Z","iopub.execute_input":"2025-02-25T09:58:14.587551Z","iopub.status.idle":"2025-02-25T09:58:19.561839Z","shell.execute_reply.started":"2025-02-25T09:58:14.587515Z","shell.execute_reply":"2025-02-25T09:58:19.561098Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport cv2\nimport matplotlib.pyplot as plt\nimport random\n\n# Define directories for validation images and labels\nvalid_img_dir = \"/kaggle/working/datasets/GlobalWheat2021/images/valid_flat\"\nvalid_lbl_dir = \"/kaggle/working/datasets/GlobalWheat2021/labels/valid_flat\"\n\ndef show_valid_image_with_label(image_file):\n    # Construct full paths for the image and its label file\n    img_path = os.path.join(valid_img_dir, image_file)\n    lbl_path = os.path.join(valid_lbl_dir, os.path.splitext(image_file)[0] + \".txt\")\n    \n    # Read the image using OpenCV\n    img = cv2.imread(img_path)\n    if img is None:\n        print(\"Image not found:\", img_path)\n        return\n    h, w = img.shape[:2]\n    \n    # Check if label file exists and then read the annotation(s)\n    if os.path.exists(lbl_path):\n        with open(lbl_path, \"r\") as f:\n            lines = f.readlines()\n        # For each annotation in the label file\n        for line in lines:\n            parts = line.strip().split()\n            if len(parts) != 5:\n                continue\n            # YOLO format: <class> <x_center> <y_center> <width> <height> (all normalized)\n            cls, xc, yc, bw, bh = parts\n            xc, yc, bw, bh = float(xc), float(yc), float(bw), float(bh)\n            # Denormalize bounding box coordinates\n            box_w = bw * w\n            box_h = bh * h\n            x_center = xc * w\n            y_center = yc * h\n            x1 = int(x_center - box_w/2)\n            y1 = int(y_center - box_h/2)\n            x2 = int(x_center + box_w/2)\n            y2 = int(y_center + box_h/2)\n            # Draw the bounding box (red rectangle)\n            cv2.rectangle(img, (x1, y1), (x2, y2), (0, 0, 255), 2)\n    else:\n        print(\"No label file found for\", image_file)\n    \n    # Convert BGR to RGB and display the image using matplotlib\n    img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n    plt.figure(figsize=(8, 6))\n    plt.imshow(img_rgb)\n    plt.axis(\"off\")\n    plt.title(image_file)\n    plt.show()\n\n# Get a list of all validation images\nvalid_images = os.listdir(valid_img_dir)\nif len(valid_images) == 0:\n    print(\"No validation images found in\", valid_img_dir)\nelse:\n    # Display 3 random validation images with their labels\n    for image_file in random.sample(valid_images, min(3, len(valid_images))):\n        show_valid_image_with_label(image_file)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-25T09:58:22.816935Z","iopub.execute_input":"2025-02-25T09:58:22.817292Z","iopub.status.idle":"2025-02-25T09:58:23.959203Z","shell.execute_reply.started":"2025-02-25T09:58:22.817266Z","shell.execute_reply":"2025-02-25T09:58:23.957993Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from ultralytics import YOLO\n\n# If you have a pretrained YOLOv12 checkpoint, use it here.\n# For example, if you have 'yolov12n.pt', you can load it like this:\n# model = YOLO('yolov12n.pt')\n\n# Otherwise, we instantiate the model from the config file (which builds the architecture).\n# This example uses the YOLOv12 configuration we downloaded earlier.\nmodel = YOLO('yolo12.yaml')\n\n# Now train the model using the YAML configuration file that defines the dataset.\n# Adjust epochs, image size, and batch size as needed.\nmodel.train(data='/kaggle/working/GlobalWheat2021.yaml', epochs=100, imgsz=640, batch=16)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-25T09:58:31.899511Z","iopub.execute_input":"2025-02-25T09:58:31.899834Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.save('trained_100_yolov12.pt')","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nfrom ultralytics import YOLO\nimport cv2\nimport matplotlib.pyplot as plt\n\n# Define the test images directory\ntest_img_dir = '/kaggle/input/wheat-plant-diseases/data/test'\ntest_images = os.listdir(test_img_dir)\n\nif len(test_images) == 0:\n    print(\"No test images found in:\", test_img_dir)\nelse:\n    # Loop through a few test images (e.g., first 5 images)\n    for img_file in test_images[:5]:\n        img_path = os.path.join(test_img_dir, img_file)\n        # Run inference on the image\n        results = model(img_path)\n        # results is a list; iterate and call .show() on each result object\n        for result in results:\n            result.show()  # This displays the image with predictions inline\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-25T09:57:57.002001Z","iopub.status.idle":"2025-02-25T09:57:57.002385Z","shell.execute_reply":"2025-02-25T09:57:57.002228Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}