muhammadhamza-stack commited on
Commit
ab45e08
·
1 Parent(s): ea5ee8e

dockerize the app

Browse files
Files changed (5) hide show
  1. .DS_Store +0 -0
  2. Dockerfile +31 -0
  3. README.md +1 -1
  4. app.py +4 -382
  5. runtime.txt +0 -1
.DS_Store ADDED
Binary file (6.15 kB). View file
 
Dockerfile ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # HF Spaces compatible base image
2
+ FROM python:3.9-slim
3
+
4
+ # Prevent Python from writing .pyc files
5
+ ENV PYTHONDONTWRITEBYTECODE=1
6
+ ENV PYTHONUNBUFFERED=1
7
+
8
+ # Set working directory
9
+ WORKDIR /app
10
+
11
+ # System dependencies (safe defaults)
12
+ RUN apt-get update && apt-get install -y \
13
+ git \
14
+ curl \
15
+ && rm -rf /var/lib/apt/lists/*
16
+
17
+ # Copy requirements first (better Docker caching)
18
+ COPY requirements.txt .
19
+
20
+ # Upgrade pip and install dependencies
21
+ RUN pip install --upgrade pip \
22
+ && pip install --no-cache-dir -r requirements.txt
23
+
24
+ # Copy the rest of the application
25
+ COPY . .
26
+
27
+ # Hugging Face Spaces uses port 7860
28
+ EXPOSE 7860
29
+
30
+ # Start the app
31
+ CMD ["python", "app.py"]
README.md CHANGED
@@ -3,7 +3,7 @@ title: ImageRecognition
3
  emoji: 💬
4
  colorFrom: yellow
5
  colorTo: purple
6
- sdk: gradio
7
  sdk_version: 5.0.1
8
  app_file: app.py
9
  pinned: false
 
3
  emoji: 💬
4
  colorFrom: yellow
5
  colorTo: purple
6
+ sdk: docker
7
  sdk_version: 5.0.1
8
  app_file: app.py
9
  pinned: false
app.py CHANGED
@@ -1,384 +1,3 @@
1
- # import os
2
- # os.environ["CUDA_VISIBLE_DEVICES"] = "-1"
3
-
4
-
5
- # import os
6
- # import tempfile
7
- # import numpy as np
8
- # import cv2
9
- # import gradio as gr
10
- # from tensorflow.keras.applications import ResNet50
11
- # from tensorflow.keras.applications.resnet50 import preprocess_input
12
- # from tensorflow.keras.preprocessing import image
13
- # from skimage.metrics import structural_similarity as ssim
14
- # from PIL import Image
15
- # from io import BytesIO
16
-
17
-
18
- # # Disable GPU for TensorFlow
19
- # os.environ["TF_ENABLE_ONEDNN_OPTS"] = "0"
20
- # os.environ["CUDA_VISIBLE_DEVICES"] = "-1"
21
-
22
- # class ImageCharacterClassifier:
23
- # def __init__(self, similarity_threshold=0.5):
24
- # self.model = ResNet50(weights='imagenet', include_top=False, pooling='avg')
25
- # self.similarity_threshold = similarity_threshold
26
-
27
- # def load_and_preprocess_image(self, img):
28
- # # Convert image to array and preprocess it
29
- # img = img.convert('RGB')
30
- # img_array = np.array(img)
31
- # img_array = cv2.resize(img_array, (224, 224)) # Ensure correct size
32
- # img_array = np.expand_dims(img_array, axis=0)
33
- # img_array = preprocess_input(img_array)
34
- # return img_array
35
-
36
- # def extract_features(self, img):
37
- # preprocessed_img = self.load_and_preprocess_image(img)
38
- # features = self.model.predict(preprocessed_img)
39
- # return features
40
-
41
- # def calculate_ssim(self, img1, img2):
42
- # img1_gray = cv2.cvtColor(img1, cv2.COLOR_RGB2GRAY)
43
- # img2_gray = cv2.cvtColor(img2, cv2.COLOR_RGB2GRAY)
44
- # img2_gray = cv2.resize(img2_gray, (img1_gray.shape[1], img1_gray.shape[0]))
45
- # return ssim(img1_gray, img2_gray)
46
-
47
- # def process_images(reference_image, comparison_images, similarity_threshold):
48
- # try:
49
- # if reference_image is None:
50
- # return "Please upload a reference image.", []
51
- # if not comparison_images:
52
- # return "Please upload comparison images.", []
53
-
54
- # classifier = ImageCharacterClassifier(similarity_threshold)
55
-
56
- # # Convert reference image to NumPy array
57
- # ref_image = Image.fromarray(reference_image)
58
- # ref_features = classifier.extract_features(ref_image)
59
-
60
- # results = []
61
- # html_output = "<h3>Comparison Results:</h3>"
62
-
63
- # # for comp_image in comparison_images:
64
- # # try:
65
- # # # Read image file as PIL Image
66
- # # comp_pil = Image.open(comp_image)
67
- # # comp_pil = comp_pil.convert("RGB")
68
-
69
- # # # Convert to NumPy format for SSIM
70
- # # comp_array = np.array(comp_pil)
71
-
72
-
73
- # for comp_image in comparison_images:
74
- # try:
75
- # with open(comp_image.name, "rb") as f:
76
- # comp_pil = Image.open(BytesIO(f.read()))
77
- # comp_pil = comp_pil.convert("RGB")
78
-
79
- # comp_array = np.array(comp_pil)
80
-
81
-
82
- # # Calculate SSIM score
83
- # ssim_score = classifier.calculate_ssim(reference_image, comp_array)
84
-
85
- # # Extract features
86
- # comp_features = classifier.extract_features(comp_pil)
87
- # max_feature_diff = np.max(np.abs(ref_features - comp_features))
88
- # is_similar = max_feature_diff < 6.0
89
-
90
- # status_text = "SIMILAR" if is_similar else "NOT SIMILAR"
91
- # status_color = "green" if is_similar else "red"
92
-
93
- # html_output += f"<p style='color:{status_color};'>{comp_image.name}: {status_text}</p>"
94
- # results.append(comp_array)
95
-
96
- # except Exception as e:
97
- # html_output += f"<p style='color:red;'>Error processing {comp_image.name}: {str(e)}</p>"
98
-
99
- # return html_output, results
100
-
101
- # except Exception as e:
102
- # return f"<p style='color:red;'>Error: {str(e)}</p>", []
103
-
104
- # def create_interface():
105
- # with gr.Blocks() as interface:
106
- # gr.Markdown("# Image Similarity Classifier")
107
- # gr.Markdown("Upload a reference image and multiple comparison images.")
108
-
109
- # with gr.Row():
110
- # with gr.Column():
111
- # reference_input = gr.Image(label="Reference Image", type="numpy")
112
- # comparison_input = gr.Files(label="Comparison Images", type="file")
113
- # threshold_slider = gr.Slider(minimum=0.0, maximum=1.0, value=0.5, step=0.05, label="Similarity Threshold")
114
- # submit_button = gr.Button("Compare Images")
115
-
116
- # with gr.Column():
117
- # output_html = gr.HTML(label="Results")
118
- # output_gallery = gr.Gallery(label="Processed Images", columns=3)
119
-
120
- # submit_button.click(
121
- # fn=process_images,
122
- # inputs=[reference_input, comparison_input, threshold_slider],
123
- # outputs=[output_html, output_gallery]
124
- # )
125
-
126
- # return interface
127
-
128
- # if __name__ == "__main__":
129
- # interface = create_interface()
130
- # interface.launch(share=True)
131
-
132
-
133
-
134
-
135
-
136
-
137
-
138
-
139
-
140
- # import os
141
- # os.environ["CUDA_VISIBLE_DEVICES"] = "-1"
142
-
143
-
144
- # import os
145
- # import tempfile
146
- # import numpy as np
147
- # import cv2
148
- # import gradio as gr
149
- # from tensorflow.keras.applications import ResNet50
150
- # from tensorflow.keras.applications.resnet50 import preprocess_input
151
- # from tensorflow.keras.preprocessing import image
152
- # from skimage.metrics import structural_similarity as ssim
153
- # from PIL import Image
154
- # from io import BytesIO
155
-
156
- # # Disable GPU for TensorFlow
157
- # os.environ["TF_ENABLE_ONEDNN_OPTS"] = "0"
158
- # os.environ["CUDA_VISIBLE_DEVICES"] = "-1"
159
-
160
- # # --- DOCUMENTATION STRINGS (English Only) ---
161
-
162
- # GUIDELINE_SETUP = """
163
- # ## 1. Quick Start Guide: Setup and Run Instructions
164
-
165
- # This application uses a combination of advanced feature extraction (ResNet50) and structural analysis (SSIM) to determine if comparison images are structurally and semantically similar to a reference image.
166
-
167
- # 1. **Upload Reference:** Upload the main image you want to compare against in the 'Reference Image' box.
168
- # 2. **Upload Comparisons:** Upload one or more images you want to test for similarity in the 'Comparison Images' file upload area.
169
- # 3. **Set Threshold:** Adjust the 'Similarity Threshold' slider. This primarily affects the structural (SSIM) component, but the feature comparison also plays a role (currently fixed).
170
- # 4. **Run:** Click the **"Compare Images"** button.
171
- # 5. **Review:** Results will appear in the 'Results' panel, indicating if each comparison image is "SIMILAR" or "NOT SIMILAR".
172
- # """
173
-
174
- # GUIDELINE_INPUT = """
175
- # ## 2. Expected Inputs
176
-
177
- # | Input Field | Purpose | Requirement |
178
- # | :--- | :--- | :--- |
179
- # | **Reference Image** | The baseline image against which all others will be compared. | Must be a single image file (JPG, PNG). |
180
- # | **Comparison Images** | One or more images to be tested for similarity. | Must be multiple image files. Upload them using the file selector. |
181
- # | **Similarity Threshold** | A slider controlling the sensitivity (0.0 to 1.0) for structural similarity (SSIM). | Higher values (closer to 1.0) mean stricter similarity requirements. Default is 0.5. |
182
-
183
- # **Image Preprocessing:** All uploaded images are automatically resized to 224x224 pixels and standardized according to the requirements of the ResNet model before feature extraction.
184
- # """
185
-
186
- # GUIDELINE_OUTPUT = """
187
- # ## 3. Expected Outputs (Similarity Results)
188
-
189
- # The application provides two main outputs:
190
-
191
- # 1. **Results (HTML Panel):**
192
- # * A list detailing the outcome for each comparison image.
193
- # * Status: **SIMILAR** (Green) or **NOT SIMILAR** (Red).
194
- # * Similarity is determined by a combined metric: Structural Similarity (SSIM) AND feature vector distance (ResNet features).
195
-
196
- # 2. **Processed Images (Gallery):**
197
- # * A gallery displaying the input comparison images after they have been processed.
198
-
199
- # ### How Similarity is Determined:
200
- # The classification relies on two checks:
201
- # 1. **Feature Distance:** The distance between the deep features extracted by the ResNet50 model (checking semantic content).
202
- # 2. **Structural Similarity (SSIM):** A metric comparing the structural fidelity between the reference and comparison images (checking visual layout and quality).
203
- # An image is typically marked "SIMILAR" only if both checks suggest a close match.
204
- # """
205
-
206
- # # --- CLASSIFIER CLASS ---
207
- # class ImageCharacterClassifier:
208
- # def __init__(self, similarity_threshold=0.5):
209
- # # Setting include_top=False loads the ResNet50 convolutional layers
210
- # self.model = ResNet50(weights='imagenet', include_top=False, pooling='avg')
211
- # self.similarity_threshold = similarity_threshold
212
-
213
- # def load_and_preprocess_image(self, img):
214
- # # Convert image to array and preprocess it
215
- # img = img.convert('RGB')
216
- # img_array = np.array(img)
217
- # img_array = cv2.resize(img_array, (224, 224)) # Ensure correct size
218
- # img_array = np.expand_dims(img_array, axis=0)
219
- # img_array = preprocess_input(img_array)
220
- # return img_array
221
-
222
- # def extract_features(self, img):
223
- # preprocessed_img = self.load_and_preprocess_image(img)
224
- # # Use predict_on_batch for potentially better memory usage
225
- # features = self.model.predict(preprocessed_img, verbose=0)
226
- # return features
227
-
228
- # def calculate_ssim(self, img1, img2):
229
- # # Ensure images are in numpy array format for cv2 and SSIM
230
- # img1_gray = cv2.cvtColor(img1, cv2.COLOR_RGB2GRAY)
231
- # img2_gray = cv2.cvtColor(img2, cv2.COLOR_RGB2GRAY)
232
-
233
- # # Resize comparison image to match reference image size for SSIM calculation
234
- # img2_gray = cv2.resize(img2_gray, (img1_gray.shape[1], img1_gray.shape[0]))
235
-
236
- # # Ensure data types are consistent (usually float/uint8 works)
237
- # # SSIM calculation
238
- # return ssim(img1_gray, img2_gray, data_range=img1_gray.max() - img1_gray.min())
239
-
240
- # def process_images(reference_image_array, comparison_images, similarity_threshold):
241
- # try:
242
- # if reference_image_array is None:
243
- # return "<p style='color:red;'>Please upload a reference image.</p>", []
244
- # if not comparison_images:
245
- # return "<p style='color:red;'>Please upload comparison images.</p>", []
246
-
247
- # classifier = ImageCharacterClassifier(similarity_threshold)
248
-
249
- # # 1. Process Reference Image
250
- # ref_image_pil = Image.fromarray(reference_image_array).convert("RGB")
251
- # ref_features = classifier.extract_features(ref_image_pil)
252
-
253
- # # Convert array back to RGB for SSIM comparison later
254
- # ref_image_for_ssim = cv2.cvtColor(reference_image_array, cv2.COLOR_BGR2RGB)
255
-
256
-
257
- # results = []
258
- # html_output = "<h3>Comparison Results:</h3>"
259
-
260
- # # 2. Process Comparison Images
261
- # for comp_file in comparison_images:
262
- # try:
263
- # # Open image file using PIL
264
- # with open(comp_file.name, "rb") as f:
265
- # comp_pil = Image.open(BytesIO(f.read())).convert("RGB")
266
-
267
- # comp_array = np.array(comp_pil)
268
-
269
- # # --- Similarity Checks ---
270
-
271
- # # A. SSIM Check (Structural Similarity)
272
- # ssim_score = classifier.calculate_ssim(ref_image_for_ssim, comp_array)
273
- # ssim_match = ssim_score >= similarity_threshold
274
-
275
- # # B. Feature Check (Semantic Similarity using ResNet features)
276
- # comp_features = classifier.extract_features(comp_pil)
277
-
278
- # # Using a hardcoded feature difference threshold (6.0 in original code)
279
- # max_feature_diff = np.max(np.abs(ref_features - comp_features))
280
- # feature_match = max_feature_diff < 6.0
281
-
282
- # # Combined Result
283
- # is_similar = feature_match # The original logic primarily used the feature match
284
-
285
- # # If you want to require both SSIM and Feature Match:
286
- # # is_similar = ssim_match and feature_match
287
-
288
- # status_text = f"SIMILAR (SSIM: {ssim_score:.3f})" if is_similar else f"NOT SIMILAR (SSIM: {ssim_score:.3f})"
289
- # status_color = "green" if is_similar else "red"
290
-
291
- # html_output += f"<p style='color:{status_color};'>{os.path.basename(comp_file.name)}: {status_text}</p>"
292
- # results.append(comp_array) # Add the numpy array of the comparison image
293
-
294
- # except Exception as e:
295
- # html_output += f"<p style='color:red;'>Error processing {os.path.basename(comp_file.name)}: {str(e)}</p>"
296
- # results.append(None) # Add None to keep list consistent
297
-
298
- # return html_output, [r for r in results if r is not None]
299
-
300
- # except Exception as e:
301
- # return f"<p style='color:red;'>Critical Error: {str(e)}</p>", []
302
-
303
- # def create_interface():
304
- # with gr.Blocks(title="Image Similarity Classifier") as interface:
305
-
306
- # gr.Markdown("# Image Similarity Classifier (ResNet + SSIM)")
307
- # gr.Markdown("Tool to compare a reference image against multiple comparison images based on structural and deep feature similarity.")
308
-
309
- # # 1. Guidelines Section
310
- # with gr.Accordion("Tips & Guidelines ", open=False):
311
- # gr.Markdown(GUIDELINE_SETUP)
312
- # gr.Markdown("---")
313
- # gr.Markdown(GUIDELINE_INPUT)
314
- # gr.Markdown("---")
315
- # gr.Markdown(GUIDELINE_OUTPUT)
316
-
317
- # gr.Markdown("---")
318
-
319
- # # 2. Application Interface
320
- # with gr.Row():
321
- # with gr.Column():
322
- # gr.Markdown("## Step 1: Upload a Reference Image ")
323
- # reference_input = gr.Image(label="Reference Image", type="numpy", height=300)
324
- # gr.Markdown("## Step 2: Upload Multiple Images to Compair with Reference Image ")
325
- # comparison_input = gr.Files(label="Comparison Images", type="file")
326
- # gr.Markdown("## Step 3: Set the Confidence Score (Optional) ")
327
- # threshold_slider = gr.Slider(minimum=0.0, maximum=1.0, value=0.5, step=0.05, label="Similarity Threshold (SSIM)")
328
- # gr.Markdown("## Step 4: Click Compare Images ")
329
- # submit_button = gr.Button("Compare Images", variant="primary")
330
- # gr.Markdown("# Results ")
331
- # gr.Markdown("## Comparison Result ")
332
- # output_html = gr.HTML(label="Comparison Results")
333
- # gr.Markdown("## Processed Comparison Images")
334
- # output_gallery = gr.Gallery(label="Processed Comparison Images", columns=3)
335
-
336
- # # 3. Event Handling
337
- # submit_button.click(
338
- # fn=process_images,
339
- # inputs=[reference_input, comparison_input, threshold_slider],
340
- # outputs=[output_html, output_gallery]
341
- # )
342
-
343
- # # Example data setup (Requires placeholder images to exist)
344
- # gr.Markdown("---")
345
- # gr.Markdown("## Sample Data for Testing")
346
-
347
- # # Note: You would need to provide actual file paths for reference and comparison samples
348
- # # Example setup demonstrating how to structure inputs for gr.Examples:
349
- # example_data = [
350
- # [np.zeros((100, 100, 3), dtype=np.uint8), [gr.File("sample_data/license3.jpg"), gr.File("sample_data/licence.jpeg")], 0.6], # Placeholder example
351
- # ]
352
-
353
- # # Since examples for Files/Gallery can be complex to set up without actual files,
354
- # # we will use a simple explanation here instead of a runnable Example block.
355
- # gr.Markdown("Due to the multi-file input requirement, please manually upload a reference image and several comparison images to test.")
356
-
357
-
358
- # return interface
359
-
360
- # if __name__ == "__main__":
361
- # interface = create_interface()
362
- # # Note: Using share=True might expose the app publicly if run without authorization.
363
- # interface.launch()
364
-
365
-
366
-
367
-
368
-
369
-
370
-
371
-
372
-
373
-
374
-
375
-
376
-
377
-
378
-
379
-
380
-
381
-
382
  import os
383
  import numpy as np
384
  import cv2
@@ -625,4 +244,7 @@ if __name__ == "__main__":
625
 
626
  interface = create_interface()
627
  interface.queue()
628
- interface.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import os
2
  import numpy as np
3
  import cv2
 
244
 
245
  interface = create_interface()
246
  interface.queue()
247
+ interface.launch(
248
+ server_name="0.0.0.0",
249
+ server_port=7860
250
+ )
runtime.txt DELETED
@@ -1 +0,0 @@
1
- python-3.10.13