Omkar1872 commited on
Commit
31fcc9f
·
verified ·
1 Parent(s): b4c1fbb

Upload 7 files

Browse files
Files changed (7) hide show
  1. Dockerfile.txt +9 -0
  2. app.py +44 -0
  3. index.html +19 -0
  4. pneumonia_model.pth +3 -0
  5. requirements.txt +8 -0
  6. script.js +25 -0
  7. style.css +63 -0
Dockerfile.txt ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.10
2
+
3
+ WORKDIR /app
4
+
5
+ COPY . /app
6
+
7
+ RUN pip install --no-cache-dir -r requirements.txt
8
+
9
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
app.py ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, File, UploadFile, Request
2
+ from fastapi.responses import HTMLResponse
3
+ from fastapi.templating import Jinja2Templates
4
+ from fastapi.staticfiles import StaticFiles
5
+ from fastapi.middleware.cors import CORSMiddleware
6
+ import torch
7
+ from torchvision import transforms
8
+ from PIL import Image
9
+ import io
10
+
11
+ app = FastAPI()
12
+ app.add_middleware(
13
+ CORSMiddleware,
14
+ allow_origins=["*"],
15
+ allow_credentials=True,
16
+ allow_methods=["*"],
17
+ allow_headers=["*"],
18
+ )
19
+
20
+ app.mount("/static", StaticFiles(directory="static"), name="static")
21
+ templates = Jinja2Templates(directory="templates")
22
+
23
+ model = torch.load("pneumonia_model.pth", map_location=torch.device('cpu'))
24
+ model.eval()
25
+
26
+ transform = transforms.Compose([
27
+ transforms.Resize((224, 224)),
28
+ transforms.ToTensor(),
29
+ ])
30
+
31
+ @app.get("/", response_class=HTMLResponse)
32
+ async def home(request: Request):
33
+ return templates.TemplateResponse("index.html", {"request": request})
34
+
35
+ @app.post("/predict")
36
+ async def predict(file: UploadFile = File(...)):
37
+ contents = await file.read()
38
+ image = Image.open(io.BytesIO(contents)).convert("RGB")
39
+ image = transform(image).unsqueeze(0)
40
+ with torch.no_grad():
41
+ output = model(image)
42
+ predicted = torch.argmax(output, 1).item()
43
+ result = "Pneumonia" if predicted == 1 else "Normal"
44
+ return {"result": result}
index.html ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>Pneumonia Detection</title>
6
+ <link rel="stylesheet" href="/static/style.css">
7
+ </head>
8
+ <body>
9
+ <div class="container">
10
+ <h1>Pneumonia Detection from Chest X-ray</h1>
11
+ <p class="subtitle">Upload an X-ray image to check for Pneumonia</p>
12
+ <input type="file" id="fileInput" accept="image/*">
13
+ <button onclick="uploadImage()">Detect</button>
14
+ <p id="loading" class="hidden">Processing...</p>
15
+ <p id="result"></p>
16
+ </div>
17
+ <script src="/static/script.js"></script>
18
+ </body>
19
+ </html>
pneumonia_model.pth ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:677596133caedaa444b61278a31f5507d3f52eee4dc57d902c48fbee22a7101a
3
+ size 22
requirements.txt ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ fastapi
2
+ uvicorn
3
+ python-multipart
4
+ jinja2
5
+ aiofiles
6
+ torch
7
+ torchvision
8
+ Pillow
script.js ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ function uploadImage() {
2
+ const fileInput = document.getElementById("fileInput");
3
+ const file = fileInput.files[0];
4
+ if (!file) return;
5
+
6
+ document.getElementById("loading").classList.remove("hidden");
7
+ document.getElementById("result").innerText = "";
8
+
9
+ const formData = new FormData();
10
+ formData.append("file", file);
11
+
12
+ fetch("/predict", {
13
+ method: "POST",
14
+ body: formData,
15
+ })
16
+ .then((res) => res.json())
17
+ .then((data) => {
18
+ document.getElementById("loading").classList.add("hidden");
19
+ document.getElementById("result").innerText = "Prediction: " + data.result;
20
+ })
21
+ .catch((err) => {
22
+ document.getElementById("loading").classList.add("hidden");
23
+ document.getElementById("result").innerText = "Error during prediction.";
24
+ });
25
+ }
style.css ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ body {
2
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
3
+ background: linear-gradient(135deg, #d3cce3, #e9e4f0);
4
+ margin: 0;
5
+ padding: 0;
6
+ }
7
+
8
+ .container {
9
+ max-width: 500px;
10
+ margin: 80px auto;
11
+ background-color: #f0f4f8;
12
+ padding: 40px;
13
+ border-radius: 15px;
14
+ box-shadow: 0 8px 20px rgba(0, 0, 0, 0.15);
15
+ text-align: center;
16
+ }
17
+
18
+ h1 {
19
+ margin-bottom: 10px;
20
+ color: #333;
21
+ }
22
+
23
+ .subtitle {
24
+ margin-bottom: 30px;
25
+ color: #555;
26
+ }
27
+
28
+ input[type="file"] {
29
+ margin: 20px 0;
30
+ display: block;
31
+ width: 100%;
32
+ padding: 10px;
33
+ border: 2px dashed #bbb;
34
+ border-radius: 10px;
35
+ background: #fafafa;
36
+ cursor: pointer;
37
+ }
38
+
39
+ button {
40
+ background-color: #007bff;
41
+ color: white;
42
+ border: none;
43
+ padding: 12px 24px;
44
+ font-size: 16px;
45
+ border-radius: 8px;
46
+ cursor: pointer;
47
+ }
48
+
49
+ #loading {
50
+ margin-top: 20px;
51
+ color: #333;
52
+ }
53
+
54
+ #result {
55
+ margin-top: 30px;
56
+ font-size: 18px;
57
+ font-weight: bold;
58
+ color: #2c3e50;
59
+ }
60
+
61
+ .hidden {
62
+ display: none;
63
+ }