AIOmarRehan commited on
Commit
5d3b587
·
verified ·
1 Parent(s): fa51247

Upload 3 files

Browse files
Files changed (3) hide show
  1. README.md +203 -3
  2. app.py +47 -0
  3. requirements.txt +4 -0
README.md CHANGED
@@ -1,8 +1,8 @@
1
  ---
2
  title: CNN Autoencoder For Image Denoising
3
- emoji: 🏃
4
- colorFrom: red
5
- colorTo: indigo
6
  sdk: gradio
7
  sdk_version: 5.49.1
8
  app_file: app.py
@@ -12,3 +12,203 @@ short_description: U-Net based CNN autoencoder designed to denoise noisy image.
12
  ---
13
 
14
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
  title: CNN Autoencoder For Image Denoising
3
+ emoji: 😻
4
+ colorFrom: purple
5
+ colorTo: pink
6
  sdk: gradio
7
  sdk_version: 5.49.1
8
  app_file: app.py
 
12
  ---
13
 
14
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
15
+
16
+ ---
17
+
18
+ # A U-Net–Based CNN Autoencoder for Cleaning Noisy Images Before Classification
19
+
20
+ A practical walkthrough of how I built and trained a deep-learning model to denoise images and boost classification performance.
21
+
22
+ When I first started working with image-classification tasks, I noticed something that kept hurting my models: **noise**. Even small distortions—random dots, compression artifacts, sensor noise—were enough to confuse the classifier.
23
+
24
+ The obvious solution was to train on noisy data… but that never felt elegant. Instead, I wanted a **preprocessing model** whose sole job is to take a noisy image and return a clean version of it. The classifier would then work on much better input.
25
+
26
+ That idea led me to build a **U-Net–based CNN Autoencoder**.
27
+
28
+ This article walks you through:
29
+
30
+ * why I chose a U-Net structure
31
+ * how the autoencoder was built
32
+ * how noisy images were generated
33
+ * how the model was trained and evaluated
34
+ * what results I achieved
35
+
36
+ **Goal:**
37
+ *Use a smart deep-learning architecture to clean images before classification.*
38
+
39
+ ---
40
+
41
+ ## 🔧 1. Setting Up the Environment
42
+
43
+ I started by loading the usual deep-learning stack:
44
+
45
+ ```python
46
+ import tensorflow as tf
47
+ from tensorflow.keras.layers import *
48
+ from tensorflow.keras.models import Model
49
+ import numpy as np
50
+ import matplotlib.pyplot as plt
51
+ ```
52
+
53
+ This is the typical setup for building custom architectures using Keras.
54
+
55
+ ---
56
+
57
+ ## 2. Why a U-Net Autoencoder?
58
+
59
+ A normal autoencoder compresses an image into a bottleneck and then reconstructs it. It works—but often loses details.
60
+
61
+ A **U-Net**, however, uses **skip connections**, meaning it:
62
+
63
+ * compresses the image (downsampling)
64
+ * learns a compact representation
65
+ * reconstructs it (upsampling)
66
+ * *also* reconnects high-resolution features from earlier layers
67
+
68
+ This makes U-Net excellent for:
69
+
70
+ * denoising
71
+ * segmentation
72
+ * super-resolution
73
+ * restoration tasks
74
+
75
+ So instead of a plain autoencoder, I built one using a U-shaped architecture.
76
+
77
+ ---
78
+
79
+ ## 3. Building the U-Net Autoencoder
80
+
81
+ ### Encoder
82
+
83
+ ```python
84
+ c1 = Conv2D(64, 3, activation='relu', padding='same')(inputs)
85
+ p1 = MaxPooling2D((2, 2))(c1)
86
+
87
+ c2 = Conv2D(128, 3, activation='relu', padding='same')(p1)
88
+ p2 = MaxPooling2D((2, 2))(c2)
89
+ ```
90
+
91
+ ### Bottleneck
92
+
93
+ ```python
94
+ bn = Conv2D(256, 3, activation='relu', padding='same')(p2)
95
+ ```
96
+
97
+ ### Decoder
98
+
99
+ ```python
100
+ u1 = UpSampling2D((2, 2))(bn)
101
+ m1 = concatenate([u1, c2])
102
+ c3 = Conv2D(128, 3, activation='relu', padding='same')(m1)
103
+
104
+ u2 = UpSampling2D((2, 2))(c3)
105
+ m2 = concatenate([u2, c1])
106
+ c4 = Conv2D(64, 3, activation='relu', padding='same')(m2)
107
+ ```
108
+
109
+ ### Output
110
+
111
+ ```python
112
+ outputs = Conv2D(1, 3, activation='sigmoid', padding='same')(c4)
113
+ ```
114
+
115
+ Even though the full architecture is larger, the core idea is:
116
+
117
+ **down → compress → up → reconnect → reconstruct**
118
+
119
+ ---
120
+
121
+ ## 4. Generating & Preprocessing Noisy Images
122
+
123
+ Instead of downloading a noisy dataset, I artificially added **Gaussian noise** to MNIST digits:
124
+
125
+ ```python
126
+ noise_factor = 0.4
127
+ x_train_noisy = x_train + noise_factor * np.random.normal(
128
+ loc=0.0, scale=1.0, size=x_train.shape
129
+ )
130
+ ```
131
+
132
+ This created image pairs:
133
+
134
+ * clean MNIST digit
135
+ * noisy version of the same digit
136
+
137
+ Perfect for training an autoencoder.
138
+
139
+ ---
140
+
141
+ ## 5. Training the Model
142
+
143
+ Compile:
144
+
145
+ ```python
146
+ model.compile(optimizer='adam', loss='binary_crossentropy')
147
+ ```
148
+
149
+ Train:
150
+
151
+ ```python
152
+ model.fit(
153
+ x_train_noisy, x_train,
154
+ epochs=10,
155
+ batch_size=128,
156
+ validation_split=0.1
157
+ )
158
+ ```
159
+
160
+ The autoencoder learns one simple rule:
161
+
162
+ **Input:** noisy image
163
+ **Output:** clean image
164
+
165
+ ---
166
+
167
+ ## 6. Visualizing the Results
168
+
169
+ After training, I checked:
170
+
171
+ * noisy input
172
+ * autoencoder output
173
+ * original clean image
174
+
175
+ The model consistently removed a large amount of noise, smoothing textures while preserving structure. Not perfect—but for MNIST and a lightweight U-Net, the results were very encouraging.
176
+
177
+ ---
178
+
179
+ ## 7. Why This Helps Classification
180
+
181
+ If you already have (or plan to build) a classifier—CNN, ResNet, etc.—you can use a pipeline like:
182
+
183
+ ```
184
+ Noisy Image → Autoencoder (denoising) → Classifier → Prediction
185
+ ```
186
+
187
+ This helps with real-world noise sources like:
188
+
189
+ * camera noise
190
+ * poor lighting
191
+ * compression artifacts
192
+ * motion blur
193
+
194
+ **Clean input → better predictions.**
195
+
196
+ ---
197
+
198
+ ## 8. Key Takeaways
199
+
200
+ - **U-Net skip connections** help preserve important features.
201
+ - **Autoencoders** serve as powerful preprocessing tools.
202
+ - **Denoised images** can significantly improve classification accuracy.
203
+ - The **model is lightweight** and easy to integrate.
204
+ - The approach **scales to any image dataset**.
205
+
206
+
207
+ This approach is not just theoretical—it’s extremely practical.
208
+ Any project involving real-world noisy data can benefit from this denoising layer.
209
+
210
+ ---
211
+
212
+ ## 9. Results
213
+
214
+ [Watch Demo Video](Results/A_U-Net_Autoencoder.mp4)
app.py ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ from tensorflow.keras.models import load_model
3
+ from PIL import Image
4
+ import gradio as gr
5
+
6
+ # Load model
7
+ model = load_model("unet_model.h5", compile=False)
8
+
9
+ # Preprocess function
10
+ def preprocess_image(image, target_size=(192, 176)):
11
+ image = image.resize((target_size[1], target_size[0])) # width, height
12
+ image = np.array(image) / 255.0
13
+ if image.ndim == 2:
14
+ image = np.expand_dims(image, axis=-1)
15
+ return np.expand_dims(image, axis=0)
16
+
17
+ # Prediction function for Gradio
18
+ def predict(img):
19
+ # Convert to grayscale
20
+ img = img.convert("L")
21
+
22
+ # Preprocess
23
+ input_data = preprocess_image(img)
24
+
25
+ # Model prediction
26
+ pred = model.predict(input_data)[0]
27
+
28
+ # Remove channel
29
+ if pred.ndim == 3 and pred.shape[-1] == 1:
30
+ pred = np.squeeze(pred, axis=-1)
31
+
32
+ # Convert to image
33
+ pred_img = (pred * 255).astype(np.uint8)
34
+ pred_img = Image.fromarray(pred_img)
35
+
36
+ return pred_img
37
+
38
+ # Gradio UI
39
+ interface = gr.Interface(
40
+ fn=predict,
41
+ inputs=gr.Image(type="pil", label="Upload Image"),
42
+ outputs=gr.Image(type="pil", label="Denoised Output"),
43
+ title="U-Net Image Denoising",
44
+ description="Upload a grayscale image and get the denoised result using a U-Net model."
45
+ )
46
+
47
+ interface.launch()
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ tensorflow
2
+ gradio
3
+ numpy
4
+ Pillow