Amitshri commited on
Commit
04315fe
·
1 Parent(s): d159520

initial code

Browse files

initial code push

Files changed (6) hide show
  1. .dockerignore +27 -0
  2. .gitignore +5 -0
  3. Dockerfile +26 -0
  4. app/main.py +37 -0
  5. app/removal.py +52 -0
  6. requirements.txt +9 -0
.dockerignore ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ **/__pycache__
2
+ **/.venv
3
+ **/.classpath
4
+ **/.dockerignore
5
+ **/.env
6
+ **/.git
7
+ **/.gitignore
8
+ **/.project
9
+ **/.settings
10
+ **/.toolstarget
11
+ **/.vs
12
+ **/.vscode
13
+ **/*.*proj.user
14
+ **/*.dbmdl
15
+ **/*.jfm
16
+ **/bin
17
+ **/charts
18
+ **/docker-compose*
19
+ **/compose*
20
+ **/Dockerfile*
21
+ **/node_modules
22
+ **/npm-debug.log
23
+ **/obj
24
+ **/secrets.dev.yaml
25
+ **/values.dev.yaml
26
+ LICENSE
27
+ README.md
.gitignore ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ .venv
2
+ .env
3
+ __pycache__/
4
+ .vscode
5
+ venv
Dockerfile ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # For more information, please refer to https://aka.ms/vscode-docker-python
2
+ FROM python:3.11-slim
3
+
4
+ EXPOSE 8000
5
+
6
+ # Keeps Python from generating .pyc files in the container
7
+ ENV PYTHONDONTWRITEBYTECODE=1
8
+
9
+ # Turns off buffering for easier container logging
10
+ ENV PYTHONUNBUFFERED=1
11
+
12
+ # Install pip requirements
13
+ COPY requirements.txt .
14
+ RUN python -m pip install -r requirements.txt
15
+
16
+ WORKDIR /app
17
+ COPY . /app
18
+
19
+ # Creates a non-root user with an explicit UID and adds permission to access the /app folder
20
+ # For more info, please refer to https://aka.ms/vscode-docker-python-configure-containers
21
+ RUN adduser -u 5678 --disabled-password --gecos "" appuser && chown -R appuser /app
22
+ USER appuser
23
+
24
+ # During debugging, this entry point will be overridden. For more information, please refer to https://aka.ms/vscode-docker-python-debug
25
+ CMD ["gunicorn", "--bind", "0.0.0.0:8000", "-k", "uvicorn.workers.UvicornWorker", "-t", "3500" ,"--keep-alive" , "3500", "app.main:app"]
26
+
app/main.py ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI
2
+ from pydantic import BaseModel
3
+ from fastapi.middleware.cors import CORSMiddleware
4
+ import uvicorn
5
+ from app.removal import remove_bg_base64
6
+ from pydantic import BaseModel
7
+
8
+
9
+ app = FastAPI()
10
+
11
+ app.add_middleware(
12
+ CORSMiddleware,
13
+ allow_origins=["*"],
14
+ allow_credentials=True,
15
+ allow_methods=["*"],
16
+ allow_headers=["*"],
17
+ )
18
+
19
+ class ImageData(BaseModel):
20
+ image_data: str
21
+
22
+ active_connections = []
23
+ VERSION = "1.0.0"
24
+
25
+ @app.get("/")
26
+ async def health_check():
27
+ return {"status": "healthy"}
28
+
29
+ @app.post("/BgRemoval")
30
+ async def bg_removal(request: ImageData):
31
+ try:
32
+ image_data = request.image_data
33
+ output_image = remove_bg_base64(image_data)
34
+ return {"output_image": output_image}
35
+ except Exception as e:
36
+ print(f"Error Occured: {str(e)}")
37
+ return {"error": str(e)}
app/removal.py ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import base64
2
+ from io import BytesIO
3
+ from rembg import remove
4
+ from PIL import Image
5
+ import numpy as np
6
+ import scipy.ndimage as ndi
7
+
8
+
9
+ def keep_largest_object_alpha(alpha_mask_np, threshold=0.1):
10
+ binary_mask = (alpha_mask_np > threshold).astype(np.uint8)
11
+ labeled, n = ndi.label(binary_mask)
12
+ if n == 0:
13
+ return alpha_mask_np
14
+ sizes = ndi.sum(binary_mask, labeled, range(n + 1))
15
+ largest_label = sizes.argmax()
16
+ largest_mask = (labeled == largest_label).astype(np.float32)
17
+ return largest_mask * alpha_mask_np
18
+
19
+
20
+ def remove_bg_base64(base64_image: str) -> str:
21
+ # Decode base64 image to PIL Image
22
+ image_data = base64.b64decode(base64_image)
23
+ input_image = Image.open(BytesIO(image_data)).convert("RGBA")
24
+
25
+ # Remove background
26
+ output = remove(input_image)
27
+
28
+ # Convert to RGBA and extract alpha
29
+ output = output.convert("RGBA")
30
+ r, g, b, a = output.split()
31
+ alpha_np = np.array(a).astype(np.float32) / 255.0
32
+
33
+ # Keep only largest subject in the alpha mask
34
+ filtered_alpha = keep_largest_object_alpha(alpha_np)
35
+
36
+ # Convert filtered alpha to image
37
+ filtered_alpha_img = Image.fromarray((filtered_alpha * 255).astype(np.uint8))
38
+ output.putalpha(filtered_alpha_img)
39
+
40
+ # Paste onto white background
41
+ white_bg = Image.new("RGBA", output.size, (255, 255, 255, 255))
42
+ white_bg.paste(output, (0, 0), mask=output.split()[3])
43
+
44
+ # Final image (no alpha)
45
+ final_image = white_bg.convert("RGB")
46
+
47
+ # Convert to base64 string
48
+ buffered = BytesIO()
49
+ final_image.save(buffered, format="JPEG")
50
+ final_base64 = base64.b64encode(buffered.getvalue()).decode("utf-8")
51
+
52
+ return final_base64
requirements.txt ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ fastapi
2
+ gunicorn
3
+ pydantic
4
+ uvicorn
5
+ numpy
6
+ rembg
7
+ Pillow
8
+ scipy
9
+ onnxruntime