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