Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
|
@@ -31,8 +31,8 @@ except Exception as e:
|
|
| 31 |
print(f"Salesforce connection failed: {str(e)}")
|
| 32 |
raise
|
| 33 |
|
| 34 |
-
# Valid milestones
|
| 35 |
-
VALID_MILESTONES = ["Planning", "Foundation", "Walls Erected", "
|
| 36 |
|
| 37 |
# Adjust the timezone to your local timezone
|
| 38 |
local_timezone = pytz.timezone("Asia/Kolkata")
|
|
@@ -45,22 +45,31 @@ def process_image(images, project_name):
|
|
| 45 |
|
| 46 |
milestones = []
|
| 47 |
for image in images:
|
| 48 |
-
img = Image.open(image)
|
| 49 |
|
| 50 |
# Check if the image exceeds the size limit (20MB)
|
| 51 |
-
image_size_mb =
|
| 52 |
if image_size_mb > 20:
|
| 53 |
return "Error: One or more images exceed 20MB.", "Failure", "", "", 0
|
| 54 |
if not str(image).lower().endswith(('.jpg', '.jpeg', '.png')):
|
| 55 |
return "Error: Only JPG/PNG images are supported.", "Failure", "", "", 0
|
| 56 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 57 |
# Convert image to base64 before uploading to Salesforce
|
| 58 |
-
|
|
|
|
| 59 |
|
| 60 |
# Create the ContentVersion record in Salesforce
|
| 61 |
content_version = {
|
| 62 |
-
'Title':
|
| 63 |
-
'PathOnClient':
|
| 64 |
'VersionData': image_data
|
| 65 |
}
|
| 66 |
|
|
@@ -72,8 +81,15 @@ def process_image(images, project_name):
|
|
| 72 |
except Exception as e:
|
| 73 |
return f"Error: Failed to upload image to Salesforce - {str(e)}", "Failure", "", "", 0
|
| 74 |
|
| 75 |
-
#
|
| 76 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 77 |
|
| 78 |
milestones.append(milestone)
|
| 79 |
|
|
@@ -83,11 +99,63 @@ def process_image(images, project_name):
|
|
| 83 |
"Planning": 10,
|
| 84 |
"Foundation": 30,
|
| 85 |
"Walls Erected": 50,
|
| 86 |
-
"Interior Furnishing": 80,
|
| 87 |
"Completed": 100,
|
| 88 |
}
|
| 89 |
percent_complete = milestone_completion_map.get(final_milestone, 0)
|
| 90 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 91 |
completed_tasks = completion_details[final_milestone]["completed"]
|
| 92 |
not_completed_tasks = completion_details[final_milestone]["not_completed"]
|
| 93 |
|
|
@@ -114,7 +182,6 @@ def process_image(images, project_name):
|
|
| 114 |
<span style="color: {'#2ecc71' if final_milestone == 'Planning' else '#bdc3c7'};">Planning</span>
|
| 115 |
<span style="color: {'#2ecc71' if final_milestone == 'Foundation' else '#bdc3c7'};">Foundation</span>
|
| 116 |
<span style="color: {'#2ecc71' if final_milestone == 'Walls Erected' else '#bdc3c7'};">Walls Erected</span>
|
| 117 |
-
<span style="color: {'#2ecc71' if final_milestone == 'Interior Furnishing' else '#bdc3c7'};">Interior Furnishing</span>
|
| 118 |
<span style="color: {'#2ecc71' if final_milestone == 'Completed' else '#bdc3c7'};">Completed</span>
|
| 119 |
</div>
|
| 120 |
|
|
@@ -157,24 +224,6 @@ def process_image(images, project_name):
|
|
| 157 |
except Exception as e:
|
| 158 |
return f"Error: {str(e)}", "Failure", "", "", "0%"
|
| 159 |
|
| 160 |
-
# Enhanced Milestone Detection based on image content or filename
|
| 161 |
-
def detect_milestone(image_path):
|
| 162 |
-
# Check the image filename for certain keywords that might indicate a milestone
|
| 163 |
-
image_name = os.path.basename(image_path).lower()
|
| 164 |
-
if "planning" in image_name:
|
| 165 |
-
return "Planning"
|
| 166 |
-
elif "foundation" in image_name:
|
| 167 |
-
return "Foundation"
|
| 168 |
-
elif "walls" in image_name or "erected" in image_name:
|
| 169 |
-
return "Walls Erected"
|
| 170 |
-
elif "interior" in image_name or "furnishing" in image_name:
|
| 171 |
-
return "Interior Furnishing"
|
| 172 |
-
elif "completed" in image_name:
|
| 173 |
-
return "Completed"
|
| 174 |
-
|
| 175 |
-
# Default to Planning if no specific milestone found
|
| 176 |
-
return "Planning"
|
| 177 |
-
|
| 178 |
# Gradio UI
|
| 179 |
with gr.Blocks(css="""
|
| 180 |
.gradio-container {
|
|
@@ -229,10 +278,10 @@ with gr.Blocks(css="""
|
|
| 229 |
""") as demo:
|
| 230 |
gr.Markdown("<h1 class='title'>Construction Progress Analyzer</h1>")
|
| 231 |
with gr.Row():
|
| 232 |
-
image_input = gr.Files(type="
|
| 233 |
project_name_input = gr.Textbox(label="Project Name (Required)", placeholder="e.g. Project_12345")
|
| 234 |
|
| 235 |
-
submit_button = gr.Button("Process
|
| 236 |
output_html = gr.HTML(label="Result")
|
| 237 |
upload_status = gr.Textbox(label="Upload Status")
|
| 238 |
milestone = gr.Textbox(label="Detected Milestone")
|
|
|
|
| 31 |
print(f"Salesforce connection failed: {str(e)}")
|
| 32 |
raise
|
| 33 |
|
| 34 |
+
# Valid milestones
|
| 35 |
+
VALID_MILESTONES = ["Planning", "Foundation", "Walls Erected", "Completed"]
|
| 36 |
|
| 37 |
# Adjust the timezone to your local timezone
|
| 38 |
local_timezone = pytz.timezone("Asia/Kolkata")
|
|
|
|
| 45 |
|
| 46 |
milestones = []
|
| 47 |
for image in images:
|
| 48 |
+
img = Image.open(image)
|
| 49 |
|
| 50 |
# Check if the image exceeds the size limit (20MB)
|
| 51 |
+
image_size_mb = os.path.getsize(image) / (1024 * 1024)
|
| 52 |
if image_size_mb > 20:
|
| 53 |
return "Error: One or more images exceed 20MB.", "Failure", "", "", 0
|
| 54 |
if not str(image).lower().endswith(('.jpg', '.jpeg', '.png')):
|
| 55 |
return "Error: Only JPG/PNG images are supported.", "Failure", "", "", 0
|
| 56 |
|
| 57 |
+
# Save image to public folder temporarily before uploading to Salesforce
|
| 58 |
+
upload_dir = "public_uploads"
|
| 59 |
+
os.makedirs(upload_dir, exist_ok=True)
|
| 60 |
+
unique_id = datetime.now().strftime("%Y%m%d%H%M%S")
|
| 61 |
+
image_filename = f"{unique_id}_{os.path.basename(image)}"
|
| 62 |
+
saved_image_path = os.path.join(upload_dir, image_filename)
|
| 63 |
+
shutil.copy(image, saved_image_path)
|
| 64 |
+
|
| 65 |
# Convert image to base64 before uploading to Salesforce
|
| 66 |
+
with open(saved_image_path, 'rb') as image_file:
|
| 67 |
+
image_data = base64.b64encode(image_file.read()).decode('utf-8')
|
| 68 |
|
| 69 |
# Create the ContentVersion record in Salesforce
|
| 70 |
content_version = {
|
| 71 |
+
'Title': image_filename,
|
| 72 |
+
'PathOnClient': saved_image_path,
|
| 73 |
'VersionData': image_data
|
| 74 |
}
|
| 75 |
|
|
|
|
| 81 |
except Exception as e:
|
| 82 |
return f"Error: Failed to upload image to Salesforce - {str(e)}", "Failure", "", "", 0
|
| 83 |
|
| 84 |
+
# Now check for completion criteria
|
| 85 |
+
if "completed" in os.path.basename(image).lower() or "finished" in os.path.basename(image).lower():
|
| 86 |
+
milestone = "Completed" # Directly detect completion if such features exist
|
| 87 |
+
else:
|
| 88 |
+
# Default milestone detection logic (mock AI model or image-based hash)
|
| 89 |
+
img_bytes = img.tobytes()
|
| 90 |
+
img_hash = int(hashlib.sha256(img_bytes).hexdigest(), 16)
|
| 91 |
+
milestone_index = img_hash % len(VALID_MILESTONES)
|
| 92 |
+
milestone = VALID_MILESTONES[milestone_index]
|
| 93 |
|
| 94 |
milestones.append(milestone)
|
| 95 |
|
|
|
|
| 99 |
"Planning": 10,
|
| 100 |
"Foundation": 30,
|
| 101 |
"Walls Erected": 50,
|
|
|
|
| 102 |
"Completed": 100,
|
| 103 |
}
|
| 104 |
percent_complete = milestone_completion_map.get(final_milestone, 0)
|
| 105 |
|
| 106 |
+
completion_details = {
|
| 107 |
+
"Planning": {
|
| 108 |
+
"completed": [
|
| 109 |
+
"Initial project outline and objectives have been established.",
|
| 110 |
+
"Preliminary designs and architectural plans are drafted.",
|
| 111 |
+
"Stakeholder meetings and initial approvals are completed."
|
| 112 |
+
],
|
| 113 |
+
"not_completed": [
|
| 114 |
+
"Detailed construction plans and blueprints are pending finalization.",
|
| 115 |
+
"Permits and regulatory approvals are yet to be obtained.",
|
| 116 |
+
"Contractor selection and procurement processes are not yet complete."
|
| 117 |
+
]
|
| 118 |
+
},
|
| 119 |
+
"Foundation": {
|
| 120 |
+
"completed": [
|
| 121 |
+
"Site preparation, including clearing and leveling, is finished.",
|
| 122 |
+
"Excavation for the foundation has been completed.",
|
| 123 |
+
"Concrete pouring for the foundation, including footings and slabs, is done.",
|
| 124 |
+
"Initial structural inspections for the foundation have been passed."
|
| 125 |
+
],
|
| 126 |
+
"not_completed": [
|
| 127 |
+
"Plumbing and electrical groundwork installations are pending.",
|
| 128 |
+
"Backfilling and site grading around the foundation are not yet done.",
|
| 129 |
+
"Above-ground structural work, such as columns and walls, has not started."
|
| 130 |
+
]
|
| 131 |
+
},
|
| 132 |
+
"Walls Erected": {
|
| 133 |
+
"completed": [
|
| 134 |
+
"The concrete framework, including columns and beams, is in place.",
|
| 135 |
+
"All structural walls have been erected and stabilized.",
|
| 136 |
+
"Temporary scaffolding and safety measures are installed for ongoing work.",
|
| 137 |
+
"Initial inspections for structural integrity have been completed."
|
| 138 |
+
],
|
| 139 |
+
"not_completed": [
|
| 140 |
+
"Roofing installation and weatherproofing are pending.",
|
| 141 |
+
"Windows, doors, and exterior cladding are not yet installed.",
|
| 142 |
+
"Interior walls, electrical, and plumbing systems are still to be implemented."
|
| 143 |
+
]
|
| 144 |
+
},
|
| 145 |
+
"Completed": {
|
| 146 |
+
"completed": [
|
| 147 |
+
"The concrete framework, including columns, beams, and floor slabs, is fully constructed.",
|
| 148 |
+
"Exterior walls, windows, and cladding are installed, completing the building's facade.",
|
| 149 |
+
"Interior work, including electrical, plumbing, and HVAC systems, is fully implemented.",
|
| 150 |
+
"Finishing touches, such as flooring, painting, and fixtures, are completed.",
|
| 151 |
+
"All phases of the project are finished, including final inspections and approvals."
|
| 152 |
+
],
|
| 153 |
+
"not_completed": [
|
| 154 |
+
"There should be no more pending work as the project is fully completed."
|
| 155 |
+
]
|
| 156 |
+
}
|
| 157 |
+
}
|
| 158 |
+
|
| 159 |
completed_tasks = completion_details[final_milestone]["completed"]
|
| 160 |
not_completed_tasks = completion_details[final_milestone]["not_completed"]
|
| 161 |
|
|
|
|
| 182 |
<span style="color: {'#2ecc71' if final_milestone == 'Planning' else '#bdc3c7'};">Planning</span>
|
| 183 |
<span style="color: {'#2ecc71' if final_milestone == 'Foundation' else '#bdc3c7'};">Foundation</span>
|
| 184 |
<span style="color: {'#2ecc71' if final_milestone == 'Walls Erected' else '#bdc3c7'};">Walls Erected</span>
|
|
|
|
| 185 |
<span style="color: {'#2ecc71' if final_milestone == 'Completed' else '#bdc3c7'};">Completed</span>
|
| 186 |
</div>
|
| 187 |
|
|
|
|
| 224 |
except Exception as e:
|
| 225 |
return f"Error: {str(e)}", "Failure", "", "", "0%"
|
| 226 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 227 |
# Gradio UI
|
| 228 |
with gr.Blocks(css="""
|
| 229 |
.gradio-container {
|
|
|
|
| 278 |
""") as demo:
|
| 279 |
gr.Markdown("<h1 class='title'>Construction Progress Analyzer</h1>")
|
| 280 |
with gr.Row():
|
| 281 |
+
image_input = gr.Files(type="filepath", label="Upload Construction Site Photos (JPG/PNG, ≤ 20MB)")
|
| 282 |
project_name_input = gr.Textbox(label="Project Name (Required)", placeholder="e.g. Project_12345")
|
| 283 |
|
| 284 |
+
submit_button = gr.Button("Process Image")
|
| 285 |
output_html = gr.HTML(label="Result")
|
| 286 |
upload_status = gr.Textbox(label="Upload Status")
|
| 287 |
milestone = gr.Textbox(label="Detected Milestone")
|