pavansuresh commited on
Commit
d5934fb
·
verified ·
1 Parent(s): 92dbc1f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +78 -31
app.py CHANGED
@@ -12,15 +12,19 @@ import base64
12
  import io
13
  import logging
14
 
 
15
  logging.basicConfig(level=logging.INFO)
16
  logger = logging.getLogger(__name__)
17
 
 
18
  ocr_model = PaddleOCR(use_textline_orientation=True, lang='en')
19
 
20
  def analyze_uv_coverage(img, brightness_threshold=150, kernel_size=5, apply_blur=True, adaptive_thresh=False):
21
  gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
 
22
  if apply_blur:
23
  gray = cv2.GaussianBlur(gray, (5, 5), 0)
 
24
  if adaptive_thresh:
25
  binary_mask = cv2.adaptiveThreshold(
26
  gray, 255,
@@ -29,40 +33,56 @@ def analyze_uv_coverage(img, brightness_threshold=150, kernel_size=5, apply_blur
29
  11, 2)
30
  else:
31
  _, binary_mask = cv2.threshold(gray, brightness_threshold, 255, cv2.THRESH_BINARY)
 
 
32
  kernel = np.ones((kernel_size, kernel_size), np.uint8)
33
  binary_mask = cv2.morphologyEx(binary_mask, cv2.MORPH_OPEN, kernel, iterations=1)
 
 
34
  binary_mask = cv2.morphologyEx(binary_mask, cv2.MORPH_CLOSE, kernel, iterations=1)
 
35
  total_pixels = binary_mask.size
36
  sterilized_pixels = cv2.countNonZero(binary_mask)
37
  coverage_percent = (sterilized_pixels / total_pixels) * 100
 
 
38
  overlay = img.copy()
39
- overlay[binary_mask == 255] = [0, 255, 0]
40
- overlay[binary_mask == 0] = [0, 0, 255]
 
41
  annotated_img = cv2.addWeighted(img, 0.6, overlay, 0.4, 0)
 
42
  return annotated_img, coverage_percent
43
 
44
  def create_pdf_report(coverage_percent, extracted_texts, annotated_image_path, output_path):
45
  pdf = FPDF()
46
  pdf.add_page()
 
47
  pdf.set_font("Arial", 'B', 16)
48
  pdf.cell(200, 10, txt="UV Sterilization Report", ln=True, align='C')
49
  pdf.ln(10)
 
50
  pdf.set_font("Arial", size=12)
51
  pdf.cell(0, 10, f"Sterilization Coverage: {coverage_percent:.2f}%", ln=True)
52
  pdf.ln(5)
 
53
  pdf.cell(0, 10, "Extracted Text from Image (OCR):", ln=True)
54
  pdf.set_font("Arial", size=10)
55
  if extracted_texts:
56
  for text in extracted_texts:
 
57
  if len(text.strip()) > 1:
58
  pdf.multi_cell(0, 8, f"- {text}")
59
  else:
60
  pdf.cell(0, 8, "No text detected.", ln=True)
 
61
  pdf.ln(10)
62
  pdf.cell(0, 10, "Annotated Image:", ln=True)
63
  pdf.image(annotated_image_path, x=10, y=pdf.get_y(), w=pdf.w - 20)
 
64
  pdf.output(output_path)
65
 
 
66
  def upload_image_to_salesforce(image_path, image_name, record_id=None):
67
  try:
68
  sf = Salesforce(
@@ -71,19 +91,31 @@ def upload_image_to_salesforce(image_path, image_name, record_id=None):
71
  security_token=os.environ['SF_SECURITY_TOKEN'],
72
  domain=os.environ.get('SF_DOMAIN', 'login')
73
  )
 
 
 
74
  with open(image_path, "rb") as f:
75
  image_data = f.read()
 
76
  encoded_image_data = base64.b64encode(image_data).decode('utf-8')
 
 
77
  content_version_data = {
78
  "Title": image_name,
79
  "PathOnClient": image_name,
80
  "VersionData": encoded_image_data,
81
  }
 
82
  if record_id:
83
  content_version_data["FirstPublishLocationId"] = record_id
 
84
  content_version = sf.ContentVersion.create(content_version_data)
85
  content_version_id = content_version["id"]
 
 
 
86
  image_url = f"https://{sf.sf_instance}/sfc/servlet.shepherd/version/download/{content_version_id}"
 
87
  return image_url
88
  except Exception as e:
89
  logger.error(f"Error uploading image to Salesforce: {str(e)}", exc_info=True)
@@ -92,7 +124,9 @@ def upload_image_to_salesforce(image_path, image_name, record_id=None):
92
  def upload_image_and_get_url(image_path):
93
  from datetime import datetime
94
  import uuid
 
95
  unique_filename = f"{uuid.uuid4().hex}_{datetime.utcnow().strftime('%Y%m%d_%H%M%S')}.jpg"
 
96
  try:
97
  image_url = upload_image_to_salesforce(image_path, unique_filename)
98
  return image_url
@@ -105,16 +139,22 @@ def save_record_to_salesforce(annotated_image_url, coverage_percent, original_im
105
  username=os.environ['SF_USERNAME'],
106
  password=os.environ['SF_PASSWORD'],
107
  security_token=os.environ['SF_SECURITY_TOKEN'],
108
- domain=os.environ.get('SF_DOMAIN', 'login')
109
  )
 
 
110
  with tempfile.NamedTemporaryFile(delete=False, suffix=".jpg") as temp_orig_img_file:
111
  original_image_pil.save(temp_orig_img_file.name, format="JPEG")
112
  temp_orig_img_path = temp_orig_img_file.name
113
- original_image_url = upload_image_and_get_url(temp_orig_img_path)
 
114
  os.unlink(temp_orig_img_path)
 
115
  compliance_status = 'Pass' if coverage_percent >= compliance_threshold else 'Fail'
116
- technician_id = os.environ.get('SF_TECHNICIAN_ID')
 
117
  record_name = f"UV Verification - {datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S')}"
 
118
  sf.UV_Verification__c.create({
119
  'Name': record_name,
120
  'Annotated_Image__c': annotated_image_url,
@@ -125,17 +165,20 @@ def save_record_to_salesforce(annotated_image_url, coverage_percent, original_im
125
  'Verified_On__c': datetime.utcnow().isoformat()
126
  })
127
 
128
- def process_image(input_img, brightness_threshold=150):
129
- img = np.array(input_img)
130
- img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
 
131
  max_dim = 640
132
  h, w = img.shape[:2]
133
  if max(h, w) > max_dim:
134
  scale = max_dim / max(h, w)
135
  img = cv2.resize(img, (int(w * scale), int(h * scale)))
 
136
  start_time = time.time()
137
- ocr_result = ocr_model.predict(img)
138
  ocr_time = time.time() - start_time
 
139
  extracted_texts = []
140
  for line in ocr_result:
141
  if line:
@@ -143,44 +186,48 @@ def process_image(input_img, brightness_threshold=150):
143
  text = word_info[1][0].strip()
144
  if len(text) > 1:
145
  extracted_texts.append(text)
 
146
  annotated_img, coverage_percent = analyze_uv_coverage(img, brightness_threshold)
 
147
  with tempfile.NamedTemporaryFile(delete=False, suffix=".jpg") as temp_img_file:
148
  cv2.imwrite(temp_img_file.name, annotated_img)
149
  annotated_img_path = temp_img_file.name
 
150
  temp_pdf_file = tempfile.NamedTemporaryFile(delete=False, suffix=".pdf")
151
  temp_pdf_file.close()
152
  create_pdf_report(coverage_percent, extracted_texts, annotated_img_path, temp_pdf_file.name)
 
 
153
  annotated_image_url = upload_image_and_get_url(annotated_img_path)
 
 
154
  save_record_to_salesforce(annotated_image_url, coverage_percent, input_img)
155
- annotated_img_rgb = cv2.cvtColor(annotated_img, cv2.COLOR_BGR2RGB)
156
- report_text = f"UV Sterilization Coverage: {coverage_percent:.2f}%"
157
- os.unlink(annotated_img_path)
158
- return annotated_img_rgb, report_text, temp_pdf_file.name
159
 
160
- with gr.Blocks() as iface:
161
- gr.Markdown("""# UV Sterilization Coverage Analyzer
162
- Upload a post-UV sterilization image to analyze surface coverage and generate a compliance report.""")
163
 
164
- with gr.Row():
165
- image_input = gr.Image(type="pil", label="Upload Post-UV Sterilization Image")
166
- image_output = gr.Image(type="numpy", label="Annotated Image")
167
 
168
- slider = gr.Slider(50, 255, value=150, step=1, label="Brightness Threshold")
169
- report_output = gr.Textbox(label="UV Sterilization Report", lines=5)
170
- pdf_output = gr.File(label="Download PDF Report")
171
 
172
- with gr.Row():
173
- clear_btn = gr.Button("Clear")
174
- submit_btn = gr.Button("Submit", variant="primary")
175
 
176
- def reset_slider(img):
177
- return 150
178
 
179
- image_input.change(fn=reset_slider, inputs=image_input, outputs=slider)
180
- submit_btn.click(fn=process_image, inputs=[image_input, slider], outputs=[image_output, report_output, pdf_output])
181
- clear_btn.click(lambda: [None, None, 150, "", None], outputs=[image_input, image_output, slider, report_output, pdf_output])
 
 
 
 
 
 
 
 
182
 
183
- iface.queue()
184
 
185
  if __name__ == "__main__":
186
  iface.launch()
 
12
  import io
13
  import logging
14
 
15
+ # Set up logging to debug file writing issues
16
  logging.basicConfig(level=logging.INFO)
17
  logger = logging.getLogger(__name__)
18
 
19
+ # Initialize PaddleOCR once with updated parameters
20
  ocr_model = PaddleOCR(use_textline_orientation=True, lang='en')
21
 
22
  def analyze_uv_coverage(img, brightness_threshold=150, kernel_size=5, apply_blur=True, adaptive_thresh=False):
23
  gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
24
+
25
  if apply_blur:
26
  gray = cv2.GaussianBlur(gray, (5, 5), 0)
27
+
28
  if adaptive_thresh:
29
  binary_mask = cv2.adaptiveThreshold(
30
  gray, 255,
 
33
  11, 2)
34
  else:
35
  _, binary_mask = cv2.threshold(gray, brightness_threshold, 255, cv2.THRESH_BINARY)
36
+
37
+ # Morphological opening (erosion followed by dilation) to remove noise
38
  kernel = np.ones((kernel_size, kernel_size), np.uint8)
39
  binary_mask = cv2.morphologyEx(binary_mask, cv2.MORPH_OPEN, kernel, iterations=1)
40
+
41
+ # Morphological closing (dilation followed by erosion) to close small holes inside foreground
42
  binary_mask = cv2.morphologyEx(binary_mask, cv2.MORPH_CLOSE, kernel, iterations=1)
43
+
44
  total_pixels = binary_mask.size
45
  sterilized_pixels = cv2.countNonZero(binary_mask)
46
  coverage_percent = (sterilized_pixels / total_pixels) * 100
47
+
48
+ # Create overlay for visualization: Green = sterilized, Red = unsterilized
49
  overlay = img.copy()
50
+ overlay[binary_mask == 255] = [0, 255, 0] # Green
51
+ overlay[binary_mask == 0] = [0, 0, 255] # Red
52
+
53
  annotated_img = cv2.addWeighted(img, 0.6, overlay, 0.4, 0)
54
+
55
  return annotated_img, coverage_percent
56
 
57
  def create_pdf_report(coverage_percent, extracted_texts, annotated_image_path, output_path):
58
  pdf = FPDF()
59
  pdf.add_page()
60
+
61
  pdf.set_font("Arial", 'B', 16)
62
  pdf.cell(200, 10, txt="UV Sterilization Report", ln=True, align='C')
63
  pdf.ln(10)
64
+
65
  pdf.set_font("Arial", size=12)
66
  pdf.cell(0, 10, f"Sterilization Coverage: {coverage_percent:.2f}%", ln=True)
67
  pdf.ln(5)
68
+
69
  pdf.cell(0, 10, "Extracted Text from Image (OCR):", ln=True)
70
  pdf.set_font("Arial", size=10)
71
  if extracted_texts:
72
  for text in extracted_texts:
73
+ # Filter out very short or empty OCR texts to improve clarity
74
  if len(text.strip()) > 1:
75
  pdf.multi_cell(0, 8, f"- {text}")
76
  else:
77
  pdf.cell(0, 8, "No text detected.", ln=True)
78
+
79
  pdf.ln(10)
80
  pdf.cell(0, 10, "Annotated Image:", ln=True)
81
  pdf.image(annotated_image_path, x=10, y=pdf.get_y(), w=pdf.w - 20)
82
+
83
  pdf.output(output_path)
84
 
85
+ # New function to upload image to Salesforce and get URL (adapted from reference code)
86
  def upload_image_to_salesforce(image_path, image_name, record_id=None):
87
  try:
88
  sf = Salesforce(
 
91
  security_token=os.environ['SF_SECURITY_TOKEN'],
92
  domain=os.environ.get('SF_DOMAIN', 'login')
93
  )
94
+ logger.debug(f"Uploading image {image_name} for record ID: {record_id}")
95
+
96
+ # Read the image file and encode it as base64
97
  with open(image_path, "rb") as f:
98
  image_data = f.read()
99
+
100
  encoded_image_data = base64.b64encode(image_data).decode('utf-8')
101
+
102
+ # Create a ContentVersion in Salesforce
103
  content_version_data = {
104
  "Title": image_name,
105
  "PathOnClient": image_name,
106
  "VersionData": encoded_image_data,
107
  }
108
+
109
  if record_id:
110
  content_version_data["FirstPublishLocationId"] = record_id
111
+
112
  content_version = sf.ContentVersion.create(content_version_data)
113
  content_version_id = content_version["id"]
114
+ logger.info(f"Image uploaded to Salesforce with ContentVersion ID: {content_version_id}")
115
+
116
+ # Generate the public URL for the image
117
  image_url = f"https://{sf.sf_instance}/sfc/servlet.shepherd/version/download/{content_version_id}"
118
+ logger.debug(f"Generated image URL: {image_url}")
119
  return image_url
120
  except Exception as e:
121
  logger.error(f"Error uploading image to Salesforce: {str(e)}", exc_info=True)
 
124
  def upload_image_and_get_url(image_path):
125
  from datetime import datetime
126
  import uuid
127
+
128
  unique_filename = f"{uuid.uuid4().hex}_{datetime.utcnow().strftime('%Y%m%d_%H%M%S')}.jpg"
129
+
130
  try:
131
  image_url = upload_image_to_salesforce(image_path, unique_filename)
132
  return image_url
 
139
  username=os.environ['SF_USERNAME'],
140
  password=os.environ['SF_PASSWORD'],
141
  security_token=os.environ['SF_SECURITY_TOKEN'],
142
+ domain=os.environ.get('SF_DOMAIN', 'login') # 'test' for sandbox
143
  )
144
+
145
+ # Save original image temporarily, upload it, get URL
146
  with tempfile.NamedTemporaryFile(delete=False, suffix=".jpg") as temp_orig_img_file:
147
  original_image_pil.save(temp_orig_img_file.name, format="JPEG")
148
  temp_orig_img_path = temp_orig_img_file.name
149
+
150
+ original_image_url = upload_image_and_get_url(temp_orig_img_path)
151
  os.unlink(temp_orig_img_path)
152
+
153
  compliance_status = 'Pass' if coverage_percent >= compliance_threshold else 'Fail'
154
+ technician_id = os.environ.get('SF_TECHNICIAN_ID') # Salesforce UserId lookup
155
+
156
  record_name = f"UV Verification - {datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S')}"
157
+
158
  sf.UV_Verification__c.create({
159
  'Name': record_name,
160
  'Annotated_Image__c': annotated_image_url,
 
165
  'Verified_On__c': datetime.utcnow().isoformat()
166
  })
167
 
168
+ def process_image(input_img, brightness_threshold=150, slider_state=gr.State()):
169
+ img = cv2.cvtColor(np.array(input_img), cv2.COLOR_RGB2BGR)
170
+
171
+ # Resize large images for faster processing, preserving aspect ratio
172
  max_dim = 640
173
  h, w = img.shape[:2]
174
  if max(h, w) > max_dim:
175
  scale = max_dim / max(h, w)
176
  img = cv2.resize(img, (int(w * scale), int(h * scale)))
177
+
178
  start_time = time.time()
179
+ ocr_result = ocr_model.ocr(img)
180
  ocr_time = time.time() - start_time
181
+
182
  extracted_texts = []
183
  for line in ocr_result:
184
  if line:
 
186
  text = word_info[1][0].strip()
187
  if len(text) > 1:
188
  extracted_texts.append(text)
189
+
190
  annotated_img, coverage_percent = analyze_uv_coverage(img, brightness_threshold)
191
+
192
  with tempfile.NamedTemporaryFile(delete=False, suffix=".jpg") as temp_img_file:
193
  cv2.imwrite(temp_img_file.name, annotated_img)
194
  annotated_img_path = temp_img_file.name
195
+
196
  temp_pdf_file = tempfile.NamedTemporaryFile(delete=False, suffix=".pdf")
197
  temp_pdf_file.close()
198
  create_pdf_report(coverage_percent, extracted_texts, annotated_img_path, temp_pdf_file.name)
199
+
200
+ # Upload annotated image and get URL
201
  annotated_image_url = upload_image_and_get_url(annotated_img_path)
202
+
203
+ # Save record in Salesforce
204
  save_record_to_salesforce(annotated_image_url, coverage_percent, input_img)
 
 
 
 
205
 
206
+ annotated_img_rgb = cv2.cvtColor(annotated_img, cv2.COLOR_BGR2RGB)
 
 
207
 
208
+ report_text = f"UV Sterilization Coverage: {coverage_percent:.2f}%"
 
 
209
 
210
+ # Clean up temp image file after PDF generation
211
+ os.unlink(annotated_img_path)
 
212
 
213
+ # Store the current slider value for future image uploads
214
+ slider_state = brightness_threshold
 
215
 
216
+ return annotated_img_rgb, report_text, temp_pdf_file.name, slider_state
 
217
 
218
+ iface = gr.Interface(
219
+ fn=process_image,
220
+ inputs=[gr.Image(type="pil", label="Upload Post-UV Sterilization Image"),
221
+ gr.Slider(50, 255, value=150, step=1, label="Brightness Threshold", interactive=True)],
222
+ outputs=[gr.Image(type="numpy", label="Annotated Image"),
223
+ gr.Textbox(label="UV Sterilization Report", lines=5),
224
+ gr.File(label="Download PDF Report"),
225
+ gr.State()],
226
+ title="UV Sterilization Coverage Analyzer",
227
+ description="Upload a post-UV sterilization image to analyze surface coverage and generate a compliance report."
228
+ )
229
 
230
+ iface.queue() # Enable request queuing to improve UX on heavy processing
231
 
232
  if __name__ == "__main__":
233
  iface.launch()