Kushalmanda commited on
Commit
462cdba
·
verified ·
1 Parent(s): e3a5b43

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +207 -208
app.py CHANGED
@@ -7,9 +7,8 @@ import datetime
7
  import logging
8
  import sys
9
  from simple_salesforce import Salesforce
10
- from decouple import config
11
 
12
- # Configure logging
13
  logging.basicConfig(
14
  level=logging.INFO,
15
  format='%(asctime)s - %(levelname)s - %(message)s',
@@ -20,14 +19,10 @@ logging.basicConfig(
20
  )
21
  logger = logging.getLogger(__name__)
22
 
23
- # Load Salesforce credentials from environment variables
24
- try:
25
- SALESFORCE_USERNAME = config('SALESFORCE_USERNAME')
26
- SALESFORCE_PASSWORD = config('SALESFORCE_PASSWORD')
27
- SALESFORCE_SECURITY_TOKEN = config('SALESFORCE_SECURITY_TOKEN')
28
- except Exception as e:
29
- logger.error(f"Failed to load environment variables: {str(e)}")
30
- raise
31
 
32
  # Initialize Salesforce connection
33
  try:
@@ -42,7 +37,7 @@ except Exception as e:
42
  logger.error(f"Failed to connect to Salesforce: {str(e)}")
43
  raise
44
 
45
- # Initialize PaddleOCR
46
  try:
47
  logger.info("Initializing PaddleOCR...")
48
  ocr = PaddleOCR(use_angle_cls=True, lang='en')
@@ -51,126 +46,146 @@ except Exception as e:
51
  logger.error(f"Failed to initialize PaddleOCR: {str(e)}")
52
  raise
53
 
 
54
  def calculate_materials_from_dimensions(wall_area, foundation_area, structure_type):
55
  logger.info(f"Calculating materials for wall_area={wall_area:.2f} m², foundation_area={foundation_area:.2f} m²")
56
- wall_materials = {
57
  "cement": 0,
58
  "bricks": 0,
59
  "steel": 0,
60
  "sand": 0,
61
- "gravel": 0
62
- }
63
- foundation_materials = {
64
- "cement": 0,
65
- "bricks": 0,
66
- "steel": 0,
67
- "sand": 0,
68
- "gravel": 0
69
- }
70
-
71
- # Material coefficients based on structure type
72
- coefficients = {
73
- "Residential": {
74
- "cement_wall": 10, "cement_foundation": 20,
75
- "brick_wall": 500, "brick_foundation": 750,
76
- "steel_wall": 2, "steel_foundation": 5,
77
- "sand_wall": 0.5, "sand_foundation": 0.8,
78
- "gravel_wall": 0.8, "gravel_foundation": 1.2
79
- },
80
- "Commercial": {
81
- "cement_wall": 12, "cement_foundation": 25,
82
- "brick_wall": 600, "brick_foundation": 900,
83
- "steel_wall": 3, "steel_foundation": 7,
84
- "sand_wall": 0.7, "sand_foundation": 1.0,
85
- "gravel_wall": 1.0, "gravel_foundation": 1.5
86
- },
87
- "Industrial": {
88
- "cement_wall": 15, "cement_foundation": 30,
89
- "brick_wall": 700, "brick_foundation": 1000,
90
- "steel_wall": 4, "steel_foundation": 8,
91
- "sand_wall": 0.9, "sand_foundation": 1.2,
92
- "gravel_wall": 1.2, "gravel_foundation": 1.8
93
- }
94
  }
95
 
96
- coeffs = coefficients.get(structure_type, coefficients["Residential"])
97
-
98
- # Wall calculations
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
  if wall_area > 0:
100
- wall_materials['cement'] = wall_area * coeffs['cement_wall']
101
- wall_materials['bricks'] = wall_area * coeffs['brick_wall']
102
- wall_materials['steel'] = wall_area * coeffs['steel_wall']
103
- wall_materials['sand'] = wall_area * coeffs['sand_wall']
104
- wall_materials['gravel'] = wall_area * coeffs['gravel_wall']
105
 
106
- # Foundation calculations
107
  if foundation_area > 0:
108
- foundation_materials['cement'] = foundation_area * coeffs['cement_foundation']
109
- foundation_materials['bricks'] = foundation_area * coeffs['brick_foundation']
110
- foundation_materials['steel'] = foundation_area * coeffs['steel_foundation']
111
- foundation_materials['sand'] = foundation_area * coeffs['sand_foundation']
112
- foundation_materials['gravel'] = foundation_area * coeffs['gravel_foundation']
113
 
114
- logger.info(f"Wall materials: {wall_materials}")
115
- logger.info(f"Foundation materials: {foundation_materials}")
116
- return wall_materials, foundation_materials
117
 
 
118
  def calculate_construction_materials(site_area, slab_thickness, wall_height):
119
  logger.info(f"Calculating construction materials for site_area={site_area:.2f} sq ft, "
120
  f"slab_thickness={slab_thickness:.2f} ft, wall_height={wall_height:.2f} ft")
121
- slab_materials = {
122
- "cement": 0,
123
- "sand": 0,
124
- "gravel": 0,
125
- "steel": 0,
126
- "bricks": 0
127
- }
128
- wall_materials = {
129
- "cement": 0,
130
- "sand": 0,
131
- "gravel": 0,
132
- "steel": 0,
133
- "bricks": 0
134
- }
135
-
136
- # Concrete mix ratio (Cement:Sand:Gravel = 1:2:4)
137
- cement_ratio, sand_ratio, gravel_ratio = 1, 2, 4
138
  total_ratio = cement_ratio + sand_ratio + gravel_ratio
 
 
139
  steel_per_cubic_ft = 1.5
140
- brick_size = 0.10 # 7.5in × 3.5in ≈ 0.10 sq ft
141
 
 
 
 
 
 
 
 
142
  try:
143
  slab_volume = site_area * slab_thickness
 
 
144
  except Exception as e:
145
- logger.error(f"Error calculating slab volume: {str(e)}")
146
  raise
147
 
148
- # Slab calculations
149
- slab_materials['cement'] = (cement_ratio / total_ratio) * slab_volume
150
- slab_materials['sand'] = (sand_ratio / total_ratio) * slab_volume
151
- slab_materials['gravel'] = (gravel_ratio / total_ratio) * slab_volume
152
- slab_materials['steel'] = steel_per_cubic_ft * slab_volume
 
 
153
 
154
- # Wall calculations (from construction perspective)
155
- wall_materials['bricks'] = (wall_height * site_area) / brick_size
156
 
157
- logger.info(f"Slab materials: {slab_materials}")
158
- logger.info(f"Construction wall materials: {wall_materials}")
159
- return slab_materials, wall_materials
160
 
 
 
 
 
 
 
 
 
 
 
 
 
161
  def process_blueprint(image, blueprint_title, uploaded_by, structure_type, site_area, slab_thickness, wall_height):
162
  logger.info("Processing blueprint image...")
163
  try:
 
164
  open_cv_image = np.array(image)
165
  open_cv_image = cv2.cvtColor(open_cv_image, cv2.COLOR_RGB2BGR)
166
  except Exception as e:
167
  logger.error(f"Error converting image to OpenCV format: {str(e)}")
168
  raise
169
 
 
170
  gray = cv2.cvtColor(open_cv_image, cv2.COLOR_BGR2GRAY)
 
 
171
  edges = cv2.Canny(gray, 50, 150, apertureSize=3)
 
 
172
  lines = cv2.HoughLinesP(edges, 1, np.pi / 180, threshold=100, minLineLength=50, maxLineGap=10)
173
 
 
174
  total_wall_length_pixels = 0
175
  if lines is not None:
176
  for line in lines:
@@ -179,165 +194,143 @@ def process_blueprint(image, blueprint_title, uploaded_by, structure_type, site_
179
  total_wall_length_pixels += length
180
  logger.info(f"Total wall length (pixels): {total_wall_length_pixels:.2f}")
181
 
 
182
  image_height, image_width = open_cv_image.shape[:2]
183
- blueprint_width_m = 27 # Fixed blueprint dimensions
184
- blueprint_height_m = 9.78
185
- pixel_to_meter = ((blueprint_width_m / image_width) + (blueprint_height_m / image_height)) / 2
 
 
 
 
186
  logger.info(f"Pixel-to-meter ratio: {pixel_to_meter:.6f}")
187
 
 
188
  total_wall_length_m = total_wall_length_pixels * pixel_to_meter
189
- wall_area = total_wall_length_m * 3 # Assume 3m wall height
190
- total_area = blueprint_width_m * blueprint_height_m
191
- foundation_area = total_area * 0.1
192
- logger.info(f"Wall area: {wall_area:.2f} m², Foundation area: {foundation_area:.2f} m²")
193
 
194
- # Calculate materials
195
- blueprint_wall_materials, foundation_materials = calculate_materials_from_dimensions(wall_area, foundation_area, structure_type)
196
- slab_materials, construction_wall_materials = calculate_construction_materials(site_area, slab_thickness, wall_height)
 
197
 
198
- cement_conversion_factor = 144 # kg per cubic foot
199
- combined_wall_materials = {
200
- 'cement': blueprint_wall_materials['cement'] + (construction_wall_materials['cement'] * cement_conversion_factor),
201
- 'sand': blueprint_wall_materials['sand'] + construction_wall_materials['sand'],
202
- 'gravel': blueprint_wall_materials['gravel'] + construction_wall_materials['gravel'],
203
- 'steel': blueprint_wall_materials['steel'] + construction_wall_materials['steel'],
204
- 'bricks': blueprint_wall_materials['bricks'] + construction_wall_materials['bricks']
205
- }
206
- combined_slab_materials = {
207
- 'cement': slab_materials['cement'] * cement_conversion_factor,
208
- 'sand': slab_materials['sand'],
209
- 'gravel': slab_materials['gravel'],
210
- 'steel': slab_materials['steel'],
211
- 'bricks': slab_materials['bricks']
212
- }
213
 
214
- logger.info(f"Combined wall materials: {combined_wall_materials}")
215
- logger.info(f"Combined slab materials: {combined_slab_materials}")
216
-
217
- # Generate Quantity JSON
218
- quantity_json = {
219
- "blueprint_id": blueprint_title,
220
- "structural_elements": [
221
- {
222
- "element_type": "wall",
223
- "dimensions": {"length_m": total_wall_length_m, "height_m": 3.0, "area_m2": wall_area},
224
- "material_quantities": {
225
- "cement_kg": combined_wall_materials['cement'],
226
- "bricks_units": combined_wall_materials['bricks'],
227
- "steel_kg": combined_wall_materials['steel'],
228
- "sand_cft": combined_wall_materials['sand'],
229
- "gravel_cft": combined_wall_materials['gravel']
230
- }
231
- },
232
- {
233
- "element_type": "slab",
234
- "dimensions": {"area_sqft": site_area, "thickness_ft": slab_thickness},
235
- "material_quantities": {
236
- "cement_kg": combined_slab_materials['cement'],
237
- "bricks_units": combined_slab_materials['bricks'],
238
- "steel_kg": combined_slab_materials['steel'],
239
- "sand_cft": combined_slab_materials['sand'],
240
- "gravel_cft": combined_slab_materials['gravel']
241
- }
242
- },
243
- {
244
- "element_type": "foundation",
245
- "dimensions": {"area_m2": foundation_area},
246
- "material_quantities": {
247
- "cement_kg": foundation_materials['cement'],
248
- "bricks_units": foundation_materials['bricks'],
249
- "steel_kg": foundation_materials['steel'],
250
- "sand_cft": foundation_materials['sand'],
251
- "gravel_cft": foundation_materials['gravel']
252
- }
253
- }
254
- ],
255
- "total_quantities": {
256
- "cement_kg": combined_wall_materials['cement'] + combined_slab_materials['cement'] + foundation_materials['cement'],
257
- "bricks_units": combined_wall_materials['bricks'] + combined_slab_materials['bricks'] + foundation_materials['bricks'],
258
- "steel_kg": combined_wall_materials['steel'] + combined_slab_materials['steel'] + foundation_materials['steel'],
259
- "sand_cft": combined_wall_materials['sand'] + combined_slab_materials['sand'] + foundation_materials['sand'],
260
- "gravel_cft": combined_wall_materials['gravel'] + combined_slab_materials['gravel'] + foundation_materials['gravel']
261
- },
262
- "estimation_accuracy": {"score": 0.95, "warnings": []}
263
  }
 
264
 
 
265
  material_summary = f"""
266
- <h3>Wall Material Requirements:</h3>
267
- <p><b>Cement:</b> {combined_wall_materials['cement']:.2f} kg</p>
268
- <p><b>Sand:</b> {combined_wall_materials['sand']:.2f} CFT</p>
269
- <p><b>Gravel:</b> {combined_wall_materials['gravel']:.2f} CFT</p>
270
- <p><b>Steel:</b> {combined_wall_materials['steel']:.2f} kg</p>
271
- <p><b>Bricks:</b> {combined_wall_materials['bricks']:.0f} units</p>
272
- <h3>Slab Material Requirements:</h3>
273
- <p><b>Cement:</b> {combined_slab_materials['cement']:.2f} kg</p>
274
- <p><b>Sand:</b> {combined_slab_materials['sand']:.2f} CFT</p>
275
- <p><b>Gravel:</b> {combined_slab_materials['gravel']:.2f} CFT</p>
276
- <p><b>Steel:</b> {combined_slab_materials['steel']:.2f} kg</p>
277
- <p><b>Bricks:</b> {combined_slab_materials['bricks']:.0f} units</p>
278
  """
279
 
 
280
  estimation_pdf_url = "https://example.com/estimation_pdfs/blueprint_123.pdf"
 
 
281
  upload_date = datetime.datetime.now().strftime("%Y-%m-%d")
 
 
282
  extracted_text = extract_text_with_paddleocr(image)
283
 
 
284
  salesforce_record = {
285
  "Blueprint_Title__c": blueprint_title,
286
- "Uploaded_By__c": uploaded_by,
287
  "Upload_Date__c": upload_date,
288
  "Structure_Type__c": structure_type,
289
- "Cement_Required_KG__c": combined_wall_materials['cement'] + combined_slab_materials['cement'] + foundation_materials['cement'],
290
- "Steel_Required_KG__c": combined_wall_materials['steel'] + combined_slab_materials['steel'] + foundation_materials['steel'],
291
- "Brick_Count__c": combined_wall_materials['bricks'] + combined_slab_materials['bricks'] + foundation_materials['bricks'],
292
- "Sand_Required_CFT__c": combined_wall_materials['sand'] + combined_slab_materials['sand'] + foundation_materials['sand'],
293
- "Material_Summary__c": material_summary,
294
- "Estimation_PDF__c": estimation_pdf_url,
295
- "Gravel__c": combined_wall_materials['gravel'] + combined_slab_materials['gravel'] + foundation_materials['gravel']
 
 
 
296
  }
 
297
 
 
298
  try:
299
- response = sf.Blueprint_Estimation__c.create(salesforce_record)
300
- logger.info(f"Salesforce record created: {response}")
301
- salesforce_record['Salesforce_Record_Id'] = response['id']
302
  except Exception as e:
303
  logger.error(f"Failed to create Salesforce record: {str(e)}")
304
  salesforce_record['Salesforce_Error'] = str(e)
305
 
306
- result = {
307
- "salesforce_record": salesforce_record,
308
- "quantity_json": quantity_json,
309
- "wall_materials": combined_wall_materials,
310
- "slab_materials": combined_slab_materials
311
- }
312
  return result, extracted_text
313
 
 
314
  def extract_text_with_paddleocr(image):
315
  logger.info("Extracting text with PaddleOCR...")
316
  try:
 
317
  open_cv_image = np.array(image)
318
  open_cv_image = cv2.cvtColor(open_cv_image, cv2.COLOR_RGB2BGR)
 
 
319
  ocr_results = ocr.ocr(open_cv_image, cls=True)
320
- extracted_text = '\n'.join([line[1][0] for line in ocr_results[0]]) if ocr_results and ocr_results[0] else "No text detected."
321
- logger.info("Text extracted successfully.")
 
 
 
 
322
  return extracted_text
323
  except Exception as e:
324
  logger.error(f"Error during OCR processing: {str(e)}")
325
  return f"OCR failed: {str(e)}"
326
 
 
327
  def gradio_process_file(image, blueprint_title, uploaded_by, structure_type, site_area, slab_thickness, wall_height):
328
  logger.info("Starting Gradio process...")
329
- if not image:
330
  logger.error("No image uploaded.")
331
  return {"error": "No image uploaded"}, None
332
 
 
333
  try:
334
- site_area = float(site_area or 1000.0)
335
- slab_thickness = float(slab_thickness or 0.5)
336
- wall_height = float(wall_height or 10.0)
 
 
 
 
 
337
  if site_area <= 0 or slab_thickness <= 0 or wall_height <= 0:
338
- raise ValueError("Site area, slab thickness, and wall height must be positive.")
339
- if not blueprint_title or not uploaded_by:
340
- raise ValueError("Blueprint title and uploaded by fields are required.")
341
  except (ValueError, TypeError) as e:
342
  logger.error(f"Invalid input: {str(e)}")
343
  return {"error": f"Invalid input: {str(e)}"}, None
@@ -350,13 +343,18 @@ def gradio_process_file(image, blueprint_title, uploaded_by, structure_type, sit
350
  logger.error(f"Gradio processing failed: {str(e)}")
351
  return {"error": str(e)}, None
352
 
 
353
  interface = gr.Interface(
354
  fn=gradio_process_file,
355
  inputs=[
356
  gr.Image(type="pil", label="Upload Blueprint Image"),
357
- gr.Textbox(label="Blueprint Title", placeholder="Enter blueprint title"),
358
- gr.Textbox(label="Uploaded By (Salesforce User ID)", placeholder="Enter Salesforce User ID"),
359
- gr.Dropdown(choices=["Residential", "Commercial", "Industrial"], label="Structure Type", value="Residential"),
 
 
 
 
360
  gr.Number(label="Site Area (sq ft)", value=1000.0, minimum=1.0),
361
  gr.Number(label="Slab Thickness (ft)", value=0.5, minimum=0.1),
362
  gr.Number(label="Wall Height (ft)", value=10.0, minimum=1.0)
@@ -366,9 +364,10 @@ interface = gr.Interface(
366
  gr.Textbox(label="Extracted Text")
367
  ],
368
  title="Blueprint Material Estimator",
369
- description="Upload a blueprint to estimate materials and save to Salesforce."
370
  )
371
 
 
372
  if __name__ == "__main__":
373
  logger.info("Launching Gradio interface...")
374
  try:
@@ -376,4 +375,4 @@ if __name__ == "__main__":
376
  logger.info("Gradio interface launched successfully.")
377
  except Exception as e:
378
  logger.error(f"Failed to launch Gradio interface: {str(e)}")
379
- sys.exit(1)
 
7
  import logging
8
  import sys
9
  from simple_salesforce import Salesforce
 
10
 
11
+ # Configure logging to capture errors and debug information
12
  logging.basicConfig(
13
  level=logging.INFO,
14
  format='%(asctime)s - %(levelname)s - %(message)s',
 
19
  )
20
  logger = logging.getLogger(__name__)
21
 
22
+ # Salesforce credentials
23
+ SALESFORCE_USERNAME = "[email protected]"
24
+ SALESFORCE_PASSWORD = "Vijaya@1888"
25
+ SALESFORCE_SECURITY_TOKEN = "LfxlLZssa4Bp9vTSd0B78Cyu"
 
 
 
 
26
 
27
  # Initialize Salesforce connection
28
  try:
 
37
  logger.error(f"Failed to connect to Salesforce: {str(e)}")
38
  raise
39
 
40
+ # Initialize PaddleOCR with error handling
41
  try:
42
  logger.info("Initializing PaddleOCR...")
43
  ocr = PaddleOCR(use_angle_cls=True, lang='en')
 
46
  logger.error(f"Failed to initialize PaddleOCR: {str(e)}")
47
  raise
48
 
49
+ # Function to calculate materials based on blueprint dimensions (wall and foundation)
50
  def calculate_materials_from_dimensions(wall_area, foundation_area, structure_type):
51
  logger.info(f"Calculating materials for wall_area={wall_area:.2f} m², foundation_area={foundation_area:.2f} m²")
52
+ materials = {
53
  "cement": 0,
54
  "bricks": 0,
55
  "steel": 0,
56
  "sand": 0,
57
+ "gravel": 0,
58
+ "tiles": 0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  }
60
 
61
+ # Adjust material coefficients based on structure type
62
+ if structure_type == "Residential":
63
+ cement_factor_wall = 10 # kg/m²
64
+ cement_factor_foundation = 20
65
+ brick_factor_wall = 500
66
+ brick_factor_foundation = 750
67
+ steel_factor_wall = 2
68
+ steel_factor_foundation = 5
69
+ sand_factor_wall = 0.5
70
+ sand_factor_foundation = 0.8
71
+ gravel_factor_wall = 0.8
72
+ gravel_factor_foundation = 1.2
73
+ elif structure_type == "Commercial":
74
+ cement_factor_wall = 12
75
+ cement_factor_foundation = 25
76
+ brick_factor_wall = 600
77
+ brick_factor_foundation = 900
78
+ steel_factor_wall = 3
79
+ steel_factor_foundation = 7
80
+ sand_factor_wall = 0.7
81
+ sand_factor_foundation = 1.0
82
+ gravel_factor_wall = 1.0
83
+ gravel_factor_foundation = 1.5
84
+ else: # Industrial
85
+ cement_factor_wall = 15
86
+ cement_factor_foundation = 30
87
+ brick_factor_wall = 700
88
+ brick_factor_foundation = 1000
89
+ steel_factor_wall = 4
90
+ steel_factor_foundation = 8
91
+ sand_factor_wall = 0.9
92
+ sand_factor_foundation = 1.2
93
+ gravel_factor_wall = 1.2
94
+ gravel_factor_foundation = 1.8
95
+
96
+ # Wall calculations (in m²)
97
  if wall_area > 0:
98
+ materials['cement'] += wall_area * cement_factor_wall
99
+ materials['bricks'] += wall_area * brick_factor_wall
100
+ materials['steel'] += wall_area * steel_factor_wall
101
+ materials['sand'] += wall_area * sand_factor_wall
102
+ materials['gravel'] += wall_area * gravel_factor_wall
103
 
104
+ # Foundation calculations (in m²)
105
  if foundation_area > 0:
106
+ materials['cement'] += foundation_area * cement_factor_foundation
107
+ materials['bricks'] += foundation_area * brick_factor_foundation
108
+ materials['steel'] += foundation_area * steel_factor_foundation
109
+ materials['sand'] += foundation_area * sand_factor_foundation
110
+ materials['gravel'] += foundation_area * gravel_factor_foundation
111
 
112
+ logger.info(f"Blueprint materials calculated: {materials}")
113
+ return materials
 
114
 
115
+ # Function to calculate materials based on site area, slab thickness, and wall height
116
  def calculate_construction_materials(site_area, slab_thickness, wall_height):
117
  logger.info(f"Calculating construction materials for site_area={site_area:.2f} sq ft, "
118
  f"slab_thickness={slab_thickness:.2f} ft, wall_height={wall_height:.2f} ft")
119
+ # Concrete Mix Ratio (Cement: Sand: Gravel)
120
+ cement_ratio = 1
121
+ sand_ratio = 2
122
+ gravel_ratio = 4
 
 
 
 
 
 
 
 
 
 
 
 
 
123
  total_ratio = cement_ratio + sand_ratio + gravel_ratio
124
+
125
+ # Steel estimation (kg per cubic foot of concrete)
126
  steel_per_cubic_ft = 1.5
 
127
 
128
+ # Brick size (in square feet per brick)
129
+ brick_size = 0.10 # 7.5 inches × 3.5 inches (approx 0.10 sq ft per brick)
130
+
131
+ # Tile size (in square feet per tile)
132
+ tile_size = 1 # 1x1 foot tiles
133
+
134
+ # Concrete Calculation
135
  try:
136
  slab_volume = site_area * slab_thickness
137
+ foundation_volume = site_area * slab_thickness * 3
138
+ total_concrete_volume = slab_volume + foundation_volume
139
  except Exception as e:
140
+ logger.error(f"Error calculating concrete volume: {str(e)}")
141
  raise
142
 
143
+ # Materials for Concrete Mix
144
+ cement_needed = (cement_ratio / total_ratio) * total_concrete_volume # in cubic feet
145
+ sand_needed = (sand_ratio / total_ratio) * total_concrete_volume
146
+ gravel_needed = (gravel_ratio / total_ratio) * total_concrete_volume
147
+
148
+ # Steel Bars Calculation
149
+ steel_needed = steel_per_cubic_ft * total_concrete_volume
150
 
151
+ # Bricks Calculation
152
+ bricks_needed = (wall_height * site_area) / brick_size
153
 
154
+ # Tiles Calculation
155
+ tiles_needed = site_area / tile_size
 
156
 
157
+ materials = {
158
+ 'cement': cement_needed, # in cubic feet (will convert to kg for Salesforce)
159
+ 'sand': sand_needed,
160
+ 'gravel': gravel_needed,
161
+ 'steel': steel_needed,
162
+ 'bricks': bricks_needed,
163
+ 'tiles': tiles_needed
164
+ }
165
+ logger.info(f"Construction materials calculated: {materials}")
166
+ return materials
167
+
168
+ # Function to process the blueprint and extract dimensions
169
  def process_blueprint(image, blueprint_title, uploaded_by, structure_type, site_area, slab_thickness, wall_height):
170
  logger.info("Processing blueprint image...")
171
  try:
172
+ # Convert PIL image to OpenCV format
173
  open_cv_image = np.array(image)
174
  open_cv_image = cv2.cvtColor(open_cv_image, cv2.COLOR_RGB2BGR)
175
  except Exception as e:
176
  logger.error(f"Error converting image to OpenCV format: {str(e)}")
177
  raise
178
 
179
+ # Convert to grayscale for easier processing
180
  gray = cv2.cvtColor(open_cv_image, cv2.COLOR_BGR2GRAY)
181
+
182
+ # Apply edge detection to find lines (walls)
183
  edges = cv2.Canny(gray, 50, 150, apertureSize=3)
184
+
185
+ # Use Hough Transform to detect lines (walls)
186
  lines = cv2.HoughLinesP(edges, 1, np.pi / 180, threshold=100, minLineLength=50, maxLineGap=10)
187
 
188
+ # Calculate total wall length (in pixels)
189
  total_wall_length_pixels = 0
190
  if lines is not None:
191
  for line in lines:
 
194
  total_wall_length_pixels += length
195
  logger.info(f"Total wall length (pixels): {total_wall_length_pixels:.2f}")
196
 
197
+ # From the blueprint, we know the dimensions (27 m × 9.78 m)
198
  image_height, image_width = open_cv_image.shape[:2]
199
+ blueprint_width_m = 27 # From the blueprint (27 m)
200
+ blueprint_height_m = 9.78 # From the blueprint (9.78 m)
201
+
202
+ # Calculate pixel-to-meter ratio
203
+ pixel_to_meter_width = blueprint_width_m / image_width
204
+ pixel_to_meter_height = blueprint_height_m / image_height
205
+ pixel_to_meter = (pixel_to_meter_width + pixel_to_meter_height) / 2
206
  logger.info(f"Pixel-to-meter ratio: {pixel_to_meter:.6f}")
207
 
208
+ # Convert wall length to meters
209
  total_wall_length_m = total_wall_length_pixels * pixel_to_meter
210
+ logger.info(f"Total wall length (meters): {total_wall_length_m:.2f}")
 
 
 
211
 
212
+ # Estimate wall area (assume wall height of 3 m for simplicity)
213
+ wall_height_m = 3 # Standard room height
214
+ wall_area = total_wall_length_m * wall_height_m
215
+ logger.info(f"Wall area: {wall_area:.2f} m²")
216
 
217
+ # Estimate foundation area (based on the blueprint's total area)
218
+ total_area = blueprint_width_m * blueprint_height_m # 27 m × 9.78 m
219
+ foundation_area = total_area * 0.1 # Assume 10% of the total area is foundation
220
+ logger.info(f"Foundation area: {foundation_area:.2f} m²")
221
+
222
+ # Calculate materials based on blueprint dimensions
223
+ blueprint_materials = calculate_materials_from_dimensions(wall_area, foundation_area, structure_type)
 
 
 
 
 
 
 
 
224
 
225
+ # Calculate construction materials based on site area, slab thickness, and wall height
226
+ construction_materials = calculate_construction_materials(site_area, slab_thickness, wall_height)
227
+
228
+ # Combine materials from both calculations
229
+ # Convert cement from cubic feet to kg for Salesforce (1 cubic foot ≈ 144 kg for cement)
230
+ cement_conversion_factor = 144 # kg per cubic foot
231
+ combined_materials = {
232
+ 'cement': (blueprint_materials['cement'] + (construction_materials['cement'] * cement_conversion_factor)), # in kg
233
+ 'sand': blueprint_materials['sand'] + construction_materials['sand'], # in CFT
234
+ 'gravel': blueprint_materials['gravel'] + construction_materials['gravel'], # in CFT
235
+ 'steel': blueprint_materials['steel'] + construction_materials['steel'], # in kg
236
+ 'bricks': blueprint_materials['bricks'] + construction_materials['bricks'], # units
237
+ 'tiles': construction_materials['tiles'] # units
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
238
  }
239
+ logger.info(f"Combined materials: {combined_materials}")
240
 
241
+ # Generate Material_Summary__c in HTML format (for display)
242
  material_summary = f"""
243
+ <h3>Construction Material Requirements:</h3>
244
+ <p><b>Cement:</b> {combined_materials['cement']:.2f} kg</p>
245
+ <p><b>Sand:</b> {combined_materials['sand']:.2f} CFT</p>
246
+ <p><b>Gravel:</b> {combined_materials['gravel']:.2f} CFT</p>
247
+ <p><b>Steel:</b> {combined_materials['steel']:.2f} kg</p>
248
+ <p><b>Bricks:</b> {combined_materials['bricks']:.0f} units</p>
249
+ <p><b>Tiles:</b> {combined_materials['tiles']:.0f} units</p>
 
 
 
 
 
250
  """
251
 
252
+ # Simulate Estimation_PDF__c as a placeholder URL
253
  estimation_pdf_url = "https://example.com/estimation_pdfs/blueprint_123.pdf"
254
+
255
+ # Current date for Upload_Date__c
256
  upload_date = datetime.datetime.now().strftime("%Y-%m-%d")
257
+
258
+ # Extract text from the image using PaddleOCR
259
  extracted_text = extract_text_with_paddleocr(image)
260
 
261
+ # Map fields to Salesforce record for Blue_print_Estimation__c
262
  salesforce_record = {
263
  "Blueprint_Title__c": blueprint_title,
264
+ "Uploaded_By__c": uploaded_by, # Assumes a valid User ID
265
  "Upload_Date__c": upload_date,
266
  "Structure_Type__c": structure_type,
267
+ "Cement_Required_KG__c": combined_materials['cement'], # Already in kg
268
+ "Steel_Required_KG__c": combined_materials['steel'], # Already in kg
269
+ "Brick_Count__c": combined_materials['bricks'], # Units
270
+ "Sand__c": combined_materials['sand'], # CFT
271
+ "Sand_Required_CFT__c": combined_materials['sand'], # CFT (same as Sand__c)
272
+ "Material_Summary__c": material_summary, # HTML formatted
273
+ "Estimation_PDF__c": estimation_pdf_url, # URL
274
+ "Gravel__c": combined_materials['gravel'], # CFT
275
+ "Tiles__c": combined_materials['tiles'] # Units
276
+ # Note: User__c is not mapped as it's assumed to be the same as Uploaded_By__c
277
  }
278
+ logger.info(f"Salesforce record prepared: {salesforce_record}")
279
 
280
+ # Create the record in Salesforce (using Blue_print_Estimation__c)
281
  try:
282
+ response = sf.Blue_print_Estimation__c.create(salesforce_record)
283
+ logger.info(f"Salesforce record created successfully: {response}")
284
+ salesforce_record['Salesforce_Record_Id'] = response['id'] # Add the record ID to the result
285
  except Exception as e:
286
  logger.error(f"Failed to create Salesforce record: {str(e)}")
287
  salesforce_record['Salesforce_Error'] = str(e)
288
 
289
+ # Populate the fields in a structured dictionary for return
290
+ result = salesforce_record
291
+ logger.info("Blueprint processing completed successfully.")
 
 
 
292
  return result, extracted_text
293
 
294
+ # Function to extract text using PaddleOCR
295
  def extract_text_with_paddleocr(image):
296
  logger.info("Extracting text with PaddleOCR...")
297
  try:
298
+ # Convert PIL image to OpenCV format
299
  open_cv_image = np.array(image)
300
  open_cv_image = cv2.cvtColor(open_cv_image, cv2.COLOR_RGB2BGR)
301
+
302
+ # Perform OCR using PaddleOCR
303
  ocr_results = ocr.ocr(open_cv_image, cls=True)
304
+ if ocr_results and ocr_results[0]:
305
+ extracted_text = '\n'.join([line[1][0] for line in ocr_results[0]])
306
+ logger.info("Text extracted successfully.")
307
+ else:
308
+ extracted_text = "No text detected."
309
+ logger.info("No text detected in the image.")
310
  return extracted_text
311
  except Exception as e:
312
  logger.error(f"Error during OCR processing: {str(e)}")
313
  return f"OCR failed: {str(e)}"
314
 
315
+ # Wrapper function for Gradio to handle image input and additional fields
316
  def gradio_process_file(image, blueprint_title, uploaded_by, structure_type, site_area, slab_thickness, wall_height):
317
  logger.info("Starting Gradio process...")
318
+ if image is None:
319
  logger.error("No image uploaded.")
320
  return {"error": "No image uploaded"}, None
321
 
322
+ # Provide default values and validate numerical inputs
323
  try:
324
+ # Check for None and provide defaults
325
+ site_area = float(site_area) if site_area is not None else 1000.0
326
+ slab_thickness = float(slab_thickness) if slab_thickness is not None else 0.5
327
+ wall_height = float(wall_height) if wall_height is not None else 10.0
328
+
329
+ logger.info(f"Input values - site_area: {site_area}, slab_thickness: {slab_thickness}, wall_height: {wall_height}")
330
+
331
+ # Validate that values are positive
332
  if site_area <= 0 or slab_thickness <= 0 or wall_height <= 0:
333
+ raise ValueError("Site area, slab thickness, and wall height must be positive numbers.")
 
 
334
  except (ValueError, TypeError) as e:
335
  logger.error(f"Invalid input: {str(e)}")
336
  return {"error": f"Invalid input: {str(e)}"}, None
 
343
  logger.error(f"Gradio processing failed: {str(e)}")
344
  return {"error": str(e)}, None
345
 
346
+ # Set up a single Gradio interface for image input with additional fields
347
  interface = gr.Interface(
348
  fn=gradio_process_file,
349
  inputs=[
350
  gr.Image(type="pil", label="Upload Blueprint Image"),
351
+ gr.Textbox(label="Blueprint Title", placeholder="Enter the blueprint title"),
352
+ gr.Textbox(label="Uploaded By (Salesforce User ID)", placeholder="Enter the Salesforce User ID (e.g., 005xxxxxxxxxxxx)"),
353
+ gr.Dropdown(
354
+ choices=["Residential", "Commercial", "Industrial"],
355
+ label="Structure Type",
356
+ value="Residential"
357
+ ),
358
  gr.Number(label="Site Area (sq ft)", value=1000.0, minimum=1.0),
359
  gr.Number(label="Slab Thickness (ft)", value=0.5, minimum=0.1),
360
  gr.Number(label="Wall Height (ft)", value=10.0, minimum=1.0)
 
364
  gr.Textbox(label="Extracted Text")
365
  ],
366
  title="Blueprint Material Estimator",
367
+ description="Upload a blueprint image to estimate construction materials and save to Salesforce (Blue_print_Estimation__c)."
368
  )
369
 
370
+ # Launch the interface
371
  if __name__ == "__main__":
372
  logger.info("Launching Gradio interface...")
373
  try:
 
375
  logger.info("Gradio interface launched successfully.")
376
  except Exception as e:
377
  logger.error(f"Failed to launch Gradio interface: {str(e)}")
378
+ sys.exit(1)