Spaces:
Runtime error
Runtime error
NORLIE JHON MALAGDAO
commited on
Update app.py
Browse files
app.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
import
|
2 |
import matplotlib.pyplot as plt
|
3 |
import numpy as np
|
4 |
import os
|
@@ -8,34 +8,12 @@ import tensorflow as tf
|
|
8 |
from tensorflow import keras
|
9 |
from tensorflow.keras import layers
|
10 |
from tensorflow.keras.models import Sequential
|
11 |
-
from tensorflow.keras.preprocessing.image import ImageDataGenerator
|
12 |
-
from tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping
|
13 |
-
from tensorflow.keras.optimizers import Adam
|
14 |
-
from tensorflow.keras.layers import Dense, Dropout, Flatten, BatchNormalization
|
15 |
-
from tensorflow.keras.models import Model
|
16 |
-
|
17 |
-
from sklearn.model_selection import train_test_split
|
18 |
-
from sklearn.metrics import classification_report
|
19 |
-
|
20 |
-
import pandas as pd
|
21 |
-
import random
|
22 |
-
import cv2
|
23 |
|
24 |
from PIL import Image
|
25 |
import gdown
|
26 |
import zipfile
|
27 |
-
|
28 |
import pathlib
|
29 |
|
30 |
-
class PyDataset(tf.keras.utils.data_utils.Dataset):
|
31 |
-
def __init__(self, **kwargs):
|
32 |
-
super().__init__(**kwargs)
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
# Ensure that these imports are at the beginning of your script to avoid any NameError issues.
|
37 |
-
|
38 |
-
|
39 |
# Define the Google Drive shareable link
|
40 |
gdrive_url = 'https://drive.google.com/file/d/1HjHYlQyRz5oWt8kehkt1TiOGRRlKFsv8/view?usp=drive_link'
|
41 |
|
@@ -77,349 +55,86 @@ for root, dirs, files in os.walk(extracted_path):
|
|
77 |
|
78 |
# Path to the dataset directory
|
79 |
data_dir = pathlib.Path('extracted_files/Pest_Dataset')
|
80 |
-
data_dir = pathlib.Path(data_dir)
|
81 |
-
|
82 |
-
# Read images and labels into a DataFrame
|
83 |
-
image_paths = list(data_dir.glob('*/*.jpg'))
|
84 |
-
image_labels = [str(path.parent.name) for path in image_paths]
|
85 |
-
image_df = pd.DataFrame({'Filepath': image_paths, 'Label': image_labels})
|
86 |
-
|
87 |
-
# Display distribution of labels
|
88 |
-
label_counts = image_df['Label'].value_counts()
|
89 |
-
plt.figure(figsize=(10, 6))
|
90 |
-
sns.barplot(x=label_counts.index, y=label_counts.values, alpha=0.8, palette='rocket')
|
91 |
-
plt.title('Distribution of Labels in Image Dataset', fontsize=16)
|
92 |
-
plt.xlabel('Label', fontsize=14)
|
93 |
-
plt.ylabel('Count', fontsize=14)
|
94 |
-
plt.xticks(rotation=45)
|
95 |
-
plt.show()
|
96 |
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
# Function to return a random image path from a given directory
|
108 |
-
def random_sample(directory):
|
109 |
-
images = [os.path.join(directory, img) for img in os.listdir(directory) if img.endswith(('.jpg', '.jpeg', '.png'))]
|
110 |
-
return random.choice(images)
|
111 |
-
|
112 |
-
# Function to compute the Error Level Analysis (ELA) of an image
|
113 |
-
def compute_ela_cv(path, quality):
|
114 |
-
temp_filename = 'temp.jpg'
|
115 |
-
orig = cv2.imread(path)
|
116 |
-
cv2.imwrite(temp_filename, orig, [int(cv2.IMWRITE_JPEG_QUALITY), quality])
|
117 |
-
compressed = cv2.imread(temp_filename)
|
118 |
-
ela_image = cv2.absdiff(orig, compressed)
|
119 |
-
ela_image = np.clip(ela_image * 10, 0, 255).astype(np.uint8)
|
120 |
-
return ela_image
|
121 |
-
|
122 |
-
# View random sample from the dataset
|
123 |
-
p = random_sample('extracted_files/Pest_Dataset/beetle')
|
124 |
-
orig = cv2.imread(p)
|
125 |
-
orig = cv2.cvtColor(orig, cv2.COLOR_BGR2RGB) / 255.0
|
126 |
-
init_val = 100
|
127 |
-
columns = 3
|
128 |
-
rows = 3
|
129 |
-
|
130 |
-
fig = plt.figure(figsize=(15, 10))
|
131 |
-
for i in range(1, columns*rows + 1):
|
132 |
-
quality = init_val - (i-1) * 8
|
133 |
-
img = compute_ela_cv(path=p, quality=quality)
|
134 |
-
if i == 1:
|
135 |
-
img = orig.copy()
|
136 |
-
ax = fig.add_subplot(rows, columns, i)
|
137 |
-
ax.title.set_text(f'q: {quality}')
|
138 |
-
plt.imshow(img)
|
139 |
-
plt.show()
|
140 |
-
|
141 |
-
# Read images and labels into a DataFrame
|
142 |
-
image_paths = list(data_dir.glob('*/*.jpg'))
|
143 |
-
image_labels = [str(path.parent.name) for path in image_paths]
|
144 |
-
image_df = pd.DataFrame({'Filepath': [str(path) for path in image_paths], 'Label': image_labels})
|
145 |
-
|
146 |
-
# Separate into train and test data
|
147 |
-
train_df, test_df = train_test_split(image_df, test_size=0.2, shuffle=True, random_state=42)
|
148 |
-
|
149 |
-
train_generator = ImageDataGenerator(
|
150 |
-
preprocessing_function=tf.keras.applications.efficientnet_v2.preprocess_input,
|
151 |
-
validation_split=0.2
|
152 |
)
|
153 |
|
154 |
-
|
155 |
-
|
|
|
|
|
|
|
|
|
|
|
156 |
)
|
157 |
|
158 |
-
|
159 |
-
train_images = train_generator.flow_from_dataframe(
|
160 |
-
dataframe=train_df,
|
161 |
-
x_col='Filepath',
|
162 |
-
y_col='Label',
|
163 |
-
target_size=(224, 224),
|
164 |
-
color_mode='rgb',
|
165 |
-
class_mode='categorical',
|
166 |
-
batch_size=32,
|
167 |
-
shuffle=True,
|
168 |
-
seed=42,
|
169 |
-
subset='training'
|
170 |
-
)
|
171 |
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
seed=42,
|
182 |
-
subset='validation'
|
183 |
-
)
|
184 |
-
|
185 |
-
test_images = test_generator.flow_from_dataframe(
|
186 |
-
dataframe=test_df,
|
187 |
-
x_col='Filepath',
|
188 |
-
y_col='Label',
|
189 |
-
target_size =(224, 224),
|
190 |
-
color_mode='rgb',
|
191 |
-
class_mode='categorical',
|
192 |
-
batch_size=32,
|
193 |
-
shuffle=False
|
194 |
)
|
195 |
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
|
|
|
|
|
|
|
|
|
|
205 |
])
|
206 |
|
|
|
|
|
|
|
207 |
|
208 |
-
|
209 |
-
pretrained_model = tf.keras.applications.efficientnet_v2.EfficientNetV2L(
|
210 |
-
input_shape=(224, 224, 3),
|
211 |
-
include_top=False,
|
212 |
-
weights='imagenet',
|
213 |
-
pooling='max'
|
214 |
-
)
|
215 |
-
|
216 |
-
pretrained_model.trainable = False
|
217 |
-
|
218 |
-
# Create checkpoint callback
|
219 |
-
checkpoint_path = "pests_cats_classification_model_checkpoint.weights.h5"
|
220 |
-
checkpoint_callback = ModelCheckpoint(checkpoint_path,
|
221 |
-
save_weights_only=True,
|
222 |
-
monitor="val_accuracy",
|
223 |
-
save_best_only=True)
|
224 |
-
|
225 |
-
# Setup EarlyStopping callback to stop training if model's val_loss doesn't improve for 5 epochs
|
226 |
-
early_stopping = EarlyStopping(monitor="val_loss", patience=5, restore_best_weights=True)
|
227 |
-
|
228 |
-
inputs = pretrained_model.input
|
229 |
-
x = augment(inputs)
|
230 |
-
|
231 |
-
# Add new classification layers
|
232 |
-
x = Flatten()(pretrained_model.output)
|
233 |
-
x = Dense(256, activation='relu')(x)
|
234 |
-
x = Dropout(0.5)(x)
|
235 |
-
x = BatchNormalization()(x)
|
236 |
-
x = Dense(128, activation='relu')(x)
|
237 |
-
x = Dropout(0.5)(x)
|
238 |
-
|
239 |
-
outputs = Dense(12, activation='softmax')(x)
|
240 |
-
|
241 |
-
model = Model(inputs=inputs, outputs=outputs)
|
242 |
-
|
243 |
-
model.compile(
|
244 |
-
optimizer=Adam(0.00001),
|
245 |
-
loss='categorical_crossentropy',
|
246 |
-
metrics=['accuracy']
|
247 |
-
)
|
248 |
-
|
249 |
-
# Train the model
|
250 |
history = model.fit(
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
validation_steps=len(val_images),
|
255 |
-
epochs=20, # Change epochs to 20
|
256 |
-
callbacks=[
|
257 |
-
early_stopping,
|
258 |
-
checkpoint_callback,
|
259 |
-
]
|
260 |
)
|
261 |
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
print("Test Accuracy: {:.2f}%".format(results[1] * 100))
|
266 |
-
|
267 |
-
accuracy = history.history['accuracy']
|
268 |
-
val_accuracy = history.history['val_accuracy']
|
269 |
-
|
270 |
-
loss = history.history['loss']
|
271 |
-
val_loss = history.history['val_loss']
|
272 |
-
|
273 |
-
epochs = range(len(accuracy))
|
274 |
-
plt.plot(epochs, accuracy, 'b', label='Training accuracy')
|
275 |
-
plt.plot(epochs, val_accuracy, 'r', label='Validation accuracy')
|
276 |
-
|
277 |
-
plt.title('Training and validation accuracy')
|
278 |
-
plt.legend()
|
279 |
-
plt.figure()
|
280 |
-
plt.plot(epochs, loss, 'b', label='Training loss')
|
281 |
-
plt.plot(epochs, val_loss, 'r', label='Validation loss')
|
282 |
-
|
283 |
-
plt.title('Training and validation loss')
|
284 |
-
plt.legend()
|
285 |
-
plt.show()
|
286 |
-
|
287 |
-
# Predict the label of the test_images
|
288 |
-
pred = model.predict(test_images)
|
289 |
-
pred = np.argmax(pred, axis=1)
|
290 |
-
|
291 |
-
# Map the label
|
292 |
-
labels = (train_images.class_indices)
|
293 |
-
labels = dict((v, k) for k, v in labels.items())
|
294 |
-
pred = [labels[k] for k in pred]
|
295 |
-
|
296 |
-
# Display the result
|
297 |
-
print(f'The first 5 predictions: {pred[:5]}')
|
298 |
-
|
299 |
-
# Display 25 random pictures from the dataset with their labels
|
300 |
-
random_index = np.random.randint(0, len(test_df) - 1, 15)
|
301 |
-
fig, axes = plt.subplots(nrows=3, ncols=5, figsize=(25, 15),
|
302 |
-
subplot_kw={'xticks': [], 'yticks': []})
|
303 |
-
|
304 |
-
for i, ax in enumerate(axes.flat):
|
305 |
-
ax.imshow(plt.imread(test_df.Filepath.iloc[random_index[i]]))
|
306 |
-
if test_df.Label.iloc[random_index[i]] == pred[random_index[i]]:
|
307 |
-
color = "green"
|
308 |
-
else:
|
309 |
-
color = "red"
|
310 |
-
ax.set_title(f"True: {test_df.Label.iloc[random_index[i]]}\nPredicted: {pred[random_index[i]]}", color=color)
|
311 |
-
plt.show()
|
312 |
-
plt.tight_layout()
|
313 |
-
|
314 |
-
y_test = list(test_df.Label)
|
315 |
-
print(classification_report(y_test, pred))
|
316 |
-
|
317 |
-
report = classification_report(y_test, pred, output_dict=True)
|
318 |
-
df = pd.DataFrame(report).transpose()
|
319 |
-
df
|
320 |
-
|
321 |
-
# Define function to get image array
|
322 |
-
def get_img_array(img_path, size):
|
323 |
-
img = tf.keras.preprocessing.image.load_img(img_path, target_size=size)
|
324 |
-
array = tf.keras.preprocessing.image.img_to_array(img)
|
325 |
-
array = np.expand_dims(array, axis=0)
|
326 |
-
return array
|
327 |
-
|
328 |
-
# Define function to make Grad-CAM heatmap
|
329 |
-
def make_gradcam_heatmap(img_array, model, last_conv_layer_name, classifier_layer_names=None):
|
330 |
-
grad_model = tf.keras.models.Model(
|
331 |
-
[model.inputs], [model.get_layer(last_conv_layer_name).output, model.output]
|
332 |
-
)
|
333 |
-
|
334 |
-
with tf.GradientTape() as tape:
|
335 |
-
conv_outputs, predictions = grad_model(img_array)
|
336 |
-
loss = predictions[:, np.argmax(predictions[0])]
|
337 |
-
|
338 |
-
output = conv_outputs[0]
|
339 |
-
grads = tape.gradient(loss, conv_outputs)[0]
|
340 |
-
|
341 |
-
gate_f = tf.cast(output > 0, "float32")
|
342 |
-
gate_r = tf.cast(grads > 0, "float32")
|
343 |
-
guided_grads = grads * gate_f * gate_r
|
344 |
-
|
345 |
-
weights = tf.reduce_mean(guided_grads, axis=(0, 1))
|
346 |
-
|
347 |
-
cam = np.zeros(output.shape[0:2], dtype=np.float32)
|
348 |
-
|
349 |
-
for i, w in enumerate(weights):
|
350 |
-
cam += w * output[:, :, i]
|
351 |
-
|
352 |
-
cam = cv2.resize(cam.numpy(), (img_array.shape[2], img_array.shape[1]))
|
353 |
-
cam = np.maximum(cam, 0)
|
354 |
-
heatmap = cam / cam.max()
|
355 |
-
|
356 |
-
return heatmap
|
357 |
-
|
358 |
-
# Define function to save and display Grad-CAM
|
359 |
-
def save_and_display_gradcam(img_path, heatmap, cam_path="cam.jpg", alpha=0.4):
|
360 |
-
img = tf.keras.preprocessing.image.load_img(img_path)
|
361 |
-
img = tf.keras.preprocessing.image.img_to_array(img)
|
362 |
-
|
363 |
-
heatmap = np.uint8(255 * heatmap)
|
364 |
-
|
365 |
-
jet = cm.get_cmap("jet")
|
366 |
-
|
367 |
-
jet_colors = jet(np.arange(256))[:, :3]
|
368 |
-
jet_heatmap = jet_colors[heatmap]
|
369 |
-
|
370 |
-
jet_heatmap = tf.keras.preprocessing.image.array_to_img(jet_heatmap)
|
371 |
-
jet_heatmap = jet_heatmap.resize((img.shape[1], img.shape[0]))
|
372 |
-
jet_heatmap = tf.keras.preprocessing.image.img_to_array(jet_heatmap)
|
373 |
-
|
374 |
-
superimposed_img = jet_heatmap * alpha + img
|
375 |
-
superimposed_img = tf.keras.preprocessing.image.array_to_img(superimposed_img)
|
376 |
-
|
377 |
-
superimposed_img.save(cam_path)
|
378 |
-
|
379 |
-
return cam_path
|
380 |
-
|
381 |
-
# Display the part of the pictures used by the neural network to classify the pictures
|
382 |
-
fig, axes = plt.subplots(nrows=3, ncols=5, figsize=(15, 10),
|
383 |
-
subplot_kw={'xticks': [], 'yticks': []})
|
384 |
-
|
385 |
-
for i, ax in enumerate(axes.flat):
|
386 |
-
img_path = test_df.Filepath.iloc[random_index[i]]
|
387 |
-
img_array = tf.keras.applications.efficientnet_v2.preprocess_input(get_img_array(img_path, size=(224, 224)))
|
388 |
-
heatmap = make_gradcam_heatmap(img_array, model, last_conv_layer_name="top_conv")
|
389 |
-
cam_path = save_and_display_gradcam(img_path, heatmap)
|
390 |
-
ax.imshow(plt.imread(cam_path))
|
391 |
-
ax.set_title(f"True: {test_df.Label.iloc[random_index[i]]}\nPredicted: {pred[random_index[i]]}")
|
392 |
-
plt.tight_layout()
|
393 |
-
plt.show()
|
394 |
|
395 |
-
# Define Gradio interface
|
396 |
def predict_image(img):
|
397 |
img = np.array(img)
|
398 |
-
img_resized = tf.image.resize(img, (
|
399 |
img_4d = tf.expand_dims(img_resized, axis=0)
|
400 |
prediction = model.predict(img_4d)[0]
|
401 |
-
|
|
|
402 |
|
403 |
image = gr.Image()
|
404 |
-
label = gr.Label(num_top_classes=
|
405 |
-
|
406 |
-
# Define custom CSS for background image
|
407 |
-
custom_css = """
|
408 |
-
body {
|
409 |
-
background-image: url('extracted_files/Pest_Dataset/bees/bees (444).jpg');
|
410 |
-
background-size: cover;
|
411 |
-
background-repeat: no-repeat;
|
412 |
-
background-attachment: fixed;
|
413 |
-
color: white;
|
414 |
-
}
|
415 |
-
"""
|
416 |
|
417 |
gr.Interface(
|
418 |
fn=predict_image,
|
419 |
inputs=image,
|
420 |
outputs=label,
|
421 |
-
title="
|
422 |
-
description="
|
423 |
-
css=custom_css
|
424 |
).launch(debug=True)
|
425 |
-
|
|
|
1 |
+
import gradio as gr
|
2 |
import matplotlib.pyplot as plt
|
3 |
import numpy as np
|
4 |
import os
|
|
|
8 |
from tensorflow import keras
|
9 |
from tensorflow.keras import layers
|
10 |
from tensorflow.keras.models import Sequential
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
|
12 |
from PIL import Image
|
13 |
import gdown
|
14 |
import zipfile
|
|
|
15 |
import pathlib
|
16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
# Define the Google Drive shareable link
|
18 |
gdrive_url = 'https://drive.google.com/file/d/1HjHYlQyRz5oWt8kehkt1TiOGRRlKFsv8/view?usp=drive_link'
|
19 |
|
|
|
55 |
|
56 |
# Path to the dataset directory
|
57 |
data_dir = pathlib.Path('extracted_files/Pest_Dataset')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
58 |
|
59 |
+
img_height, img_width = 180, 180
|
60 |
+
batch_size = 32
|
61 |
+
train_ds = tf.keras.preprocessing.image_dataset_from_directory(
|
62 |
+
data_dir,
|
63 |
+
validation_split=0.2,
|
64 |
+
subset="training",
|
65 |
+
seed=123,
|
66 |
+
image_size=(img_height, img_width),
|
67 |
+
batch_size=batch_size
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
68 |
)
|
69 |
|
70 |
+
val_ds = tf.keras.preprocessing.image_dataset_from_directory(
|
71 |
+
data_dir,
|
72 |
+
validation_split=0.2,
|
73 |
+
subset="validation",
|
74 |
+
seed=123,
|
75 |
+
image_size=(img_height, img_width),
|
76 |
+
batch_size=batch_size
|
77 |
)
|
78 |
|
79 |
+
class_names = train_ds.class_names
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
80 |
|
81 |
+
data_augmentation = keras.Sequential(
|
82 |
+
[
|
83 |
+
layers.RandomFlip("horizontal",
|
84 |
+
input_shape=(img_height,
|
85 |
+
img_width,
|
86 |
+
3)),
|
87 |
+
layers.RandomRotation(0.1),
|
88 |
+
layers.RandomZoom(0.1),
|
89 |
+
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
90 |
)
|
91 |
|
92 |
+
num_classes = len(class_names)
|
93 |
+
model = Sequential([
|
94 |
+
data_augmentation,
|
95 |
+
layers.Rescaling(1. / 255),
|
96 |
+
layers.Conv2D(16, 3, padding='same', activation='relu'),
|
97 |
+
layers.MaxPooling2D(),
|
98 |
+
layers.Conv2D(32, 3, padding='same', activation='relu'),
|
99 |
+
layers.MaxPooling2D(),
|
100 |
+
layers.Conv2D(64, 3, padding='same', activation='relu'),
|
101 |
+
layers.MaxPooling2D(),
|
102 |
+
layers.Dropout(0.2),
|
103 |
+
layers.Flatten(),
|
104 |
+
layers.Dense(128, activation='relu'),
|
105 |
+
layers.Dense(num_classes, name="outputs")
|
106 |
])
|
107 |
|
108 |
+
model.compile(optimizer='adam',
|
109 |
+
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
|
110 |
+
metrics=['accuracy'])
|
111 |
|
112 |
+
epochs = 20
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
113 |
history = model.fit(
|
114 |
+
train_ds,
|
115 |
+
validation_data=val_ds,
|
116 |
+
epochs=epochs
|
|
|
|
|
|
|
|
|
|
|
|
|
117 |
)
|
118 |
|
119 |
+
import gradio as gr
|
120 |
+
import numpy as np
|
121 |
+
import tensorflow as tf
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
122 |
|
|
|
123 |
def predict_image(img):
|
124 |
img = np.array(img)
|
125 |
+
img_resized = tf.image.resize(img, (180, 180))
|
126 |
img_4d = tf.expand_dims(img_resized, axis=0)
|
127 |
prediction = model.predict(img_4d)[0]
|
128 |
+
probabilities = tf.nn.softmax(prediction)
|
129 |
+
return {class_names[i]: float(probabilities[i]) * 100 for i in range(len(class_names))}
|
130 |
|
131 |
image = gr.Image()
|
132 |
+
label = gr.Label(num_top_classes=12)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
133 |
|
134 |
gr.Interface(
|
135 |
fn=predict_image,
|
136 |
inputs=image,
|
137 |
outputs=label,
|
138 |
+
title="Pest Classification",
|
139 |
+
description="Upload an image of a pest to classify it into one of the predefined categories."
|
|
|
140 |
).launch(debug=True)
|
|