File size: 7,437 Bytes
76e08f4
 
 
 
 
 
 
 
 
ecd56d9
76e08f4
 
 
3fc77fd
76e08f4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3fc77fd
76e08f4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b84ad8d
 
 
 
76e08f4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e0a16bd
76e08f4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b84ad8d
 
 
 
 
76e08f4
b84ad8d
 
 
e0a16bd
6843abb
 
b84ad8d
 
76e08f4
 
3fc77fd
b84ad8d
 
76e08f4
 
b84ad8d
 
 
 
 
 
 
 
 
 
6843abb
e0a16bd
76e08f4
b84ad8d
76e08f4
 
 
 
 
b84ad8d
76e08f4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b84ad8d
 
e0a16bd
 
ecd56d9
b84ad8d
76e08f4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
import gradio as gr
from PIL import Image, ImageDraw
import torch
from torchvision import models, transforms
from simple_salesforce import Salesforce
import base64
from io import BytesIO
import logging
from datetime import datetime

# Setup logging
logging.basicConfig(level=logging.INFO)

# Salesforce Credentials (ensure these are set up in your environment variables for security)
SALESFORCE_USERNAME = "drone@sathkrutha.com"
SALESFORCE_PASSWORD = "Komal1303@"
SALESFORCE_SECURITY_TOKEN = "53AWRskW9EjWUsSL5LU6nFTy3"
SALESFORCE_INSTANCE_URL = "https://sathikrutha-a-dev-ed.my.salesforce.com"

# Replace with a valid Site__c record ID from your Salesforce org
SITE_RECORD_ID = "a003000000xxxxx"  # TODO: Update with actual ID from Site__c

# Connect to Salesforce
try:
    sf = Salesforce(
        username=SALESFORCE_USERNAME,
        password=SALESFORCE_PASSWORD,
        security_token=SALESFORCE_SECURITY_TOKEN,
        instance_url=SALESFORCE_INSTANCE_URL
    )
    logging.info("Salesforce connection established.")
except Exception as e:
    logging.error(f"Failed to connect to Salesforce: {str(e)}")
    raise Exception(f"Failed to connect to Salesforce: {str(e)}")

# Load Model (updated to use correct weights for the current PyTorch version)
model = models.detection.fasterrcnn_resnet50_fpn(weights="FasterRCNN_ResNet50_FPN_Weights.COCO_V1")
model.eval()

# Define labels (COCO labels; fine-tune for structural defects)
COCO_INSTANCE_CATEGORY_NAMES = [
    '__background__', 'person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus',
    'train', 'truck', 'boat', 'traffic light', 'fire hydrant', 'stop sign', 'parking meter',
    'bench', 'bird', 'cat', 'dog', 'horse', 'sheep', 'cow', 'elephant', 'bear', 'zebra',
    'giraffe', 'backpack', 'umbrella', 'handbag', 'tie', 'suitcase', 'frisbee', 'skis',
    'snowboard', 'sports ball', 'kite', 'baseball bat', 'baseball glove', 'skateboard',
    'surfboard', 'tennis racket', 'bottle', 'wine glass', 'cup', 'fork', 'knife', 'spoon',
    'bowl', 'banana', 'apple', 'sandwich', 'orange', 'broccoli', 'carrot', 'hot dog', 'pizza',
    'donut', 'cake', 'chair', 'couch', 'potted plant', 'bed', 'dining table', 'toilet',
    'tv', 'laptop', 'mouse', 'remote', 'keyboard', 'cell phone', 'microwave', 'oven',
    'toaster', 'sink', 'refrigerator', 'book', 'clock', 'vase', 'scissors', 'teddy bear',
    'hair drier', 'toothbrush'
]

# Image transformations
transform = transforms.Compose([
    transforms.ToTensor(),
])

# Map model severity to Salesforce picklist values
def get_severity(score):
    if score >= 0.9:
        return "Critical"
    elif score >= 0.7:
        return "Moderate"
    else:
        return "Minor"

# Temporary mapping for COCO labels to structural defects
COCO_TO_DEFECT_MAPPING = {
    'car': 'Crack',
    'person': 'Rust',
    'bicycle': 'Deformation',
    'truck': 'Corrosion',
    'boat': 'Spalling',
}

def map_defect_type(coco_label):
    return COCO_TO_DEFECT_MAPPING.get(coco_label, "Crack")

# Function to upload image to Salesforce as ContentVersion
def upload_image_to_salesforce(image, filename="detected_image.jpg", record_id=None):
    try:
        buffered = BytesIO()
        image.save(buffered, format="JPEG")
        img_data = base64.b64encode(buffered.getvalue()).decode("utf-8")
        
        content_version = sf.ContentVersion.create({
            "Title": filename,
            "PathOnClient": filename,
            "VersionData": img_data,
            "FirstPublishLocationId": record_id if record_id else None
        })
        logging.info(f"Image uploaded to Salesforce with ContentVersion ID: {content_version['id']}")
        return content_version["id"]
    except Exception as e:
        logging.error(f"Failed to upload image to Salesforce: {str(e)}")
        raise Exception(f"Failed to upload image to Salesforce: {str(e)}")

# Detect defects and integrate with Salesforce
def detect_defects(image):
    if not image:
        return None, {"error": "No image provided"}

    try:
        # Perform detection
        image_tensor = transform(image).unsqueeze(0)
        with torch.no_grad():
            predictions = model(image_tensor)

        result_image = image.copy()
        draw = ImageDraw.Draw(result_image)
        output = []

        for i in range(len(predictions[0]['boxes'])):
            score = predictions[0]['scores'][i].item()
            if score < 0.3:  # Lowered threshold to detect more objects
                continue

            box = predictions[0]['boxes'][i].tolist()
            label_idx = predictions[0]['labels'][i].item()
            coco_label = COCO_INSTANCE_CATEGORY_NAMES[label_idx]
            defect_type = map_defect_type(coco_label)
            severity = get_severity(score)

            output.append({
                "type": defect_type,
                "confidence": round(score, 2),
                "severity": severity,
                "coco_label": coco_label
            })

            draw.rectangle(box, outline="red", width=3)
            draw.text((box[0], box[1]), f"{defect_type}: {severity}", fill="red")

        # Create Salesforce record if detections exist
        if output:
            try:
                current_date = datetime.now().strftime("%Y-%m-%d")
                inspection_name = f"Inspection-{current_date}-{len(output):03d}"

                # Creating the Salesforce record with updated fields
                inspection_record = sf.Drone_Structure_Inspection__c.create({
                    "Inspection_Date__c": current_date,
                    "Fault_Type__c": output[0]["type"],  # Mapping defect type
                    "Severity__c": output[0]["severity"],  # Mapping severity
                    "Fault_Summary__c": str(output),  # Summarizing the defects
                    "Status__c": "New",  # Default status
                    "Annotated_Image_URL__c": "",  # Placeholder for image URL
                    "Report_PDF__c": ""  # Placeholder for report PDF URL
                })

                record_id = inspection_record.get("id")
                content_version_id = upload_image_to_salesforce(
                    result_image,
                    filename=f"detected_defect_{record_id}.jpg",
                    record_id=record_id
                )

                if content_version_id:
                    sf.Drone_Structure_Inspection__c.update(record_id, {
                        "Annotated_Image_URL__c": f"/sfc/servlet.shepherd/version/download/{content_version_id}"
                    })

                output.append({"salesforce_record_id": record_id})
            except Exception as e:
                output.append({"error": f"Failed to create Salesforce record: {str(e)}"})

        return result_image, output

    except Exception as e:
        logging.error(f"Processing failed: {str(e)}")
        return None, {"error": f"Processing failed: {str(e)}"}

# Gradio Interface
demo = gr.Interface(
    fn=detect_defects,
    inputs=gr.Image(type="pil", label="Upload Drone Image"),
    outputs=[
        gr.Image(label="Detection Result"),
        gr.Textbox(label="Detected Faults with Severity")
    ],
    title="Structural Defect Detection with Salesforce Integration",
    description="Detects objects using Faster R-CNN and stores results in Salesforce. Fine-tune the model for structural defects like cracks, rust, and spalling."
)

if __name__ == "__main__":
    demo.launch()