Shuairong commited on
Commit
948e6bf
·
verified ·
1 Parent(s): f0a4cd4

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +92 -91
app.py CHANGED
@@ -1,6 +1,6 @@
1
  import os
2
  import gradio as gr
3
- from PIL import Image, ImageTk
4
  import pandas as pd
5
  from ultralytics import YOLO
6
  import easyocr
@@ -9,22 +9,27 @@ from tqdm import tqdm # For progress tracking
9
  from datetime import datetime # Import for handling dates
10
 
11
  # Initialize variables
12
- output_excel = "results.xlsx"
13
  annotations = []
14
  current_index = 0
 
 
15
  # Directories for saving original and YOLO-ed images
16
  original_dir = "original_images"
17
  yoloed_dir = "yoloed_images"
 
18
  # Ensure directories exist
19
  os.makedirs(original_dir, exist_ok=True)
20
  os.makedirs(yoloed_dir, exist_ok=True)
 
21
  # Load the trained YOLO model
22
  model_path = "best.pt"
23
  if not os.path.exists(model_path):
24
  raise FileNotFoundError(f"YOLO model not found at {model_path}. Ensure the model is in the correct location.")
25
  model = YOLO(model_path)
 
26
  # Initialize EasyOCR reader
27
  reader = easyocr.Reader(['en'])
 
28
  # Global counter for cropped image filenames
29
  global_crop_counter = 0
30
 
@@ -79,68 +84,18 @@ def perform_ocr(image):
79
  numbers = ''.join(filter(str.isdigit, ''.join(result)))
80
  return numbers.strip()
81
 
82
- # Function to load images and process them one by one
83
- def load_images_with_progress(folder_path):
84
- global annotations, current_index
85
- try:
86
- # Clear previous annotations
87
- annotations.clear()
88
- current_index = 0
89
- # Get list of images
90
- image_files = [f for f in os.listdir(folder_path) if f.lower().endswith(('.png', '.jpg', '.jpeg'))]
91
- total_images = len(image_files)
92
- # Process images one by one
93
- for i, image_file in enumerate(tqdm(image_files, desc="Processing Images")):
94
- image_path = os.path.join(folder_path, image_file)
95
- # Save the original image
96
- original_filename = os.path.basename(image_path)
97
- original_path = os.path.join(original_dir, original_filename)
98
- original_image = Image.open(image_path)
99
- original_image.save(original_path)
100
- # Detect objects using YOLO
101
- detections = detect_objects(image_path)
102
- if detections:
103
- # Crop the image using YOLO bounding boxes
104
- cropped_images = crop_image(image_path, detections)
105
- # Perform OCR on each cropped image
106
- for j, cropped_image in enumerate(cropped_images):
107
- annotation = {
108
- "image_path": image_path,
109
- "cropped_image": cropped_image,
110
- "meter_value": perform_ocr(cropped_image),
111
- "original_image": original_image,
112
- "room_number": "" # Initialize room number as empty
113
- }
114
- annotations.append(annotation)
115
- else:
116
- # If no detections, add the original image with no OCR result
117
- annotation = {
118
- "image_path": image_path,
119
- "cropped_image": None,
120
- "meter_value": "",
121
- "original_image": original_image,
122
- "room_number": "" # Initialize room number as empty
123
- }
124
- annotations.append(annotation)
125
- # Update GUI
126
- if annotations:
127
- current_index = 0
128
- return update_gui()
129
- except Exception as e:
130
- return str(e), None, None, None, None
131
-
132
  # Function to update GUI
133
  def update_gui():
134
  global current_index
135
  if not annotations:
136
- return "No images processed.", None, None, None, None
137
  annotation = annotations[current_index]
138
  # Return images and annotations
139
  original_image = annotation["original_image"]
140
  cropped_image = annotation["cropped_image"]
141
  meter_value = annotation.get("meter_value", "")
142
  room_number = annotation.get("room_number", "")
143
- return original_image, cropped_image, meter_value, room_number, ""
144
 
145
  # Function to move to the next image
146
  def next_image():
@@ -148,7 +103,7 @@ def next_image():
148
  if current_index < len(annotations) - 1:
149
  current_index += 1
150
  return update_gui()
151
- return "No more images.", None, None, None, None
152
 
153
  # Function to move to the previous image
154
  def prev_image():
@@ -156,14 +111,14 @@ def prev_image():
156
  if current_index > 0:
157
  current_index -= 1
158
  return update_gui()
159
- return "No previous images.", None, None, None, None
160
 
161
  # Function to export to Excel
162
- def export_to_excel(room_numbers, meter_values):
163
  try:
164
  # Prepare data for export
165
  data = []
166
- for room_number, meter_value in zip(room_numbers, meter_values):
167
  data.append({
168
  "room_number": room_number,
169
  "meter_value": meter_value
@@ -175,18 +130,19 @@ def export_to_excel(room_numbers, meter_values):
175
  # Create a folder with today's date
176
  today_date = datetime.now().strftime("%Y-%m-%d") # Format: YYYY-MM-DD
177
  folder_name = f"electricity_meter_values_{today_date}"
178
- os.makedirs(folder_name, exist_ok=True) # Create the folder if it doesn't exist
 
179
  # Save original images renamed to room numbers
180
- for annotation, room_number in zip(annotations, room_numbers):
181
  if room_number: # Only proceed if room number is not empty
182
  original_image_path = annotation["image_path"]
183
  original_image = Image.open(original_image_path)
184
- # Construct the new filename using the room number
185
- new_image_name = f"{room_number}.jpg" # Use room number as the filename
186
  new_image_path = os.path.join(folder_name, new_image_name)
187
- # Save the image in the new folder
188
  original_image.save(new_image_path)
 
189
  return f"Excel file and images saved successfully in '{folder_name}' folder."
 
190
  except Exception as e:
191
  return str(e)
192
 
@@ -202,33 +158,21 @@ def update_meter_value(meter_value):
202
  annotations[current_index]["meter_value"] = meter_value
203
  return meter_value
204
 
 
205
  def process_images(folder_input):
206
  global annotations, current_index
207
-
208
  if folder_input is None:
209
- # Return default values if no folder is selected
210
- return (
211
- None, # original_image_output
212
- None, # cropped_image_output
213
- None, # meter_value_output
214
- None, # room_number_output
215
- [], # room_numbers (state)
216
- [] # meter_values (state)
217
- )
218
-
219
  try:
220
- folder_path = folder_input['name'] # Extract path from folder input
221
  annotations.clear()
222
  current_index = 0
223
-
224
  image_files = [f for f in os.listdir(folder_path) if f.lower().endswith(('.png', '.jpg', '.jpeg'))]
225
  total_images = len(image_files)
226
-
227
  for i, image_file in enumerate(tqdm(image_files, desc="Processing Images")):
228
  image_path = os.path.join(folder_path, image_file)
229
  original_image = Image.open(image_path)
230
  detections = detect_objects(image_path)
231
-
232
  if detections:
233
  cropped_images = crop_image(image_path, detections)
234
  for cropped_image in cropped_images:
@@ -249,26 +193,83 @@ def process_images(folder_input):
249
  "room_number": ""
250
  }
251
  annotations.append(annotation)
252
-
253
  if annotations:
254
  current_index = 0
255
  result = update_gui()
256
  room_numbers = [a["room_number"] for a in annotations]
257
  meter_values = [a["meter_value"] for a in annotations]
258
  return (*result, room_numbers, meter_values)
 
 
 
259
 
260
- # Default return in case no annotations were created
261
- return (None, None, "", "", [], [])
 
262
 
263
- except Exception as e:
264
- # Ensure all 6 outputs are returned even on error
265
- return (
266
- f"Error: {str(e)}", # original_image_output (textual error display)
267
- None, # cropped_image_output
268
- None, # meter_value_output
269
- None, # room_number_output
270
- [], # room_numbers (state)
271
- [] # meter_values (state)
272
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
273
 
 
274
  demo.launch()
 
1
  import os
2
  import gradio as gr
3
+ from PIL import Image
4
  import pandas as pd
5
  from ultralytics import YOLO
6
  import easyocr
 
9
  from datetime import datetime # Import for handling dates
10
 
11
  # Initialize variables
 
12
  annotations = []
13
  current_index = 0
14
+ output_excel = "results.xlsx"
15
+
16
  # Directories for saving original and YOLO-ed images
17
  original_dir = "original_images"
18
  yoloed_dir = "yoloed_images"
19
+
20
  # Ensure directories exist
21
  os.makedirs(original_dir, exist_ok=True)
22
  os.makedirs(yoloed_dir, exist_ok=True)
23
+
24
  # Load the trained YOLO model
25
  model_path = "best.pt"
26
  if not os.path.exists(model_path):
27
  raise FileNotFoundError(f"YOLO model not found at {model_path}. Ensure the model is in the correct location.")
28
  model = YOLO(model_path)
29
+
30
  # Initialize EasyOCR reader
31
  reader = easyocr.Reader(['en'])
32
+
33
  # Global counter for cropped image filenames
34
  global_crop_counter = 0
35
 
 
84
  numbers = ''.join(filter(str.isdigit, ''.join(result)))
85
  return numbers.strip()
86
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
  # Function to update GUI
88
  def update_gui():
89
  global current_index
90
  if not annotations:
91
+ return "No images processed.", None, "", ""
92
  annotation = annotations[current_index]
93
  # Return images and annotations
94
  original_image = annotation["original_image"]
95
  cropped_image = annotation["cropped_image"]
96
  meter_value = annotation.get("meter_value", "")
97
  room_number = annotation.get("room_number", "")
98
+ return original_image, cropped_image, meter_value, room_number
99
 
100
  # Function to move to the next image
101
  def next_image():
 
103
  if current_index < len(annotations) - 1:
104
  current_index += 1
105
  return update_gui()
106
+ return "No more images.", None, "", ""
107
 
108
  # Function to move to the previous image
109
  def prev_image():
 
111
  if current_index > 0:
112
  current_index -= 1
113
  return update_gui()
114
+ return "No previous images.", None, "", ""
115
 
116
  # Function to export to Excel
117
+ def export_to_excel(room_numbers_state, meter_values_state):
118
  try:
119
  # Prepare data for export
120
  data = []
121
+ for room_number, meter_value in zip(room_numbers_state, meter_values_state):
122
  data.append({
123
  "room_number": room_number,
124
  "meter_value": meter_value
 
130
  # Create a folder with today's date
131
  today_date = datetime.now().strftime("%Y-%m-%d") # Format: YYYY-MM-DD
132
  folder_name = f"electricity_meter_values_{today_date}"
133
+ os.makedirs(folder_name, exist_ok=True)
134
+
135
  # Save original images renamed to room numbers
136
+ for annotation, room_number in zip(annotations, room_numbers_state):
137
  if room_number: # Only proceed if room number is not empty
138
  original_image_path = annotation["image_path"]
139
  original_image = Image.open(original_image_path)
140
+ new_image_name = f"{room_number}.jpg"
 
141
  new_image_path = os.path.join(folder_name, new_image_name)
 
142
  original_image.save(new_image_path)
143
+
144
  return f"Excel file and images saved successfully in '{folder_name}' folder."
145
+
146
  except Exception as e:
147
  return str(e)
148
 
 
158
  annotations[current_index]["meter_value"] = meter_value
159
  return meter_value
160
 
161
+ # Function to process uploaded images
162
  def process_images(folder_input):
163
  global annotations, current_index
 
164
  if folder_input is None:
165
+ return None, None, "", "", [], []
 
 
 
 
 
 
 
 
 
166
  try:
167
+ folder_path = folder_input['name'] # Get actual path
168
  annotations.clear()
169
  current_index = 0
 
170
  image_files = [f for f in os.listdir(folder_path) if f.lower().endswith(('.png', '.jpg', '.jpeg'))]
171
  total_images = len(image_files)
 
172
  for i, image_file in enumerate(tqdm(image_files, desc="Processing Images")):
173
  image_path = os.path.join(folder_path, image_file)
174
  original_image = Image.open(image_path)
175
  detections = detect_objects(image_path)
 
176
  if detections:
177
  cropped_images = crop_image(image_path, detections)
178
  for cropped_image in cropped_images:
 
193
  "room_number": ""
194
  }
195
  annotations.append(annotation)
 
196
  if annotations:
197
  current_index = 0
198
  result = update_gui()
199
  room_numbers = [a["room_number"] for a in annotations]
200
  meter_values = [a["meter_value"] for a in annotations]
201
  return (*result, room_numbers, meter_values)
202
+ return None, None, "", "", [], []
203
+ except Exception as e:
204
+ return str(e), None, "", "", [], []
205
 
206
+ # Define Gradio Interface
207
+ with gr.Blocks() as demo:
208
+ gr.Markdown("## Electricity Meter Reader")
209
 
210
+ with gr.Row():
211
+ folder_input = gr.File(label="Upload Folder", file_types=["directory"])
212
+
213
+ with gr.Row():
214
+ original_image_output = gr.Image(label="Original Image")
215
+ cropped_image_output = gr.Image(label="Cropped Meter Region")
216
+
217
+ with gr.Row():
218
+ meter_value_output = gr.Textbox(label="Meter Value", interactive=True)
219
+ room_number_output = gr.Textbox(label="Room Number", interactive=True)
220
+
221
+ with gr.Row():
222
+ prev_button = gr.Button("Previous")
223
+ next_button = gr.Button("Next")
224
+ export_button = gr.Button("Export to Excel")
225
+
226
+ # Hidden states for storing lists of room numbers and meter values
227
+ room_numbers_state = gr.State([])
228
+ meter_values_state = gr.State([])
229
+
230
+ # Actions
231
+ folder_input.change(
232
+ fn=process_images,
233
+ inputs=[folder_input],
234
+ outputs=[
235
+ original_image_output,
236
+ cropped_image_output,
237
+ meter_value_output,
238
+ room_number_output,
239
+ room_numbers_state,
240
+ meter_values_state,
241
+ ]
242
+ )
243
+
244
+ prev_button.click(
245
+ fn=prev_image,
246
+ inputs=[],
247
+ outputs=[original_image_output, cropped_image_output, meter_value_output, room_number_output]
248
+ )
249
+
250
+ next_button.click(
251
+ fn=next_image,
252
+ inputs=[],
253
+ outputs=[original_image_output, cropped_image_output, meter_value_output, room_number_output]
254
+ )
255
+
256
+ room_number_output.change(
257
+ fn=update_room_number,
258
+ inputs=[room_number_output],
259
+ outputs=[room_number_output]
260
+ )
261
+
262
+ meter_value_output.change(
263
+ fn=update_meter_value,
264
+ inputs=[meter_value_output],
265
+ outputs=[meter_value_output]
266
+ )
267
+
268
+ export_button.click(
269
+ fn=export_to_excel,
270
+ inputs=[room_numbers_state, meter_values_state],
271
+ outputs=[gr.Textbox(label="Status")]
272
+ )
273
 
274
+ # Launch the app
275
  demo.launch()