{ "cells": [ { "cell_type": "code", "execution_count": 2, "id": "83194846", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "==================================================\n", "Testing Complete Preprocessing Pipeline\n", "==================================================\n", "โœ… BackgroundRemover imported\n", "โœ… EdgeDetector imported\n", "\n", "๐Ÿ”„ Initializing portable BackgroundRemover...\n", "โœ… U2Net source already present\n", "โœ… BackgroundRemover initialized with U2Net model\n", "โœ… BackgroundRemover initialized\n", "\n", "๐Ÿ”„ Processing image: C:\\Users\\HP\\NitroSense-AI\\static\\uploads\\2888723a-fd6f-4471-b7e5-692727bd5692_668bc6dbe4b48.jpg\n", "๐Ÿ“ Image resized to 800x434 for processing\n", "\n", "๐Ÿ”„ Step 1: Background removal...\n", " โœ… Background removal complete\n", " Background removed shape: (224, 224, 3)\n", " Mask shape: (224, 224)\n", "\n", "๐Ÿ”„ Step 2: Edge detection...\n", " โœ… Edge detection complete\n", " Edge detected shape: (224, 224, 3)\n", "\n", "๐Ÿ”„ Step 3: Final preprocessing...\n", " โœ… Preprocessing complete - shape: (224, 224, 3)\n", " Final image range: [0.00, 1.00]\n", " Final image dtype: float32\n", "\n", "๐Ÿ’พ Saving results to verify...\n", " โœ… Images saved to: C:\\Users\\HP\\NitroSense-AI\\test_output\n", " Files saved:\n", " - 1_original.jpg\n", " - 2_mask.jpg (if available)\n", " - 3_background_removed.jpg\n", " - 3_edge_detected.jpg\n", " - 4_final.jpg\n", "\n", "๐Ÿงน Cleaning up...\n", "\n", "==================================================\n", "โœ… Pipeline test successful!\n", "==================================================\n", "โœ… No kernel crash!\n", "โœ… Check output images in: C:\\Users\\HP\\NitroSense-AI\\test_output\n", "\n", "โœ… Saved ImagePreprocessor to C:\\Users\\HP\\NitroSense-AI\\utils\\preprocessing.py\n", "\n", "==================================================\n", "Verifying saved preprocessor\n", "==================================================\n", "โœ… Preprocessor verification successful!\n", " Output shape: (224, 224, 3)\n", " Output dtype: float32\n", " Output range: [0.00, 0.00]\n", "\n", "==================================================\n", "๐ŸŽ‰ Preprocessing pipeline setup complete!\n", "==================================================\n", "\n", "๐Ÿ“ NOTE: Images were saved to 'test_output' folder instead of displaying\n", " This prevents kernel death from matplotlib rendering\n" ] } ], "source": [ "# %% [markdown]\n", "# # Step 4: Create Complete Preprocessing Pipeline\n", "# ## Memory-Optimized Version (No Display to Prevent Kernel Death)\n", "\n", "# %%\n", "import cv2\n", "import numpy as np\n", "from PIL import Image\n", "import matplotlib.pyplot as plt\n", "import os\n", "import gc\n", "import sys\n", "import warnings\n", "warnings.filterwarnings('ignore')\n", "\n", "# %%\n", "# Memory optimization settings\n", "import torch\n", "torch.set_num_threads(1)\n", "os.environ[\"OMP_NUM_THREADS\"] = \"1\"\n", "os.environ[\"MKL_NUM_THREADS\"] = \"1\"\n", "\n", "# %%\n", "class ImagePreprocessor:\n", " def __init__(self, target_size=(224, 224)): # DenseNet121 expects 224x224\n", " self.target_size = target_size\n", " \n", " def preprocess_for_model(self, image):\n", " \"\"\"\n", " Final preprocessing for model input\n", " \"\"\"\n", " if isinstance(image, Image.Image):\n", " image = np.array(image)\n", " elif isinstance(image, torch.Tensor):\n", " image = image.cpu().numpy()\n", " \n", " # Ensure image is uint8 for resize\n", " if image.dtype != np.uint8:\n", " if image.max() <= 1.0:\n", " image = (image * 255).astype(np.uint8)\n", " else:\n", " image = image.astype(np.uint8)\n", " \n", " # Resize\n", " image = cv2.resize(image, self.target_size)\n", " \n", " # Normalize to [0,1]\n", " image = image.astype(np.float32) / 255.0\n", " \n", " return image\n", " \n", " def combine_with_features(self, image, fertilizer_amount, days):\n", " \"\"\"\n", " Combine image with numerical features\n", " \"\"\"\n", " features = np.array([fertilizer_amount, days])\n", " return image, features\n", "\n", "# %%\n", "# Add path to utils\n", "utils_path = os.path.join(os.getcwd(), 'utils')\n", "if utils_path not in sys.path:\n", " sys.path.append(utils_path)\n", "\n", "# %%\n", "# Helper function to get a test image from the project\n", "def get_test_image():\n", " \"\"\"Get the first image from static/uploads folder or create a dummy image\"\"\"\n", " # First, check static/uploads folder for existing images\n", " upload_folder = os.path.join(os.getcwd(), 'static', 'uploads')\n", " if os.path.exists(upload_folder):\n", " images = [f for f in os.listdir(upload_folder) \n", " if f.lower().endswith(('.png', '.jpg', '.jpeg', '.gif'))]\n", " if images:\n", " return os.path.join(upload_folder, images[0])\n", " \n", " # If no images found, check if there's a sample image in test_output\n", " test_output = os.path.join(os.getcwd(), 'test_output')\n", " if os.path.exists(test_output):\n", " images = [f for f in os.listdir(test_output) \n", " if f.lower().endswith(('.png', '.jpg', '.jpeg'))]\n", " if images:\n", " return os.path.join(test_output, images[0])\n", " \n", " # If no images found, return None (will use dummy image)\n", " return None\n", "\n", "# %%\n", "# Test complete pipeline with proper memory management (NO DISPLAY)\n", "print(\"=\"*50)\n", "print(\"Testing Complete Preprocessing Pipeline\")\n", "print(\"=\"*50)\n", "\n", "try:\n", " # Import with error handling\n", " try:\n", " from utils.background_removal import BackgroundRemover\n", " print(\"โœ… BackgroundRemover imported\")\n", " except Exception as e:\n", " print(f\"โŒ Failed to import BackgroundRemover: {e}\")\n", " BackgroundRemover = None\n", " \n", " try:\n", " from utils.edge_detection import EdgeDetector\n", " print(\"โœ… EdgeDetector imported\")\n", " except Exception as e:\n", " print(f\"โŒ Failed to import EdgeDetector: {e}\")\n", " EdgeDetector = None\n", " \n", " # Initialize components - Using portable BackgroundRemover\n", " current_dir = os.getcwd()\n", " \n", " # Initialize background remover (portable version - no path needed)\n", " bg_remover = None\n", " if BackgroundRemover is not None:\n", " try:\n", " # The portable BackgroundRemover finds weights automatically\n", " print(f\"\\n๐Ÿ”„ Initializing portable BackgroundRemover...\")\n", " bg_remover = BackgroundRemover() # No path needed - auto-finds in u2net/weights/\n", " print(\"โœ… BackgroundRemover initialized\")\n", " except Exception as e:\n", " print(f\"โš ๏ธ Could not initialize BackgroundRemover: {e}\")\n", " print(\" Will use fallback mode\")\n", " bg_remover = None\n", " else:\n", " print(\"โš ๏ธ Skipping U2Net initialization - will use fallback\")\n", " \n", " edge_detector = EdgeDetector() if EdgeDetector is not None else None\n", " preprocessor = ImagePreprocessor(target_size=(224, 224))\n", " \n", " # Get test image from project folders\n", " test_image_path = get_test_image()\n", " \n", " if test_image_path and os.path.exists(test_image_path):\n", " print(f\"\\n๐Ÿ”„ Processing image: {test_image_path}\")\n", " \n", " # Read image and immediately resize to smaller size\n", " image = cv2.imread(test_image_path)\n", " \n", " if image is None:\n", " print(\"โŒ Could not read image, creating dummy image for testing...\")\n", " # Create a dummy image for testing\n", " image = np.zeros((800, 800, 3), dtype=np.uint8)\n", " image[:, :] = [100, 150, 200] # Light blue background\n", " # Draw a green square in the center (simulating leaf)\n", " cv2.rectangle(image, (200, 200), (600, 600), (0, 255, 0), -1)\n", " print(\" Using dummy image for testing\")\n", " else:\n", " # Resize image to reasonable size before any processing\n", " height, width = image.shape[:2]\n", " if height > 800 or width > 800:\n", " scale = 800 / max(height, width)\n", " new_width = int(width * scale)\n", " new_height = int(height * scale)\n", " image = cv2.resize(image, (new_width, new_height))\n", " print(f\"๐Ÿ“ Image resized to {new_width}x{new_height} for processing\")\n", " \n", " image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n", " \n", " # Step 1: Background removal (with memory optimization)\n", " print(\"\\n๐Ÿ”„ Step 1: Background removal...\")\n", " if bg_remover is not None:\n", " try:\n", " # Using the portable background remover with memory optimization\n", " bg_removed, mask = bg_remover.remove_background(\n", " image_rgb, \n", " target_size=(224, 224), # Match model input size\n", " max_size=800 # Memory optimization\n", " )\n", " print(\" โœ… Background removal complete\")\n", " print(f\" Background removed shape: {bg_removed.shape}\")\n", " if mask is not None:\n", " print(f\" Mask shape: {mask.shape}\")\n", " except Exception as e:\n", " print(f\" โš ๏ธ Background removal failed: {e}\")\n", " # Fallback: just resize\n", " bg_removed = cv2.resize(image_rgb, (224, 224))\n", " mask = None\n", " else:\n", " print(\" โš ๏ธ Using fallback (no background removal)\")\n", " bg_removed = cv2.resize(image_rgb, (224, 224))\n", " mask = None\n", " \n", " # Force garbage collection\n", " gc.collect()\n", " \n", " # Step 2: Edge detection\n", " print(\"\\n๐Ÿ”„ Step 2: Edge detection...\")\n", " if edge_detector is not None and bg_removed is not None:\n", " try:\n", " edge_image, edges = edge_detector.detect_edges(bg_removed)\n", " print(\" โœ… Edge detection complete\")\n", " print(f\" Edge detected shape: {edge_image.shape}\")\n", " except Exception as e:\n", " print(f\" โš ๏ธ Edge detection failed: {e}\")\n", " edge_image = bg_removed\n", " edges = None\n", " else:\n", " print(\" โš ๏ธ Using fallback (no edge detection)\")\n", " edge_image = bg_removed\n", " \n", " # Force garbage collection\n", " gc.collect()\n", " \n", " # Step 3: Final preprocessing\n", " print(\"\\n๐Ÿ”„ Step 3: Final preprocessing...\")\n", " processed = preprocessor.preprocess_for_model(edge_image)\n", " print(f\" โœ… Preprocessing complete - shape: {processed.shape}\")\n", " print(f\" Final image range: [{processed.min():.2f}, {processed.max():.2f}]\")\n", " print(f\" Final image dtype: {processed.dtype}\")\n", " \n", " # Save images instead of displaying (to verify results)\n", " print(\"\\n๐Ÿ’พ Saving results to verify...\")\n", " \n", " # Create output directory\n", " output_dir = os.path.join(current_dir, 'test_output')\n", " os.makedirs(output_dir, exist_ok=True)\n", " \n", " # Save intermediate images\n", " cv2.imwrite(os.path.join(output_dir, '1_original.jpg'), \n", " cv2.cvtColor(cv2.resize(image_rgb, (224, 224)), cv2.COLOR_RGB2BGR))\n", " \n", " if mask is not None:\n", " cv2.imwrite(os.path.join(output_dir, '2_mask.jpg'), mask)\n", " \n", " cv2.imwrite(os.path.join(output_dir, '3_background_removed.jpg'), \n", " cv2.cvtColor(cv2.resize(bg_removed, (224, 224)), cv2.COLOR_RGB2BGR))\n", " \n", " # Save edge detected image\n", " cv2.imwrite(os.path.join(output_dir, '3_edge_detected.jpg'),\n", " cv2.cvtColor(cv2.resize(edge_image, (224, 224)), cv2.COLOR_RGB2BGR))\n", " \n", " # Save final processed image (denormalize for saving)\n", " save_image = (processed * 255).astype(np.uint8)\n", " cv2.imwrite(os.path.join(output_dir, '4_final.jpg'), \n", " cv2.cvtColor(save_image, cv2.COLOR_RGB2BGR))\n", " \n", " print(f\" โœ… Images saved to: {output_dir}\")\n", " print(f\" Files saved:\")\n", " print(f\" - 1_original.jpg\")\n", " print(f\" - 2_mask.jpg (if available)\")\n", " print(f\" - 3_background_removed.jpg\")\n", " print(f\" - 3_edge_detected.jpg\")\n", " print(f\" - 4_final.jpg\")\n", " \n", " # Clean up\n", " print(\"\\n๐Ÿงน Cleaning up...\")\n", " del bg_remover, edge_detector, preprocessor\n", " del image, image_rgb, bg_removed, edge_image, processed\n", " if 'mask' in locals():\n", " del mask\n", " if 'edges' in locals():\n", " del edges\n", " gc.collect()\n", " \n", " print(\"\\n\" + \"=\"*50)\n", " print(\"โœ… Pipeline test successful!\")\n", " print(\"=\"*50)\n", " print(\"โœ… No kernel crash!\")\n", " print(f\"โœ… Check output images in: {output_dir}\")\n", " \n", " else:\n", " print(\"\\nโš ๏ธ No test image found in static/uploads/\")\n", " print(\" Creating dummy image for pipeline test...\")\n", " \n", " # Create a dummy image for testing\n", " dummy_image = np.zeros((800, 800, 3), dtype=np.uint8)\n", " dummy_image[:, :] = [100, 150, 200] # Light blue background\n", " # Draw a green square in the center (simulating leaf)\n", " cv2.rectangle(dummy_image, (200, 200), (600, 600), (0, 255, 0), -1)\n", " # Add some texture\n", " cv2.rectangle(dummy_image, (250, 250), (550, 550), (0, 200, 0), -1)\n", " print(\" Created dummy image with green square for testing\")\n", " \n", " image_rgb = cv2.cvtColor(dummy_image, cv2.COLOR_BGR2RGB)\n", " \n", " # Process dummy image\n", " print(\"\\n๐Ÿ”„ Step 1: Background removal...\")\n", " if bg_remover is not None:\n", " try:\n", " bg_removed, mask = bg_remover.remove_background(\n", " image_rgb, \n", " target_size=(224, 224),\n", " max_size=800\n", " )\n", " print(\" โœ… Background removal complete\")\n", " except Exception as e:\n", " print(f\" โš ๏ธ Background removal error: {e}\")\n", " bg_removed = cv2.resize(image_rgb, (224, 224))\n", " else:\n", " bg_removed = cv2.resize(image_rgb, (224, 224))\n", " \n", " gc.collect()\n", " \n", " print(\"\\n๐Ÿ”„ Step 2: Edge detection...\")\n", " if edge_detector is not None:\n", " try:\n", " edge_image, edges = edge_detector.detect_edges(bg_removed)\n", " print(\" โœ… Edge detection complete\")\n", " except Exception as e:\n", " print(f\" โš ๏ธ Edge detection error: {e}\")\n", " edge_image = bg_removed\n", " else:\n", " edge_image = bg_removed\n", " \n", " gc.collect()\n", " \n", " print(\"\\n๐Ÿ”„ Step 3: Final preprocessing...\")\n", " processed = preprocessor.preprocess_for_model(edge_image)\n", " print(f\" โœ… Preprocessing complete - shape: {processed.shape}\")\n", " print(f\" Final image range: [{processed.min():.2f}, {processed.max():.2f}]\")\n", " \n", " print(\"\\nโœ… Dummy image pipeline test successful!\")\n", " \n", "except Exception as e:\n", " print(f\"โŒ Pipeline test failed: {e}\")\n", " import traceback\n", " traceback.print_exc()\n", "\n", "# %%\n", "# Save preprocessor to file with proper encoding\n", "preprocessor_code = '''\n", "import cv2\n", "import numpy as np\n", "from PIL import Image\n", "\n", "class ImagePreprocessor:\n", " def __init__(self, target_size=(224, 224)):\n", " self.target_size = target_size\n", " \n", " def preprocess_for_model(self, image):\n", " \"\"\"\n", " Final preprocessing for model input\n", " \"\"\"\n", " if isinstance(image, Image.Image):\n", " image = np.array(image)\n", " elif hasattr(image, 'cpu'): # Handle torch tensors\n", " image = image.cpu().numpy()\n", " \n", " # Ensure correct dtype\n", " if image.dtype != np.uint8:\n", " if image.max() <= 1.0:\n", " image = (image * 255).astype(np.uint8)\n", " else:\n", " image = image.astype(np.uint8)\n", " \n", " # Resize\n", " image = cv2.resize(image, self.target_size)\n", " \n", " # Normalize to [0,1]\n", " image = image.astype(np.float32) / 255.0\n", " \n", " return image\n", " \n", " def combine_with_features(self, image, fertilizer_amount, days):\n", " \"\"\"\n", " Combine image with numerical features\n", " \"\"\"\n", " features = np.array([fertilizer_amount, days])\n", " return image, features\n", "'''\n", "\n", "# Ensure utils directory exists\n", "utils_dir = os.path.join(os.getcwd(), 'utils')\n", "os.makedirs(utils_dir, exist_ok=True)\n", "\n", "# Save with utf-8 encoding\n", "with open(os.path.join(utils_dir, 'preprocessing.py'), 'w', encoding='utf-8') as f:\n", " f.write(preprocessor_code)\n", "print(f\"\\nโœ… Saved ImagePreprocessor to {os.path.join(utils_dir, 'preprocessing.py')}\")\n", "\n", "# %%\n", "# Quick verification (no display)\n", "print(\"\\n\" + \"=\"*50)\n", "print(\"Verifying saved preprocessor\")\n", "print(\"=\"*50)\n", "\n", "try:\n", " # Import the saved class\n", " sys.path.append(utils_dir)\n", " from preprocessing import ImagePreprocessor\n", " \n", " # Test\n", " test_preprocessor = ImagePreprocessor()\n", " dummy_image = np.zeros((100, 100, 3), dtype=np.uint8)\n", " result = test_preprocessor.preprocess_for_model(dummy_image)\n", " \n", " print(f\"โœ… Preprocessor verification successful!\")\n", " print(f\" Output shape: {result.shape}\")\n", " print(f\" Output dtype: {result.dtype}\")\n", " print(f\" Output range: [{result.min():.2f}, {result.max():.2f}]\")\n", " \n", "except Exception as e:\n", " print(f\"โŒ Verification failed: {e}\")\n", "\n", "print(\"\\n\" + \"=\"*50)\n", "print(\"๐ŸŽ‰ Preprocessing pipeline setup complete!\")\n", "print(\"=\"*50)\n", "print(\"\\n๐Ÿ“ NOTE: Images were saved to 'test_output' folder instead of displaying\")\n", "print(\" This prevents kernel death from matplotlib rendering\")" ] }, { "cell_type": "code", "execution_count": null, "id": "203a2186", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.11.5" } }, "nbformat": 4, "nbformat_minor": 5 }