AI-Solutions-KK commited on
Commit
8db7fa6
·
unverified ·
1 Parent(s): 7e9d5f5

Update app.py

Browse files

removed open cv version

Files changed (1) hide show
  1. app.py +95 -69
app.py CHANGED
@@ -1,11 +1,13 @@
1
  import streamlit as st
2
- import cv2
3
  import numpy as np
4
- from PIL import Image
5
  import easyocr
6
  import pandas as pd
7
  from io import BytesIO
8
  import json
 
 
 
9
 
10
  # Configure page
11
  st.set_page_config(
@@ -20,62 +22,78 @@ def load_ocr_reader():
20
  return easyocr.Reader(['en'])
21
 
22
  def preprocess_image(image):
23
- """Basic image preprocessing"""
24
- # Convert to grayscale
25
- gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
 
 
 
26
 
27
- # Apply Gaussian blur to reduce noise
28
- blurred = cv2.GaussianBlur(gray, (5, 5), 0)
29
 
30
- # Apply adaptive threshold
31
- thresh = cv2.adaptiveThreshold(
32
- blurred, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
33
- cv2.THRESH_BINARY, 11, 2
34
- )
 
 
35
 
36
- return thresh, gray
37
 
38
  def detect_shapes(image):
39
- """Detect basic shapes in the image"""
40
  shapes_detected = []
41
 
42
- # Find contours
43
- contours, _ = cv2.findContours(image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
 
 
 
 
 
 
 
 
44
 
45
- for i, contour in enumerate(contours):
46
- # Filter small contours
47
- area = cv2.contourArea(contour)
48
- if area < 500: # Minimum area threshold
49
  continue
50
-
51
- # Get bounding rectangle
52
- x, y, w, h = cv2.boundingRect(contour)
53
 
54
- # Approximate contour to polygon
55
- epsilon = 0.02 * cv2.arcLength(contour, True)
56
- approx = cv2.approxPolyDP(contour, epsilon, True)
 
 
 
 
57
 
58
- # Classify shape based on number of vertices
 
 
 
 
 
 
 
 
59
  shape_type = "Unknown"
60
- vertices = len(approx)
61
 
62
- if vertices == 3:
63
- shape_type = "Triangle"
64
- elif vertices == 4:
65
- # Check if rectangle or square
66
- aspect_ratio = w / float(h)
67
- if 0.95 <= aspect_ratio <= 1.05:
68
- shape_type = "Square"
69
- else:
70
- shape_type = "Rectangle"
71
- elif vertices > 4:
72
- # Check if circle/ellipse
73
- area_contour = cv2.contourArea(contour)
74
- area_rect = w * h
75
- if area_contour / area_rect > 0.7:
76
- shape_type = "Circle/Ellipse"
77
- else:
78
- shape_type = "Polygon"
79
 
80
  shapes_detected.append({
81
  'id': i,
@@ -87,7 +105,9 @@ def detect_shapes(image):
87
  'width': int(w),
88
  'height': int(h),
89
  'center_x': int(x + w/2),
90
- 'center_y': int(y + h/2)
 
 
91
  })
92
 
93
  return shapes_detected
@@ -102,10 +122,11 @@ def detect_text_in_shapes(image_gray, shapes, ocr_reader):
102
 
103
  # Add padding
104
  padding = 10
 
105
  x_start = max(0, x - padding)
106
  y_start = max(0, y - padding)
107
- x_end = min(image_gray.shape[1], x + w + padding)
108
- y_end = min(image_gray.shape[0], y + h + padding)
109
 
110
  roi = image_gray[y_start:y_end, x_start:x_end]
111
 
@@ -146,8 +167,17 @@ def detect_text_in_shapes(image_gray, shapes, ocr_reader):
146
  return text_results
147
 
148
  def draw_detection_results(original_image, shapes, texts):
149
- """Draw bounding boxes and text on the image"""
150
- result_image = original_image.copy()
 
 
 
 
 
 
 
 
 
151
 
152
  # Create text lookup
153
  text_lookup = {text['shape_id']: text for text in texts}
@@ -156,18 +186,18 @@ def draw_detection_results(original_image, shapes, texts):
156
  x, y, w, h = shape['x'], shape['y'], shape['width'], shape['height']
157
 
158
  # Draw bounding rectangle
159
- cv2.rectangle(result_image, (x, y), (x + w, y + h), (0, 255, 0), 2)
160
 
161
  # Add shape type label
162
  label = f"{shape['type']} (ID: {shape['id']})"
163
- cv2.putText(result_image, label, (x, y - 10),
164
- cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1)
165
 
166
  # Add detected text if any
167
  if shape['id'] in text_lookup and text_lookup[shape['id']]['text']:
168
- text = text_lookup[shape['id']]['text'][:20] + "..." if len(text_lookup[shape['id']]['text']) > 20 else text_lookup[shape['id']]['text']
169
- cv2.putText(result_image, f"Text: {text}", (x, y + h + 20),
170
- cv2.FONT_HERSHEY_SIMPLEX, 0.4, (255, 0, 0), 1)
 
171
 
172
  return result_image
173
 
@@ -213,12 +243,6 @@ def main():
213
  if uploaded_file is not None:
214
  # Load and display original image
215
  image = Image.open(uploaded_file)
216
- image_np = np.array(image)
217
-
218
- if len(image_np.shape) == 3:
219
- image_cv = cv2.cvtColor(image_np, cv2.COLOR_RGB2BGR)
220
- else:
221
- image_cv = image_np
222
 
223
  col1, col2 = st.columns(2)
224
 
@@ -231,7 +255,7 @@ def main():
231
  reader = load_ocr_reader()
232
 
233
  # Preprocess image
234
- processed_img, gray_img = preprocess_image(image_cv)
235
 
236
  # Detect shapes
237
  shapes = detect_shapes(processed_img)
@@ -248,9 +272,8 @@ def main():
248
  with col2:
249
  st.subheader("Detection Results")
250
  if shapes:
251
- result_img = draw_detection_results(image_cv, shapes, texts)
252
- result_img_rgb = cv2.cvtColor(result_img, cv2.COLOR_BGR2RGB)
253
- st.image(result_img_rgb, use_container_width=True)
254
  else:
255
  st.warning("No shapes detected. Try adjusting the minimum area threshold.")
256
 
@@ -313,8 +336,11 @@ def main():
313
  st.metric("Shapes with Text", shapes_with_text)
314
 
315
  with col3:
316
- avg_confidence = np.mean([text['confidence'] for text in texts if text['confidence'] > 0])
317
- st.metric("Avg Text Confidence", f"{avg_confidence:.2f}" if not np.isnan(avg_confidence) else "0.00")
 
 
 
318
 
319
  with col4:
320
  shape_types = len(set(shape['type'] for shape in shapes))
@@ -342,4 +368,4 @@ def main():
342
  """)
343
 
344
  if __name__ == "__main__":
345
- main()
 
1
  import streamlit as st
 
2
  import numpy as np
3
+ from PIL import Image, ImageDraw, ImageFilter, ImageEnhance
4
  import easyocr
5
  import pandas as pd
6
  from io import BytesIO
7
  import json
8
+ from scipy import ndimage
9
+ from skimage import measure, morphology, filters
10
+ from skimage.segmentation import clear_border
11
 
12
  # Configure page
13
  st.set_page_config(
 
22
  return easyocr.Reader(['en'])
23
 
24
  def preprocess_image(image):
25
+ """Basic image preprocessing using PIL and skimage"""
26
+ # Convert PIL to grayscale
27
+ if image.mode != 'L':
28
+ gray = image.convert('L')
29
+ else:
30
+ gray = image
31
 
32
+ # Convert to numpy array
33
+ gray_array = np.array(gray)
34
 
35
+ # Apply Gaussian blur using scipy
36
+ blurred = ndimage.gaussian_filter(gray_array, sigma=1.0)
37
+
38
+ # Apply threshold using skimage
39
+ thresh_val = filters.threshold_otsu(blurred)
40
+ thresh = blurred > thresh_val
41
+ thresh = thresh.astype(np.uint8) * 255
42
 
43
+ return thresh, gray_array
44
 
45
  def detect_shapes(image):
46
+ """Detect basic shapes using skimage"""
47
  shapes_detected = []
48
 
49
+ # Convert to binary
50
+ binary = image < 128 # Invert for skimage
51
+
52
+ # Remove noise
53
+ cleaned = morphology.remove_small_objects(binary, min_size=500)
54
+ cleaned = clear_border(cleaned)
55
+
56
+ # Label connected components
57
+ labeled = measure.label(cleaned)
58
+ regions = measure.regionprops(labeled)
59
 
60
+ for i, region in enumerate(regions):
61
+ # Filter small areas
62
+ if region.area < 500:
 
63
  continue
 
 
 
64
 
65
+ # Get bounding box
66
+ minr, minc, maxr, maxc = region.bbox
67
+ y, x, h, w = minr, minc, maxr - minr, maxc - minc
68
+
69
+ # Get shape characteristics
70
+ perimeter = region.perimeter
71
+ area = region.area
72
 
73
+ # Calculate shape metrics
74
+ if perimeter > 0:
75
+ circularity = 4 * np.pi * area / (perimeter * perimeter)
76
+ aspect_ratio = region.major_axis_length / region.minor_axis_length if region.minor_axis_length > 0 else 1
77
+ else:
78
+ circularity = 0
79
+ aspect_ratio = 1
80
+
81
+ # Classify shape
82
  shape_type = "Unknown"
 
83
 
84
+ if circularity > 0.7:
85
+ shape_type = "Circle"
86
+ elif aspect_ratio < 1.2:
87
+ shape_type = "Square"
88
+ elif aspect_ratio < 3.0:
89
+ shape_type = "Rectangle"
90
+ else:
91
+ shape_type = "Elongated Shape"
92
+
93
+ # Calculate vertices (approximation)
94
+ vertices = 4 # Default for most flowchart shapes
95
+ if circularity > 0.7:
96
+ vertices = 0 # Circle
 
 
 
 
97
 
98
  shapes_detected.append({
99
  'id': i,
 
105
  'width': int(w),
106
  'height': int(h),
107
  'center_x': int(x + w/2),
108
+ 'center_y': int(y + h/2),
109
+ 'circularity': round(circularity, 2),
110
+ 'aspect_ratio': round(aspect_ratio, 2)
111
  })
112
 
113
  return shapes_detected
 
122
 
123
  # Add padding
124
  padding = 10
125
+ img_height, img_width = image_gray.shape
126
  x_start = max(0, x - padding)
127
  y_start = max(0, y - padding)
128
+ x_end = min(img_width, x + w + padding)
129
+ y_end = min(img_height, y + h + padding)
130
 
131
  roi = image_gray[y_start:y_end, x_start:x_end]
132
 
 
167
  return text_results
168
 
169
  def draw_detection_results(original_image, shapes, texts):
170
+ """Draw bounding boxes and text on the image using PIL"""
171
+ # Convert numpy array to PIL Image if needed
172
+ if isinstance(original_image, np.ndarray):
173
+ if len(original_image.shape) == 3:
174
+ result_image = Image.fromarray(original_image, 'RGB')
175
+ else:
176
+ result_image = Image.fromarray(original_image, 'L').convert('RGB')
177
+ else:
178
+ result_image = original_image.convert('RGB')
179
+
180
+ draw = ImageDraw.Draw(result_image)
181
 
182
  # Create text lookup
183
  text_lookup = {text['shape_id']: text for text in texts}
 
186
  x, y, w, h = shape['x'], shape['y'], shape['width'], shape['height']
187
 
188
  # Draw bounding rectangle
189
+ draw.rectangle([x, y, x + w, y + h], outline='green', width=2)
190
 
191
  # Add shape type label
192
  label = f"{shape['type']} (ID: {shape['id']})"
193
+ draw.text((x, y - 15), label, fill='green')
 
194
 
195
  # Add detected text if any
196
  if shape['id'] in text_lookup and text_lookup[shape['id']]['text']:
197
+ text = text_lookup[shape['id']]['text']
198
+ if len(text) > 20:
199
+ text = text[:20] + "..."
200
+ draw.text((x, y + h + 5), f"Text: {text}", fill='red')
201
 
202
  return result_image
203
 
 
243
  if uploaded_file is not None:
244
  # Load and display original image
245
  image = Image.open(uploaded_file)
 
 
 
 
 
 
246
 
247
  col1, col2 = st.columns(2)
248
 
 
255
  reader = load_ocr_reader()
256
 
257
  # Preprocess image
258
+ processed_img, gray_img = preprocess_image(image)
259
 
260
  # Detect shapes
261
  shapes = detect_shapes(processed_img)
 
272
  with col2:
273
  st.subheader("Detection Results")
274
  if shapes:
275
+ result_img = draw_detection_results(image, shapes, texts)
276
+ st.image(result_img, use_container_width=True)
 
277
  else:
278
  st.warning("No shapes detected. Try adjusting the minimum area threshold.")
279
 
 
336
  st.metric("Shapes with Text", shapes_with_text)
337
 
338
  with col3:
339
+ if texts and any(text['confidence'] > 0 for text in texts):
340
+ avg_confidence = np.mean([text['confidence'] for text in texts if text['confidence'] > 0])
341
+ st.metric("Avg Text Confidence", f"{avg_confidence:.2f}")
342
+ else:
343
+ st.metric("Avg Text Confidence", "0.00")
344
 
345
  with col4:
346
  shape_types = len(set(shape['type'] for shape in shapes))
 
368
  """)
369
 
370
  if __name__ == "__main__":
371
+ main()