File size: 7,870 Bytes
dba26ff |
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 |
import os
from shapely.geometry import Polygon
class DamageCalculator:
def __init__(self):
self.cost_ranges = {
"Scratch": {
"Minor": (1000, 3000),
"Moderate": (3000, 5000),
"Severe": (5000, 10000)
},
"Dent": {
"Minor": (2000, 4000),
"Moderate": (4000, 10000),
"Severe": (10000, 15000)
},
"Paint chip": {
"Minor": (1000, 2000),
"Moderate": (2000, 4000),
"Severe": (4000, 10000)
},
"Broken part": (1000, 7000)
}
def parse_coordinates(self, file_path):
polygons = []
class_names = []
with open(file_path, 'r') as file:
for line in file:
parts = line.strip().split()
class_name = []
coordinates = []
for part in parts:
try:
coordinates.append(float(part))
except ValueError:
class_name.append(part)
if class_name and coordinates:
class_name = " ".join(class_name)
try:
if len(coordinates) % 2 != 0:
raise ValueError("Coordinates are not in pairs.")
polygon = Polygon([(coordinates[i], coordinates[i+1]) for i in range(0, len(coordinates), 2)])
polygons.append(polygon)
class_names.append(class_name)
except ValueError as e:
print(f"Skipping line due to error: {e}")
else:
print(f"Skipping line due to insufficient data: {line.strip()}")
return class_names, polygons
def calculate_severity(self, coverage_percentage):
if 3 < coverage_percentage <= 30:
return "Minor"
elif 30 < coverage_percentage <= 60:
return "Moderate"
elif coverage_percentage > 60:
return "Severe"
return "N/A"
def calculate_cost(self, damage_class, severity):
if damage_class == "Broken part":
return self.cost_ranges["Broken part"]
elif severity in self.cost_ranges[damage_class]:
return self.cost_ranges[damage_class][severity]
return (0, 0)
def summarize_damage_by_part(self, damage_polygons, part_polygons):
intersection_info = self.calculate_intersection_area(damage_polygons, part_polygons)
summary = {}
for info in intersection_info:
part_class = info['part_class']
damage_class = info['damage_class']
coverage_percentage = info['coverage_percentage']
if part_class not in summary:
summary[part_class] = {'total_coverage': 0, 'damage_types': {}}
summary[part_class]['total_coverage'] += coverage_percentage
if damage_class not in summary[part_class]['damage_types']:
summary[part_class]['damage_types'][damage_class] = 0
summary[part_class]['damage_types'][damage_class] += coverage_percentage
for part_class in summary:
total_coverage = summary[part_class]['total_coverage']
for damage_class in summary[part_class]['damage_types']:
summary[part_class]['damage_types'][damage_class] = (
summary[part_class]['damage_types'][damage_class] / total_coverage * 100
)
summary[part_class]['undamaged'] = 100 - total_coverage
return summary
def calculate_intersection_area(self, damage_polygons, part_polygons):
intersection_info = []
front_back_door_detected = any(part_class in ['Front-door', 'Back-door'] for part_class, _ in part_polygons)
for damage_class, damage_polygon in damage_polygons:
for part_class, part_polygon in part_polygons:
if damage_polygon.intersects(part_polygon):
intersection = damage_polygon.intersection(part_polygon)
intersection_area = intersection.area
part_area = part_polygon.area
coverage_percentage = (intersection_area / part_area) * 100
# Condition 1: Ignore damage coverage <= 3%
if coverage_percentage <= 3:
continue
# Condition 2: Apply weights based on the new conditions
if part_class in ['Front-bumper', 'Back-bumper']:
if front_back_door_detected:
coverage_percentage *= 0.2
else:
coverage_percentage *= 0.6
if coverage_percentage <= 3:
continue
# Updated Condition 3: Include Headlight and tail light only with broken part if damage > 50%
if part_class in ['Headlight', 'Tail-light']:
if damage_class == 'Broken part' and coverage_percentage > 50:
intersection_info.append({
"damage_class": damage_class,
"part_class": part_class,
"intersection_area": intersection_area,
"part_area": part_area,
"coverage_percentage": coverage_percentage
})
continue
# Condition 4: Exclude damage with front-wheel, back wheel, and license plate
if part_class in ['Front-wheel', 'Back-wheel', 'License-plate']:
continue
intersection_info.append({
"damage_class": damage_class,
"part_class": part_class,
"intersection_area": intersection_area,
"part_area": part_area,
"coverage_percentage": coverage_percentage
})
# Condition 5: Sum coverage for the same type of defect on the same part
summarized_info = {}
for info in intersection_info:
key = (info['damage_class'], info['part_class'])
if key not in summarized_info:
summarized_info[key] = {
"intersection_area": 0,
"part_area": info['part_area'],
"coverage_percentage": 0,
"count": 0
}
summarized_info[key]["intersection_area"] += info["intersection_area"]
summarized_info[key]["coverage_percentage"] += info["coverage_percentage"]
summarized_info[key]["count"] += 1
final_info = []
for (damage_class, part_class), values in summarized_info.items():
part_area = values["part_area"]
intersection_area = values["intersection_area"]
coverage_percentage = values["coverage_percentage"]
count = values["count"]
severity = self.calculate_severity(coverage_percentage)
cost_min, cost_max = self.calculate_cost(damage_class, severity)
final_info.append({
"damage_class": damage_class,
"part_class": part_class,
"intersection_area": intersection_area,
"part_area": part_area,
"coverage_percentage": coverage_percentage,
"severity": severity,
"cost_min": cost_min,
"cost_max": cost_max,
"count": count
})
return final_info
|