unionpoint's picture
Upload folder using huggingface_hub
5d2fa0b verified
Raw
History Blame Contribute Delete
5.25 kB
import argparse
import io
import json
from pathlib import Path
import numpy as np
import torch
import torchvision.transforms.v2 as T
from PIL import Image
from sklearn.metrics import accuracy_score, average_precision_score
from dataset import get_transforms
def get_tta_transforms(image_size):
return [
T.Compose(
[
T.Resize((image_size, image_size), antialias=True),
T.ToImage(),
T.ToDtype(torch.float32, scale=True),
T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
]
),
T.Compose(
[
T.Resize((image_size, image_size), antialias=True),
T.RandomHorizontalFlip(p=1.0),
T.ToImage(),
T.ToDtype(torch.float32, scale=True),
T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
]
),
T.Compose(
[
T.Resize(int(image_size * 1.1), antialias=True),
T.CenterCrop(image_size),
T.ToImage(),
T.ToDtype(torch.float32, scale=True),
T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
]
),
]
def evaluate(model, val_loader, device=None, use_tta=False, image_size=384):
if device is None:
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = model.to(device)
model.eval()
if use_tta:
tta_transforms = get_tta_transforms(image_size)
all_probs = []
all_labels = []
with torch.inference_mode():
for images, labels in val_loader:
images = images.to(device)
labels = labels.to(device)
if use_tta:
tta_batches = []
for transform in tta_transforms:
augmented = torch.stack([transform(img.cpu()) for img in images])
tta_batches.append(augmented)
tta_batches = torch.stack(tta_batches).to(device)
outputs = []
for tta_batch in tta_batches:
out = model(tta_batch) # [batch, num_classes]
outputs.append(out)
outputs = torch.stack(outputs).mean(dim=0)
else:
outputs = model(images)
probs = torch.softmax(outputs, dim=1)
all_probs.append(probs.cpu())
all_labels.append(labels.cpu())
all_probs = torch.cat(all_probs).numpy()
all_labels = torch.cat(all_labels).numpy()
preds = np.argmax(all_probs, axis=1)
acc = accuracy_score(all_labels, preds)
num_classes = all_probs.shape[1]
y_true_bin = np.zeros((len(all_labels), num_classes))
y_true_bin[np.arange(len(all_labels)), all_labels] = 1
per_class_ap = []
for i in range(num_classes):
if y_true_bin[:, i].sum() > 0:
ap = average_precision_score(y_true_bin[:, i], all_probs[:, i])
per_class_ap.append(ap)
mAP = np.mean(per_class_ap)
return acc, mAP, all_probs, all_labels
def predict_disease(
model, image, idx_to_disease, image_size=384, use_tta=False, device=None
):
if device is None:
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = model.to(device)
model.eval()
if use_tta:
transforms = get_tta_transforms(image_size)
tensors = [transform(image).unsqueeze(0) for transform in transforms]
batch = torch.cat(tensors, dim=0).to(device)
with torch.inference_mode():
outputs = model(batch)
output = outputs.mean(dim=0, keepdim=True)
else:
transform = get_transforms(image_size, is_train=False)
tensor = transform(image).unsqueeze(0).to(device)
with torch.inference_mode():
output = model(tensor)
probs = output.softmax(dim=1)
disease_name = idx_to_disease[probs.argmax(dim=1).item()]
return disease_name
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Run inference on a plant disease image"
)
parser.add_argument("--image_path", type=str, help="Path to input image")
parser.add_argument(
"--image_size", type=str, default=384, help="Size of input image"
)
parser.add_argument(
"--checkpoint", type=str, default=None, help="Path to checkpoint "
)
parser.add_argument("--tta", action="store_true", help="Use test time augmentation")
args = parser.parse_args()
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = torch.jit.load(args.checkpoint).to(device)
model.eval()
print(args.tta)
# load label map
data_dir = Path("data")
label_map_path = data_dir / "label_map.json"
with open(label_map_path) as f:
label_map = json.load(f)
idx_to_disease = {int(v): k for k, v in label_map.items()}
image = Image.open(args.image_path).convert("RGB")
result = predict_disease(
model,
image,
image_size=args.image_size,
idx_to_disease=idx_to_disease,
use_tta=args.tta,
)
print(f"Disease: {result}")