| |
| """ |
| Complete the final batch of ripeness labeling using conservative color analysis. |
| This script processes the remaining 46 images with higher confidence thresholds. |
| """ |
|
|
| import os |
| import json |
| import shutil |
| from pathlib import Path |
| from datetime import datetime |
| import numpy as np |
| from PIL import Image |
| import cv2 |
|
|
| def analyze_ripeness_conservative(image_path, confidence_threshold=0.8): |
| """ |
| Conservative ripeness analysis with higher confidence thresholds. |
| """ |
| try: |
| |
| img = cv2.imread(str(image_path)) |
| if img is None: |
| return None, 0.0 |
| |
| |
| hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) |
| |
| |
| |
| red_lower1 = np.array([0, 50, 50]) |
| red_upper1 = np.array([10, 255, 255]) |
| red_lower2 = np.array([170, 50, 50]) |
| red_upper2 = np.array([180, 255, 255]) |
| |
| |
| green_lower = np.array([40, 40, 40]) |
| green_upper = np.array([80, 255, 255]) |
| |
| |
| yellow_lower = np.array([15, 50, 50]) |
| yellow_upper = np.array([35, 255, 255]) |
| |
| |
| red_mask1 = cv2.inRange(hsv, red_lower1, red_upper1) |
| red_mask2 = cv2.inRange(hsv, red_lower2, red_upper2) |
| red_mask = cv2.bitwise_or(red_mask1, red_mask2) |
| |
| green_mask = cv2.inRange(hsv, green_lower, green_upper) |
| yellow_mask = cv2.inRange(hsv, yellow_lower, yellow_upper) |
| |
| |
| total_pixels = img.shape[0] * img.shape[1] |
| red_percentage = np.sum(red_mask > 0) / total_pixels |
| green_percentage = np.sum(green_mask > 0) / total_pixels |
| yellow_percentage = np.sum(yellow_mask > 0) / total_pixels |
| |
| |
| if red_percentage > 0.35 and red_percentage > green_percentage and red_percentage > yellow_percentage: |
| return "ripe", red_percentage |
| elif green_percentage > 0.25 and green_percentage > red_percentage and green_percentage > yellow_percentage: |
| return "unripe", green_percentage |
| elif yellow_percentage > 0.20 and yellow_percentage > red_percentage and yellow_percentage > green_percentage: |
| return "overripe", yellow_percentage |
| else: |
| |
| max_percentage = max(red_percentage, green_percentage, yellow_percentage) |
| if max_percentage == red_percentage: |
| return "ripe", red_percentage |
| elif max_percentage == green_percentage: |
| return "unripe", green_percentage |
| else: |
| return "overripe", yellow_percentage |
| |
| except Exception as e: |
| print(f"Error analyzing {image_path}: {e}") |
| return None, 0.0 |
|
|
| def main(): |
| """Complete the final batch of labeling.""" |
| |
| |
| to_label_dir = Path("model/ripeness_manual_dataset/to_label") |
| unripe_dir = Path("model/ripeness_manual_dataset/unripe") |
| ripe_dir = Path("model/ripeness_manual_dataset/ripe") |
| overripe_dir = Path("model/ripeness_manual_dataset/overripe") |
| |
| |
| remaining_files = list(to_label_dir.glob("*.jpg")) |
| |
| if not remaining_files: |
| print("No images remaining to label!") |
| return |
| |
| print(f"=== FINAL BATCH LABELING ===") |
| print(f"Processing {len(remaining_files)} remaining images with conservative analysis...") |
| |
| results = { |
| "timestamp": datetime.now().isoformat(), |
| "total_processed": len(remaining_files), |
| "unripe": 0, |
| "ripe": 0, |
| "overripe": 0, |
| "unknown": 0, |
| "images": [] |
| } |
| |
| for i, image_path in enumerate(remaining_files, 1): |
| print(f"Processing {i}/{len(remaining_files)}: {image_path.name}") |
| |
| |
| label, confidence = analyze_ripeness_conservative(image_path, confidence_threshold=0.8) |
| |
| if label: |
| |
| if label == "unripe": |
| dest = unripe_dir / image_path.name |
| results["unripe"] += 1 |
| elif label == "ripe": |
| dest = ripe_dir / image_path.name |
| results["ripe"] += 1 |
| elif label == "overripe": |
| dest = overripe_dir / image_path.name |
| results["overripe"] += 1 |
| |
| try: |
| shutil.move(str(image_path), str(dest)) |
| print(f" ✅ {label} (confidence: {confidence:.2f})") |
| results["images"].append({ |
| "filename": image_path.name, |
| "label": label, |
| "confidence": confidence |
| }) |
| except Exception as e: |
| print(f" ❌ Error moving file: {e}") |
| results["unknown"] += 1 |
| else: |
| print(f" ⚠️ Analysis failed") |
| results["unknown"] += 1 |
| |
| |
| results_file = f"model/ripeness_manual_dataset/final_labeling_results_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json" |
| with open(results_file, 'w') as f: |
| json.dump(results, f, indent=2) |
| |
| |
| print(f"\n=== FINAL LABELING COMPLETE ===") |
| print(f"unripe: {results['unripe']} images") |
| print(f"ripe: {results['ripe']} images") |
| print(f"overripe: {results['overripe']} images") |
| print(f"unknown: {results['unknown']} images") |
| print(f"Total processed: {results['total_processed']} images") |
| |
| |
| total_unripe = len(list(unripe_dir.glob("*.jpg"))) |
| total_ripe = len(list(ripe_dir.glob("*.jpg"))) |
| total_overripe = len(list(overripe_dir.glob("*.jpg"))) |
| remaining = len(list(to_label_dir.glob("*.jpg"))) |
| total_dataset = total_unripe + total_ripe + total_overripe + remaining |
| |
| completion_percentage = (total_dataset - remaining) / total_dataset * 100 |
| |
| print(f"\n=== FINAL DATASET STATUS ===") |
| print(f"unripe: {total_unripe} images") |
| print(f"ripe: {total_ripe} images") |
| print(f"overripe: {total_overripe} images") |
| print(f"to_label: {remaining} images") |
| print(f"TOTAL: {total_dataset} images") |
| print(f"Completion: {completion_percentage:.1f}%") |
| |
| if remaining == 0: |
| print(f"\n🎉 DATASET LABELING 100% COMPLETE! 🎉") |
| print(f"Total labeled images: {total_dataset}") |
| else: |
| print(f"\n⚠️ {remaining} images still need manual review") |
| |
| print(f"Results saved to: {results_file}") |
|
|
| if __name__ == "__main__": |
| main() |