|
|
|
|
|
""" |
|
|
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() |