UdaraChamidu commited on
Commit
8689c99
·
verified ·
1 Parent(s): 0315d72

Delete garbage_classification_preprocessing.ipynb

Browse files
garbage_classification_preprocessing.ipynb DELETED
@@ -1,436 +0,0 @@
1
- {
2
- "cells": [
3
- {
4
- "cell_type": "markdown",
5
- "id": "6e68dd4c",
6
- "metadata": {},
7
- "source": [
8
- "# Garbage Classification — Full notebook with image preprocessing (step-by-step)\n",
9
- "\n",
10
- "This notebook:\n",
11
- "- Loads the garbage classification dataset (from folder structure),\n",
12
- "- Applies an **image preprocessing pipeline** (histogram equalization, blur, Sobel edges) using a `preprocessing_function` for `ImageDataGenerator`,\n",
13
- "- Trains two models (DenseNet121 and ResNet101V2) with transfer learning,\n",
14
- "- Evaluates and visualizes results (confusion matrix, classification report),\n",
15
- "- Includes visualization of **original vs enhanced** images.\n",
16
- "\n",
17
- "**Note:** Adjust `path` if your dataset location is different (example: Google Drive or Kaggle dataset).\n"
18
- ]
19
- },
20
- {
21
- "cell_type": "code",
22
- "execution_count": null,
23
- "id": "578daf0e",
24
- "metadata": {},
25
- "outputs": [],
26
- "source": [
27
- "# 1) Imports\n",
28
- "import numpy as np\n",
29
- "import pandas as pd\n",
30
- "import matplotlib.pyplot as plt\n",
31
- "import seaborn as sns\n",
32
- "import os\n",
33
- "from PIL import Image\n",
34
- "\n",
35
- "import tensorflow as tf\n",
36
- "from tensorflow.keras.layers import Conv2D , MaxPooling2D , Dense , Flatten , Dropout , GlobalAveragePooling2D\n",
37
- "from tensorflow.keras.models import Sequential , Model\n",
38
- "from tensorflow.keras.applications import DenseNet121, ResNet101V2\n",
39
- "from pathlib import Path\n",
40
- "from sklearn.model_selection import train_test_split\n",
41
- "from sklearn.metrics import confusion_matrix, classification_report\n",
42
- "\n",
43
- "# optimizer\n",
44
- "from tensorflow.keras.optimizers import Adam, AdamW\n",
45
- "\n",
46
- "import cv2\n",
47
- "\n",
48
- "import warnings\n",
49
- "warnings.filterwarnings('ignore')\n",
50
- "\n",
51
- "print('TensorFlow version:', tf.__version__)\n"
52
- ]
53
- },
54
- {
55
- "cell_type": "code",
56
- "execution_count": null,
57
- "id": "c507e2dd",
58
- "metadata": {},
59
- "outputs": [],
60
- "source": [
61
- "# 2) Parameters & dataset path\n",
62
- "# Change this path if your dataset is elsewhere (e.g., Google Drive or local)\n",
63
- "path = '/kaggle/input/garbage-classification/garbage_classification' # <-- keep or update\n",
64
- "img_size = 128\n",
65
- "batch_size = 32\n",
66
- "random_state = 42\n"
67
- ]
68
- },
69
- {
70
- "cell_type": "code",
71
- "execution_count": null,
72
- "id": "43490050",
73
- "metadata": {},
74
- "outputs": [],
75
- "source": [
76
- "# 3) Build dataframe of image filepaths and labels\n",
77
- "filepaths = []\n",
78
- "labels = []\n",
79
- "\n",
80
- "for root, dirs, files in os.walk(path):\n",
81
- " for file in files:\n",
82
- " if file.lower().endswith(('.png', '.jpg', '.jpeg', '.gif', '.bmp')):\n",
83
- " filepath = os.path.join(root, file)\n",
84
- " filepaths.append(filepath)\n",
85
- " label = os.path.basename(root)\n",
86
- " labels.append(label)\n",
87
- "\n",
88
- "data_df = pd.DataFrame({'filepath': filepaths, 'original_label': labels})\n",
89
- "print('Total images found:', len(data_df))\n",
90
- "data_df.head()\n"
91
- ]
92
- },
93
- {
94
- "cell_type": "code",
95
- "execution_count": null,
96
- "id": "7d26c28c",
97
- "metadata": {},
98
- "outputs": [],
99
- "source": [
100
- "# 4) Unify labels (example: unify various glass subfolders into 'glass')\n",
101
- "def unify_glass_labels(label):\n",
102
- " if 'glass' in label.lower():\n",
103
- " return 'glass'\n",
104
- " return label\n",
105
- "\n",
106
- "data_df['unified_label'] = data_df['original_label'].apply(unify_glass_labels)\n",
107
- "data_df.drop(columns=['original_label'], inplace=True)\n",
108
- "\n",
109
- "print('Class distribution:')\n",
110
- "display(data_df['unified_label'].value_counts())\n"
111
- ]
112
- },
113
- {
114
- "cell_type": "code",
115
- "execution_count": null,
116
- "id": "c77a46c6",
117
- "metadata": {},
118
- "outputs": [],
119
- "source": [
120
- "# 5) Train / Test split (stratified)\n",
121
- "train_df, test_df = train_test_split(\n",
122
- " data_df,\n",
123
- " test_size=0.2,\n",
124
- " stratify=data_df['unified_label'],\n",
125
- " random_state=random_state\n",
126
- ")\n",
127
- "\n",
128
- "print('Train samples:', len(train_df))\n",
129
- "print('Test samples :', len(test_df))\n"
130
- ]
131
- },
132
- {
133
- "cell_type": "code",
134
- "execution_count": null,
135
- "id": "370a47a7",
136
- "metadata": {},
137
- "outputs": [],
138
- "source": [
139
- "# 6) Preprocessing function\n",
140
- "# This function is compatible with ImageDataGenerator.preprocessing_function.\n",
141
- "# Keras calls the preprocessing_function after rescale (so input here will be float32 in [0,1]).\n",
142
- "# We convert back to 0-255 before applying cv2 operations, then return a float array in [0,1].\n",
143
- "\n",
144
- "def enhance_preprocessing(img):\n",
145
- " import numpy as np\n",
146
- " import cv2\n",
147
- " # img: float32 in [0,1], shape (H, W, 3), color order: RGB\n",
148
- " # Convert to uint8 [0,255]\n",
149
- " arr = (img * 255).astype('uint8')\n",
150
- " # Convert RGB -> Grayscale\n",
151
- " gray = cv2.cvtColor(arr, cv2.COLOR_RGB2GRAY)\n",
152
- " # Histogram equalization\n",
153
- " equalized = cv2.equalizeHist(gray)\n",
154
- " # Gaussian blur\n",
155
- " blurred = cv2.GaussianBlur(equalized, (3, 3), 0)\n",
156
- " # Sobel edge detection\n",
157
- " sobelx = cv2.Sobel(blurred, cv2.CV_64F, 1, 0, ksize=3)\n",
158
- " sobely = cv2.Sobel(blurred, cv2.CV_64F, 0, 1, ksize=3)\n",
159
- " sobel = np.sqrt(sobelx**2 + sobely**2)\n",
160
- " sobel = np.clip(sobel, 0, 255).astype('uint8')\n",
161
- " # Stack back to 3 channels (RGB-like)\n",
162
- " final = np.stack([sobel, sobel, sobel], axis=-1)\n",
163
- " # Convert to float [0,1]\n",
164
- " final = final.astype('float32') / 255.0\n",
165
- " return final\n"
166
- ]
167
- },
168
- {
169
- "cell_type": "code",
170
- "execution_count": null,
171
- "id": "6e296335",
172
- "metadata": {},
173
- "outputs": [],
174
- "source": [
175
- "# 7) Create ImageDataGenerators (with augmentation for training)\n",
176
- "from tensorflow.keras.preprocessing.image import ImageDataGenerator\n",
177
- "\n",
178
- "train_gen = ImageDataGenerator(\n",
179
- " rescale=1./255,\n",
180
- " rotation_range=20,\n",
181
- " width_shift_range=0.2,\n",
182
- " height_shift_range=0.2,\n",
183
- " shear_range=0.2,\n",
184
- " zoom_range=0.2,\n",
185
- " horizontal_flip=True,\n",
186
- " fill_mode='nearest',\n",
187
- " preprocessing_function=enhance_preprocessing # apply our enhancement\n",
188
- ")\n",
189
- "\n",
190
- "test_gen = ImageDataGenerator(\n",
191
- " rescale=1./255,\n",
192
- " preprocessing_function=enhance_preprocessing # apply same preprocessing for evaluation\n",
193
- ")\n",
194
- "\n",
195
- "train_data = train_gen.flow_from_dataframe(\n",
196
- " train_df,\n",
197
- " x_col='filepath',\n",
198
- " y_col='unified_label',\n",
199
- " target_size=(img_size, img_size),\n",
200
- " batch_size=batch_size,\n",
201
- " class_mode='categorical',\n",
202
- " color_mode='rgb',\n",
203
- " shuffle=True\n",
204
- ")\n",
205
- "\n",
206
- "test_data = test_gen.flow_from_dataframe(\n",
207
- " test_df,\n",
208
- " x_col='filepath',\n",
209
- " y_col='unified_label',\n",
210
- " target_size=(img_size, img_size),\n",
211
- " batch_size=batch_size,\n",
212
- " class_mode='categorical',\n",
213
- " color_mode='rgb',\n",
214
- " shuffle=False\n",
215
- ")\n"
216
- ]
217
- },
218
- {
219
- "cell_type": "code",
220
- "execution_count": null,
221
- "id": "848d62b5",
222
- "metadata": {},
223
- "outputs": [],
224
- "source": [
225
- "# 8) Class indices & labels\n",
226
- "class_indices = train_data.class_indices\n",
227
- "print('Class indices (label -> index):')\n",
228
- "print(class_indices)\n",
229
- "\n",
230
- "# Build index -> label mapping for predictions later\n",
231
- "index_to_label = {v: k for k, v in class_indices.items()}\n",
232
- "classes = [index_to_label[i] for i in range(len(index_to_label))]\n",
233
- "print('\\nClasses (in model index order):', classes)\n"
234
- ]
235
- },
236
- {
237
- "cell_type": "code",
238
- "execution_count": null,
239
- "id": "2d37b6f8",
240
- "metadata": {},
241
- "outputs": [],
242
- "source": [
243
- "# 9) Visualize: Original vs Enhanced\n",
244
- "from tensorflow.keras.preprocessing.image import load_img, img_to_array\n",
245
- "\n",
246
- "# Pick a sample image from test_df\n",
247
- "sample_fp = test_df['filepath'].iloc[0]\n",
248
- "print('Sample filepath:', sample_fp)\n",
249
- "\n",
250
- "orig = img_to_array(load_img(sample_fp, target_size=(img_size, img_size))) / 255.0\n",
251
- "enh = enhance_preprocessing(orig)\n",
252
- "\n",
253
- "fig, axes = plt.subplots(1,2, figsize=(10,5))\n",
254
- "axes[0].imshow(orig)\n",
255
- "axes[0].set_title('Original (rescaled)')\n",
256
- "axes[0].axis('off')\n",
257
- "\n",
258
- "axes[1].imshow(enh)\n",
259
- "axes[1].set_title('Enhanced (preprocessing_function)')\n",
260
- "axes[1].axis('off')\n",
261
- "plt.show()\n"
262
- ]
263
- },
264
- {
265
- "cell_type": "code",
266
- "execution_count": null,
267
- "id": "693d4c04",
268
- "metadata": {},
269
- "outputs": [],
270
- "source": [
271
- "# 10) Train DenseNet121 (transfer learning)\n",
272
- "num_classes = len(class_indices)\n",
273
- "\n",
274
- "base_model = DenseNet121(input_shape=(img_size, img_size, 3), include_top=False, weights='imagenet')\n",
275
- "base_model.trainable = True\n",
276
- "\n",
277
- "x = base_model.output\n",
278
- "x = GlobalAveragePooling2D()(x)\n",
279
- "x = Dropout(0.3)(x)\n",
280
- "predictions = Dense(num_classes, activation='softmax')(x)\n",
281
- "\n",
282
- "model_DenseNet121 = Model(inputs=base_model.input, outputs=predictions)\n",
283
- "\n",
284
- "optimizer = AdamW(learning_rate=1e-4)\n",
285
- "model_DenseNet121.compile(loss='categorical_crossentropy', optimizer=optimizer, metrics=['accuracy'])\n",
286
- "model_DenseNet121.summary()\n"
287
- ]
288
- },
289
- {
290
- "cell_type": "code",
291
- "execution_count": null,
292
- "id": "f7c970e1",
293
- "metadata": {},
294
- "outputs": [],
295
- "source": [
296
- "# 11) Fit DenseNet121\n",
297
- "from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint\n",
298
- "\n",
299
- "earlystop = EarlyStopping(patience=5, restore_best_weights=True, monitor='val_accuracy')\n",
300
- "checkpoint_path = 'dense121_best.h5'\n",
301
- "mc = ModelCheckpoint(checkpoint_path, monitor='val_accuracy', save_best_only=True, verbose=1)\n",
302
- "\n",
303
- "epochs = 20\n",
304
- "\n",
305
- "history_dense = model_DenseNet121.fit(\n",
306
- " train_data,\n",
307
- " validation_data=test_data,\n",
308
- " epochs=epochs,\n",
309
- " callbacks=[earlystop, mc]\n",
310
- ")\n"
311
- ]
312
- },
313
- {
314
- "cell_type": "code",
315
- "execution_count": null,
316
- "id": "46f10b3e",
317
- "metadata": {},
318
- "outputs": [],
319
- "source": [
320
- "# 12) Evaluate DenseNet121\n",
321
- "loss, accuracy = model_DenseNet121.evaluate(test_data)\n",
322
- "print(f'DenseNet121 -> Loss: {loss:.4f}, Accuracy: {accuracy:.4f}')\n",
323
- "\n",
324
- "# Predictions\n",
325
- "preds = model_DenseNet121.predict(test_data, verbose=1)\n",
326
- "y_pred_idx = np.argmax(preds, axis=1)\n",
327
- "y_pred_labels = [index_to_label[i] for i in y_pred_idx]\n",
328
- "y_true_labels = test_df['unified_label'].values\n",
329
- "\n",
330
- "# Confusion matrix\n",
331
- "plt.figure(figsize=(10,8))\n",
332
- "cm = confusion_matrix(y_true_labels, y_pred_labels, labels=classes)\n",
333
- "sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', xticklabels=classes, yticklabels=classes)\n",
334
- "plt.title('DenseNet121 - Confusion Matrix')\n",
335
- "plt.show()\n",
336
- "\n",
337
- "print('\\nClassification Report:')\n",
338
- "print(classification_report(y_true_labels, y_pred_labels, target_names=classes))\n"
339
- ]
340
- },
341
- {
342
- "cell_type": "code",
343
- "execution_count": null,
344
- "id": "8968c73c",
345
- "metadata": {},
346
- "outputs": [],
347
- "source": [
348
- "# 13) Train ResNet101V2 (transfer learning)\n",
349
- "base_model = ResNet101V2(input_shape=(img_size, img_size, 3), include_top=False, weights='imagenet')\n",
350
- "base_model.trainable = True\n",
351
- "\n",
352
- "x = base_model.output\n",
353
- "x = GlobalAveragePooling2D()(x)\n",
354
- "x = Dropout(0.5)(x)\n",
355
- "predictions = Dense(num_classes, activation='softmax')(x)\n",
356
- "\n",
357
- "model_ResNet101V2 = Model(inputs=base_model.input, outputs=predictions)\n",
358
- "\n",
359
- "optimizer = AdamW(learning_rate=1e-4)\n",
360
- "model_ResNet101V2.compile(loss='categorical_crossentropy', optimizer=optimizer, metrics=['accuracy'])\n",
361
- "model_ResNet101V2.summary()\n"
362
- ]
363
- },
364
- {
365
- "cell_type": "code",
366
- "execution_count": null,
367
- "id": "639722e9",
368
- "metadata": {},
369
- "outputs": [],
370
- "source": [
371
- "# 14) Fit ResNet101V2\n",
372
- "checkpoint_path_r = 'resnet101v2_best.h5'\n",
373
- "mc_r = ModelCheckpoint(checkpoint_path_r, monitor='val_accuracy', save_best_only=True, verbose=1)\n",
374
- "earlystop_r = EarlyStopping(patience=5, restore_best_weights=True, monitor='val_accuracy')\n",
375
- "\n",
376
- "history_resnet = model_ResNet101V2.fit(\n",
377
- " train_data,\n",
378
- " validation_data=test_data,\n",
379
- " epochs=epochs,\n",
380
- " callbacks=[earlystop_r, mc_r]\n",
381
- ")\n"
382
- ]
383
- },
384
- {
385
- "cell_type": "code",
386
- "execution_count": null,
387
- "id": "e2ba64ab",
388
- "metadata": {},
389
- "outputs": [],
390
- "source": [
391
- "# 15) Evaluate ResNet101V2\n",
392
- "loss_r, accuracy_r = model_ResNet101V2.evaluate(test_data)\n",
393
- "print(f'ResNet101V2 -> Loss: {loss_r:.4f}, Accuracy: {accuracy_r:.4f}')\n",
394
- "\n",
395
- "# Predictions\n",
396
- "preds_r = model_ResNet101V2.predict(test_data, verbose=1)\n",
397
- "y_pred_idx_r = np.argmax(preds_r, axis=1)\n",
398
- "y_pred_labels_r = [index_to_label[i] for i in y_pred_idx_r]\n",
399
- "\n",
400
- "plt.figure(figsize=(10,8))\n",
401
- "cm_r = confusion_matrix(y_true_labels, y_pred_labels_r, labels=classes)\n",
402
- "sns.heatmap(cm_r, annot=True, fmt='d', cmap='Blues', xticklabels=classes, yticklabels=classes)\n",
403
- "plt.title('ResNet101V2 - Confusion Matrix')\n",
404
- "plt.show()\n",
405
- "\n",
406
- "print('\\nClassification Report (ResNet101V2):')\n",
407
- "print(classification_report(y_true_labels, y_pred_labels_r, target_names=classes))\n"
408
- ]
409
- },
410
- {
411
- "cell_type": "code",
412
- "execution_count": null,
413
- "id": "b70f9f9e",
414
- "metadata": {},
415
- "outputs": [],
416
- "source": [
417
- "# 16) Plot training history (DenseNet121 vs validation)\n",
418
- "def plot_history(h, title='Model'):\n",
419
- " plt.figure(figsize=(8,4))\n",
420
- " plt.plot(h.history['accuracy'], label='train_acc')\n",
421
- " plt.plot(h.history['val_accuracy'], label='val_acc')\n",
422
- " plt.xlabel('Epoch')\n",
423
- " plt.ylabel('Accuracy')\n",
424
- " plt.legend()\n",
425
- " plt.title(title)\n",
426
- " plt.show()\n",
427
- "\n",
428
- "plot_history(history_dense, title='DenseNet121 Accuracy')\n",
429
- "plot_history(history_resnet, title='ResNet101V2 Accuracy')\n"
430
- ]
431
- }
432
- ],
433
- "metadata": {},
434
- "nbformat": 4,
435
- "nbformat_minor": 5
436
- }