Spaces:
Sleeping
Sleeping
| from fastai.learner import load_learner | |
| from fastai.vision.core import PILImage | |
| from fastai.vision.all import DisplayedTransform | |
| from pathlib import Path | |
| import gradio as gr | |
| import PIL | |
| import sys | |
| import os | |
| import albumentations as A | |
| import numpy as np | |
| # Print debug information | |
| print(f"Python version: {sys.version}") | |
| print(f"PIL version: {PIL.__version__}") | |
| print(f"fastai path: {Path(__file__).parent}") | |
| print(f"Current working directory: {os.getcwd()}") | |
| # Create a custom transform class that integrates Albumentations with fastai | |
| class AlbumentationsTransform(DisplayedTransform): | |
| split_idx, order = None, 2 # Apply to both train and validation sets | |
| def __init__(self, train_aug, valid_aug=None): | |
| self.train_aug = train_aug | |
| self.valid_aug = valid_aug or A.Compose([ | |
| A.SmallestMaxSize(max_size=224), | |
| A.CenterCrop(height=224, width=224) | |
| ]) | |
| def before_call(self, b, split_idx): | |
| self.split_idx = split_idx | |
| def encodes(self, img: PILImage): | |
| # Use validation augmentation for inference | |
| aug = self.valid_aug | |
| # Convert to numpy array and ensure it's uint8 before augmentation | |
| img_array = np.array(img).astype(np.uint8) | |
| aug_img = aug(image=img_array)['image'] | |
| # Convert back to PIL Image | |
| return PILImage.create(aug_img) | |
| # Define the albumentations transforms | |
| def get_train_transform(): | |
| return A.Compose([ | |
| A.SmallestMaxSize(max_size=256), | |
| A.RandomCrop(height=224, width=224), | |
| A.HorizontalFlip(p=0.5), | |
| A.RandomBrightnessContrast(p=0.3), | |
| ]) | |
| def get_valid_transform(): | |
| return A.Compose([ | |
| A.SmallestMaxSize(max_size=256), | |
| A.CenterCrop(height=224, width=224), | |
| ]) | |
| try: | |
| learn = load_learner('export.pkl') | |
| print(f"Model loaded successfully: {type(learn)}") | |
| # Define friendly label names | |
| label_mapping = { | |
| 'positive': "Slate", | |
| 'negative': "No Slate" | |
| } | |
| # Get original labels | |
| original_labels = learn.dls.vocab | |
| print(f"Original labels: {original_labels}") | |
| def predict(img): | |
| # Convert to PILImage and apply transforms | |
| img_pil = PILImage.create(img) | |
| # Create transform with both train and valid transforms (will use valid for inference) | |
| transform = AlbumentationsTransform(get_train_transform(), get_valid_transform()) | |
| transformed_img = transform.encodes(img_pil) | |
| # Get prediction | |
| pred, pred_idx, probs = learn.predict(transformed_img) | |
| # Map the original labels to friendly names | |
| return {label_mapping[original_labels[i]]: float(probs[i]) for i in range(len(original_labels))} | |
| # Create a more attractive interface with custom styling | |
| with gr.Blocks(css="footer {visibility: hidden}") as demo: | |
| gr.Markdown("# 🎬 Image Classifier: Slate or No Slate?") | |
| gr.Markdown("Upload an image and let AI tell you whether or not it contains a film slate!") | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| # Remove webcam by setting sources to only 'upload' and 'clipboard' | |
| input_image = gr.Image( | |
| type="pil", | |
| label="Upload Image", | |
| sources=["upload", "clipboard"] | |
| ) | |
| submit_btn = gr.Button("Classify", variant="primary") | |
| with gr.Column(scale=1): | |
| output = gr.Label(num_top_classes=3, label="Predictions") | |
| with gr.Accordion("About", open=False): | |
| gr.Markdown(""" | |
| ## How it works | |
| This app uses a deep learning model trained with fastai to classify images. | |
| ## Tips for best results | |
| - Use clear, well-lit images | |
| - Center the subject in the frame | |
| - Supported categories: """ + ", ".join([label_mapping[label] for label in original_labels])) | |
| # Set up the prediction flow | |
| submit_btn.click( | |
| fn=predict, | |
| inputs=input_image, | |
| outputs=output | |
| ) | |
| # Allow image input to trigger prediction as well | |
| input_image.change( | |
| fn=predict, | |
| inputs=input_image, | |
| outputs=output | |
| ) | |
| # Use all images in the examples folder as examples | |
| examples_dir = Path("examples").resolve() | |
| example_paths = [str(p) for p in examples_dir.glob("*") if p.is_file()] | |
| gr.Examples( | |
| examples=example_paths, | |
| inputs=input_image | |
| ) | |
| allowed_paths = [str(examples_dir)] | |
| # Launch the app, allow access to the entire examples directory for @Gradio | |
| demo.launch(allowed_paths=allowed_paths) # ssr_mode=False | |
| except Exception as e: | |
| print(f"Error occurred: {e}") | |
| import traceback | |
| traceback.print_exc() |