Amina commited on
Commit
d53b194
·
1 Parent(s): 6f75e04

Add files with LFS tracking

Browse files
.idea/.gitignore ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ # Default ignored files
2
+ /shelf/
3
+ /workspace.xml
4
+ # Editor-based HTTP Client requests
5
+ /httpRequests/
6
+ # Datasource local storage ignored files
7
+ /dataSources/
8
+ /dataSources.local.xml
.idea/car-damage-app.iml ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <module type="PYTHON_MODULE" version="4">
3
+ <component name="NewModuleRootManager">
4
+ <content url="file://$MODULE_DIR$">
5
+ <excludeFolder url="file://$MODULE_DIR$/.venv" />
6
+ </content>
7
+ <orderEntry type="jdk" jdkName="Python 3.12 (car-damage-app)" jdkType="Python SDK" />
8
+ <orderEntry type="sourceFolder" forTests="false" />
9
+ </component>
10
+ </module>
.idea/inspectionProfiles/Project_Default.xml ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <component name="InspectionProjectProfileManager">
2
+ <profile version="1.0">
3
+ <option name="myName" value="Project Default" />
4
+ <inspection_tool class="PyPep8NamingInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
5
+ <option name="ignoredErrors">
6
+ <list>
7
+ <option value="N806" />
8
+ </list>
9
+ </option>
10
+ </inspection_tool>
11
+ </profile>
12
+ </component>
.idea/inspectionProfiles/profiles_settings.xml ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ <component name="InspectionProjectProfileManager">
2
+ <settings>
3
+ <option name="USE_PROJECT_PROFILE" value="false" />
4
+ <version value="1.0" />
5
+ </settings>
6
+ </component>
.idea/misc.xml ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="Black">
4
+ <option name="sdkName" value="Python 3.12 (car-damage-app)" />
5
+ </component>
6
+ </project>
.idea/modules.xml ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="ProjectModuleManager">
4
+ <modules>
5
+ <module fileurl="file://$PROJECT_DIR$/.idea/car-damage-app.iml" filepath="$PROJECT_DIR$/.idea/car-damage-app.iml" />
6
+ </modules>
7
+ </component>
8
+ </project>
.idea/vcs.xml ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="VcsDirectoryMappings">
4
+ <mapping directory="$PROJECT_DIR$" vcs="Git" />
5
+ </component>
6
+ </project>
Dockerfile ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.9-slim
2
+
3
+ WORKDIR /code
4
+
5
+ COPY ./requirements.txt /code/requirements.txt
6
+
7
+ RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
8
+
9
+ COPY ./best.pt /code/best.pt
10
+ COPY ./app.py /code/app.py
11
+
12
+
13
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
app.py ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, File, UploadFile
2
+ from PIL import Image
3
+ import torch
4
+ import io
5
+
6
+ app = FastAPI(title="Car Damage Detection API")
7
+
8
+ # Load custom YOLOv8 model.
9
+ model = torch.hub.load('ultralytics/yolov8', 'custom', path='best.pt')
10
+
11
+
12
+ @app.get("/")
13
+ def read_root():
14
+ """ A simple endpoint to check if the server is running. """
15
+ return {"status": "ok", "message": "Car Damage Detection API is running!"}
16
+
17
+
18
+ @app.post("/detect")
19
+ async def detect_damage(file: UploadFile = File(...)):
20
+ """
21
+ This endpoint receives an image, runs inference, and returns detections.
22
+ """
23
+ # Read image content from the uploaded file
24
+ contents = await file.read()
25
+ image = Image.open(io.BytesIO(contents)).convert("RGB")
26
+
27
+ # Run the model on the image
28
+ results = model(image)
29
+
30
+ # Extract results into a clean format
31
+ predictions_df = results.pandas().xyxy[0]
32
+
33
+ # Filter detections by a confidence threshold (e.g., > 50%)
34
+ detections = predictions_df[predictions_df['confidence'] > 0.5]
35
+
36
+ # Convert the results to a JSON-friendly list of dictionaries
37
+ output = detections[['name', 'confidence']].to_dict(orient='records')
38
+
39
+ return {"detections": output}
best.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e5b520423c03c31efe05a1b5c9b9387b2a15a8ecb177c47e7d6e3a5bad01fb57
3
+ size 6250474
index.html ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Car Damage Detector</title>
7
+ <style>
8
+ body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; text-align: center; margin: 0; background-color: #f0f2f5; }
9
+ .container { max-width: 600px; margin: 50px auto; padding: 30px; background-color: #fff; box-shadow: 0 4px 12px rgba(0,0,0,0.1); border-radius: 8px; }
10
+ h1 { color: #333; }
11
+ #image-preview { display: none; max-width: 100%; height: auto; margin-top: 20px; border-radius: 4px; border: 1px solid #ddd; }
12
+ .upload-area { border: 2px dashed #007bff; border-radius: 8px; padding: 40px; margin: 20px 0; cursor: pointer; background-color: #f8f9fa; }
13
+ .upload-area p { margin: 0; color: #555; }
14
+ button { font-size: 1.1em; padding: 12px 25px; cursor: pointer; background-color: #007bff; color: white; border: none; border-radius: 5px; transition: background-color 0.3s; }
15
+ button:hover { background-color: #0056b3; }
16
+ button:disabled { background-color: #aaa; cursor: not-allowed; }
17
+ #results { margin-top: 30px; font-size: 1.1em; text-align: left; }
18
+ #results ul { list-style-type: none; padding: 0; }
19
+ #results li { background-color: #e9ecef; padding: 10px; margin-bottom: 8px; border-radius: 4px; }
20
+ #results .confidence { color: #28a745; font-weight: bold; }
21
+ </style>
22
+ </head>
23
+ <body>
24
+
25
+ <div class="container">
26
+ <h1>🚗 Car Damage Detector</h1>
27
+ <p>Upload a photo to automatically check for scratches, dents, or rust.</p>
28
+
29
+ <div class="upload-area" id="upload-area">
30
+ <p>Click here or drag & drop an image</p>
31
+ </div>
32
+
33
+ <input type="file" id="image-upload" accept="image/*" hidden>
34
+
35
+ <button id="check-button" disabled>Check for Damage</button>
36
+
37
+ <img id="image-preview" src="" alt="Your uploaded image">
38
+
39
+ <div id="results"></div>
40
+ </div>
41
+
42
+ <script>
43
+ // ⚠️ IMPORTANT: REPLACE THIS URL with your actual Hugging Face Space URL!
44
+ const API_URL = "https://YOUR_USERNAME-YOUR_SPACE_NAME.hf.space/detect";
45
+
46
+ const uploadArea = document.getElementById('upload-area');
47
+ const imageUpload = document.getElementById('image-upload');
48
+ const checkButton = document.getElementById('check-button');
49
+ const imagePreview = document.getElementById('image-preview');
50
+ const resultsDiv = document.getElementById('results');
51
+ let selectedFile = null;
52
+
53
+ uploadArea.addEventListener('click', () => imageUpload.click());
54
+ imageUpload.addEventListener('change', handleFileSelect);
55
+
56
+ function handleFileSelect(event) {
57
+ selectedFile = event.target.files[0];
58
+ if (selectedFile) {
59
+ imagePreview.src = URL.createObjectURL(selectedFile);
60
+ imagePreview.style.display = 'block';
61
+ checkButton.disabled = false;
62
+ resultsDiv.innerHTML = '';
63
+ }
64
+ }
65
+
66
+ checkButton.addEventListener('click', async () => {
67
+ if (!selectedFile) {
68
+ alert("Please select an image first!");
69
+ return;
70
+ }
71
+
72
+ resultsDiv.innerHTML = "<p>Analyzing, please wait... 🧐</p>";
73
+ checkButton.disabled = true;
74
+ checkButton.innerText = "Analyzing...";
75
+
76
+ const formData = new FormData();
77
+ formData.append('file', selectedFile);
78
+
79
+ try {
80
+ const response = await fetch(API_URL, {
81
+ method: 'POST',
82
+ body: formData,
83
+ });
84
+
85
+ if (!response.ok) {
86
+ throw new Error(`Server error: ${response.statusText}`);
87
+ }
88
+
89
+ const data = await response.json();
90
+ displayResults(data.detections);
91
+
92
+ } catch (error) {
93
+ resultsDiv.innerHTML = `<p style="color: red;">An error occurred: ${error.message}</p>`;
94
+ console.error("Error:", error);
95
+ } finally {
96
+ checkButton.disabled = false;
97
+ checkButton.innerText = "Check for Damage";
98
+ }
99
+ });
100
+
101
+ function displayResults(detections) {
102
+ if (detections.length === 0) {
103
+ resultsDiv.innerHTML = "<p>✅ No damage detected!</p>";
104
+ return;
105
+ }
106
+
107
+ let html = "<h3>Detected Issues:</h3><ul>";
108
+ detections.forEach(det => {
109
+ const confidence = (det.confidence * 100).toFixed(1);
110
+ html += `<li><strong>${det.name}</strong> <span class="confidence">(${confidence}%)</span></li>`;
111
+ });
112
+ html += "</ul>";
113
+ resultsDiv.innerHTML = html;
114
+ }
115
+ </script>
116
+
117
+ </body>
118
+ </html>
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ fastapi
2
+ uvicorn
3
+ python-multipart
4
+ torch
5
+ ultralytics
6
+ Pillow