CoolFace
Modelpublic

LeafNet75/Leaf-Annotate-v2

sourceHugging Faceapache-2.0updated 10mo agoView on Hugging Face
1likes
Batch_Inference.py126 linesDownload Raw Back to root
1import os2from pathlib import Path3import torch4from PIL import Image5import numpy as np6import cv27import segmentation_models_pytorch as smp8from huggingface_hub import hf_hub_download9from tqdm import tqdm10 11 12HF_USERNAME = "Subh75"13HF_ORGNAME = "LeafNet75"14MODEL_NAME = "Leaf-Annotate-v2"15HF_MODEL_REPO_ID = f"{HF_ORGNAME}/{MODEL_NAME}"16 17# Set to your original image and output folder respectively18INPUT_IMAGE_DIR = "newimgs/images"19OUTPUT_MASK_DIR = "newimgs/masks"20 21DEVICE = "cuda" if torch.cuda.is_available() else "cpu"22IMG_SIZE = 25623CONFIDENCE_THRESHOLD = 0.524 25 26def load_model_from_hub(repo_id: str):27    """Loads the interactive segmentation model from the Hub."""28    print(f"Loading model '{repo_id}' from Hugging Face Hub...")29 30    model = smp.Unet(31        encoder_name="mobilenet_v2",32        encoder_weights=None,33        in_channels=4,  # RGB + Scribble34        classes=1,35    )36 37    model_weights_path = hf_hub_download(repo_id=repo_id, filename="best_model.pth")38    model.load_state_dict(torch.load(model_weights_path, map_location=DEVICE))39    model.to(DEVICE)40    model.eval()41    print("Model loaded successfully.")42    return model43 44 45def predict_scribble(model, pil_image, scribble_mask):46    """Runs inference using a scribble and returns a binary mask."""47    img_resized = np.array(48        pil_image.resize((IMG_SIZE, IMG_SIZE), Image.Resampling.BILINEAR)49    )50    scribble_resized = cv2.resize(51        scribble_mask, (IMG_SIZE, IMG_SIZE), interpolation=cv2.INTER_NEAREST52    )53 54    img_tensor = (55        torch.from_numpy(img_resized.astype(np.float32)).permute(2, 0, 1) / 255.056    )57    scribble_tensor = (58        torch.from_numpy(scribble_resized.astype(np.float32)).unsqueeze(0) / 255.059    )60 61    input_tensor = torch.cat([img_tensor, scribble_tensor], dim=0).unsqueeze(0).to(DEVICE)62 63    with torch.no_grad():64        output = model(input_tensor)65 66    probs = torch.sigmoid(output)67    binary_mask_resized = (probs > CONFIDENCE_THRESHOLD).float().squeeze().cpu().numpy()68 69    final_mask = cv2.resize(70        binary_mask_resized, (pil_image.width, pil_image.height), interpolation=cv2.INTER_NEAREST71    )72    return (final_mask * 255).astype(np.uint8)73 74 75def main():76    """Main function to run batch inference on a folder of images."""77    if not os.path.isdir(INPUT_IMAGE_DIR):78        print(f"Error: Input directory not found at '{INPUT_IMAGE_DIR}'")79        return80 81    os.makedirs(OUTPUT_MASK_DIR, exist_ok=True)82 83    model = load_model_from_hub(HF_MODEL_REPO_ID)84 85    image_files = [86        f for f in os.listdir(INPUT_IMAGE_DIR) if f.lower().endswith((".png", ".jpg", ".jpeg"))87    ]88 89    print(f"\nFound {len(image_files)} images to process.")90 91    for filename in tqdm(image_files, desc="Generating Masks"):92        image_path = os.path.join(INPUT_IMAGE_DIR, filename)93 94        try:95            original_image = Image.open(image_path).convert("RGB")96            h, w = original_image.height, original_image.width97 98            # Create a dummy scribble (center line)99            scribble = np.zeros((h, w), dtype=np.uint8)100            center_x, center_y = w // 2, h // 2101            length = int(min(w, h) * 0.2)102 103            start_point = (center_x - length // 2, center_y)104            end_point = (center_x + length // 2, center_y)105            cv2.line(scribble, start_point, end_point, 255, thickness=25)106 107            # Predict mask108            predicted_mask = predict_scribble(model, original_image, scribble)109 110            mask_image = Image.fromarray(predicted_mask)111 112            # Keep same base name, save as .png in OUTPUT_MASK_DIR113            base_name = Path(filename).stem114            output_path = os.path.join(OUTPUT_MASK_DIR, f"{base_name}.png")115 116            mask_image.save(output_path)117 118        except Exception as e:119            print(f"\n Could not process {filename}. Error: {e}")120 121    print(f"\n Done! Masks saved in '{OUTPUT_MASK_DIR}' with same names as input images.")122 123 124if __name__ == "__main__":125    main()126