Spaces:
Running
Running
File size: 5,821 Bytes
97e4a2e 4ebd4a2 e9b5fbf 97e4a2e 0ab5ab1 97e4a2e d758068 97e4a2e 0ab5ab1 97e4a2e d758068 97e4a2e d758068 97e4a2e d758068 97e4a2e d758068 97e4a2e d758068 dba02e5 d758068 97e4a2e d758068 97e4a2e d758068 97e4a2e d758068 97e4a2e d758068 97e4a2e d758068 97e4a2e d758068 0470a8b d758068 97e4a2e f30a193 97e4a2e d9dd6b6 97e4a2e f1a90ed a30b880 5af53ce 97e4a2e a30b880 97e4a2e c99c78a ee0cbb3 f517fa1 177a460 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
import timm
import transformers
from torch import nn
import numpy as np
import gradio as gr
import PIL
from huggingface_hub import from_pretrained_fastai
# Instantiate classification model
from fastai.vision.all import *
model_multi = load_learner('vit_tiny_patch16.pkl')
def binary_label(path):
return 'No-anomaly' if (parent_label(path) == 'No-Anomaly') else 'Anomaly'
model_binary = load_learner('vit_tiny_patch16_binary.pkl')
# Instantiate segmentation model
from transformers import SegformerFeatureExtractor, SegformerForSemanticSegmentation
from torchvision.transforms import Grayscale
seg_feature_extractor = SegformerFeatureExtractor.from_pretrained('zklee98/segformer-b1-solarModuleAnomaly-v0.1')
seg_model = SegformerForSemanticSegmentation.from_pretrained('zklee98/segformer-b1-solarModuleAnomaly-v0.1')
def get_seg_overlay(image, seg):
color_seg = np.zeros((seg.shape[0], seg.shape[1], 3), dtype=np.uint8) # height, width, 3
palette = np.array(sidewalk_palette())
for label, color in enumerate(palette):
color_seg[seg == label, :] = color
# Show image + mask
img = np.array(image) * 0.5 + color_seg * 0.5
img = img.astype(np.uint8)
#img = PIL.Image.open(img)
return img
#@title `def sidewalk_palette()`
def sidewalk_palette():
"""Sidewalk palette that maps each class to RGB values."""
return [
[0, 0, 0],
[216, 82, 24],
[255, 255, 0],
[125, 46, 141],
[118, 171, 47],
[161, 19, 46],
[255, 0, 0],
[0, 128, 128],
[190, 190, 0],
[0, 255, 0],
[0, 0, 255],
[170, 0, 255],
[84, 84, 0],
[84, 170, 0],
[84, 255, 0],
[170, 84, 0],
[170, 170, 0],
[170, 255, 0],
[255, 84, 0],
[255, 170, 0],
[255, 255, 0],
[33, 138, 200],
[0, 170, 127],
[0, 255, 127],
[84, 0, 127],
[84, 84, 127],
[84, 170, 127],
[84, 255, 127],
[170, 0, 127],
[170, 84, 127],
[170, 170, 127],
[170, 255, 127],
[255, 0, 127],
[255, 84, 127],
[255, 170, 127],
]
def predict(classification_mode, image):
if (classification_mode == 'Binary Classification'):
model = model_binary
else:
model = model_multi
labels = model.dls.vocab
# Classification model prediction
#image = PILImage.create(image)
pred, pred_idx, probs = model.predict(image)
seg_img = None
percentage_affected = '0%'
if (pred.upper() != 'NO-ANOMALY'):
addChannel = Grayscale(num_output_channels=3)
image = addChannel(image)
inputs = seg_feature_extractor(images=image, return_tensors="pt")
outputs = seg_model(**inputs)
logits = outputs.logits # shape (batch_size, num_labels, height/4, width/4)
# First, rescale logits to original image size
upsampled_logits = nn.functional.interpolate(
logits,
size=image.size[::-1], # (height, width)
mode='bilinear',
align_corners=False)
# Second, apply argmax on the class dimension
pred_seg = upsampled_logits.argmax(dim=1)[0]
seg_img = get_seg_overlay(image, pred_seg)
classified_pixels = np.unique(pred_seg.numpy(), return_counts=True)
pixels_count = dict({classified_pixels[0][0]: classified_pixels[1][0],
classified_pixels[0][1]: classified_pixels[1][1]})
#percentage_affected = round((pixels_count[1]/960)*100, 1)
percentage_affected = round((pixels_count[1]/(pixels_count[0]+pixels_count[1]))*100, 1)
percentage_affected = str(percentage_affected) + '%'
#seg_img = PIL.Image.fromarray(seg_img)
return ({labels[i]: float(probs[i]) for i in range(len(labels))}, seg_img, percentage_affected)
description = """
<center><img src="https://huggingface.co/spaces/zklee98/SolarPanelAnomaly/resolve/main/images/dronePV_picture.jpg" width=270px> </center><br>
<center>This program identifies the type of anomaly found in solar panel using an image classification model and percentage of the affected area using an image segmentation model.</center><br><br><br>
<center> Step 1: Choose classification mode > Step 2: Upload your image > Step 3: Click Submit | Examples available below</center><br>
<center><i><b>(Models are trained on <a href="https://ai4earthscience.github.io/iclr-2020-workshop/papers/ai4earth22.pdf">InfraredSolarModules</a> dataset, and hence expect infrared image as input)</b></i></center>
"""
gr.Interface(fn=predict,
inputs= [gr.Dropdown(choices=['Binary Classification', 'Multiclass Classification'], label='(Step 1) Classification Mode:',
info='Choose to classify between anomaly and no-anomaly (Binary) OR between 12 different types of anomalies (Multi).').style(container=False),
gr.Image(type='pil', label='(Step 2) Input infrared image: ').style(container=False)],
outputs=[gr.outputs.Label(num_top_classes=3, label='Detected:').style(container=False),
gr.Image(type='pil', label=' ').style(height=240, width=144),
gr.Textbox(label='Affected area:').style(container=False)],
title='Solar Panel Anomaly Detector',
description=description,
examples=[['Binary Classification', '4849.jpg'], ['Multiclass Classification', '4849.jpg'],
['Binary Classification', '7016.jpg'], ['Multiclass Classification', 'images/10000.jpg']],
cache_examples= False,
article= '<center>by <a href="https://www.linkedin.com/in/lzk/">Lee Zhe Kaai</a></center>').launch()
print(fastai.__version__) |