Skip to content

Commit 943f4ae

Browse files
authored
Add files via upload
1 parent dd4dc59 commit 943f4ae

File tree

9 files changed

+246
-2
lines changed

9 files changed

+246
-2
lines changed

docker-compose.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ services:
1313
build: streamlit/
1414
depends_on:
1515
- fastapi
16-
ports:
16+
ports:
1717
- 8501:8501
1818
networks:
1919
- deploy_network
2020
container_name: streamlit
2121

2222
networks:
2323
deploy_network:
24-
driver: bridge
24+
driver: bridge

fastapi/Dockerfile

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
FROM tiangolo/uvicorn-gunicorn:python3.7
2+
3+
RUN mkdir /fastapi
4+
5+
COPY requirements.txt /fastapi
6+
7+
ADD /detectron2 /detectron2
8+
9+
WORKDIR /fastapi
10+
11+
RUN pip install -r requirements.txt -f https://download.pytorch.org/whl/torch_stable.html
12+
13+
RUN pip install -e ../detectron2
14+
15+
COPY . /fastapi
16+
17+
EXPOSE 8000
18+
19+
CMD ["uvicorn", "server:app", "--host", "0.0.0.0", "--port", "8000"]

fastapi/detectron2.zip

2.05 MB
Binary file not shown.

fastapi/maskrcnn.py

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
#!/usr/bin/env python3
2+
# -*- coding: utf-8 -*-
3+
"""
4+
Created on Sat Jul 4 13:31:36 2020
5+
6+
@author: minseongkang
7+
"""
8+
import numpy as np
9+
from detectron2 import model_zoo
10+
from detectron2.engine import DefaultPredictor
11+
from detectron2.config import get_cfg
12+
from detectron2.utils.visualizer import Visualizer
13+
from detectron2.data import MetadataCatalog
14+
from PIL import Image
15+
import urllib.request
16+
17+
"""
18+
This class represents the Instance Segmentation model Mask R-CNN
19+
"""
20+
class Segmentor:
21+
22+
def __init__(self):
23+
#create a predictor
24+
self._cfg = get_cfg()
25+
self._predictor = self._makePredictor()
26+
self._class = MetadataCatalog.get(self._cfg.DATASETS.TRAIN[0]).get("thing_classes")
27+
28+
"""
29+
This method initalizes the model and configuration
30+
to return the predictor
31+
"""
32+
def _makePredictor(self):
33+
self._cfg.merge_from_file(model_zoo.get_config_file("COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml"))
34+
self._cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.7
35+
self._cfg.MODEL.WEIGHTS = model_zoo.get_checkpoint_url("COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml")
36+
return DefaultPredictor(self._cfg)
37+
38+
"""
39+
This method takes an opencv image and perfroms instance segmentation
40+
"""
41+
def predict(self, image):
42+
return self._predictor(image)
43+
44+
"""
45+
This method takes an output of the model and returns the segmentation
46+
map of the image
47+
"""
48+
def segMap(self, image,output):
49+
v = Visualizer(image[:, :, ::-1], MetadataCatalog.get(self._cfg.DATASETS.TRAIN[0]), scale=1.2)
50+
v = v.draw_instance_predictions(output["instances"].to("cpu"))
51+
r = Image.fromarray(v.get_image()[:,:,::-1])
52+
return r
53+
"""
54+
This method takes an output of the model and returns an array of images
55+
of key objects in the input image.
56+
"""
57+
def decompose(self, image, output):
58+
r = dict()
59+
count = dict()
60+
for i in range(len(output["instances"].pred_boxes)):
61+
box = output["instances"].pred_boxes[i].tensor.numpy()[0]
62+
dim = (box[0],box[1],box[2],box[3])
63+
mask = output["instances"].pred_masks[i]
64+
image2 = image[:,:,::-1].copy()
65+
for j in range(len(image)):
66+
for k in range(len(image[j])):
67+
if mask[j][k]==False:
68+
for l in range(len(image2[j][k])):
69+
image2[j][k][l]=255
70+
pic = Image.fromarray(image2)
71+
pic = pic.crop(dim)
72+
pic = self._transparent(pic)
73+
cl = self._class[output["instances"].pred_classes[i]]
74+
if cl in count:
75+
count[cl]+=1
76+
else:
77+
count[cl]=1
78+
r[cl+str(count[cl])]=pic
79+
return r
80+
"""
81+
Input: PIL image
82+
Output: PIL image with transparent background
83+
"""
84+
def _transparent(self,image):
85+
r = image.convert("RGBA")
86+
pixels = r.getdata()
87+
newPixels = []
88+
for i in pixels:
89+
if i[0]==255 and i[1]==255 and i[2]==255:
90+
newPixels.append((255,255,255,0))
91+
else:
92+
newPixels.append(i)
93+
r.putdata(newPixels)
94+
return r
95+
96+
"""
97+
image = Image.open(urllib.request.urlopen("https://static.independent.co.uk/s3fs-public/thumbnails/image/2015/06/06/15/Chris-Pratt.jpg?w968h681"))
98+
image = np.array(image)
99+
image = image[:,:,::-1].copy()
100+
pred = Segmentor()
101+
output = pred.predict(image)
102+
103+
final = pred.decompose(image,output)
104+
105+
106+
for pic in final:
107+
print(pic)
108+
final[pic].show()
109+
input()
110+
"""
111+
112+
113+
114+
115+
116+

fastapi/requirements.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
fastapi==0.58.0
2+
pillow==7.1.2
3+
torch==1.5.0+cpu
4+
torchvision==0.6.0+cpu
5+
python-multipart==0.0.5
6+
aiofiles==0.4.0
7+
pycocotools>=2.0.1
8+
opencv-python==4.3.0.36
9+

fastapi/server.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
from fastapi import FastAPI, File
2+
from starlette.responses import FileResponse
3+
from maskrcnn import Segmentor
4+
from zipfile import ZipFile
5+
from PIL import Image
6+
import io
7+
import numpy as np
8+
9+
10+
#model = get_segmentator()
11+
model = Segmentor()
12+
13+
app = FastAPI(title="Image Decomposer",
14+
description='''Get the image decomposed into instances using the neural
15+
network model Mask R-CNN implemented in detectron2 library.''',
16+
version="0.1.0",
17+
)
18+
19+
20+
@app.post("/segmentation")
21+
def get_segmentation_map(file: bytes = File(...)):
22+
image = Image.open(io.BytesIO(file)).convert("RGB")
23+
image = np.array(image)
24+
image = image[:,:,::-1].copy()
25+
output = model.predict(image)
26+
instances = model.decompose(image, output)
27+
28+
with ZipFile('cont.zip', 'w') as zipObj:
29+
for key in instances:
30+
instances[key].save(key+".png")
31+
zipObj.write(key+".png")
32+
33+
return FileResponse('cont.zip')

streamlit/Dockerfile

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
FROM tiangolo/uvicorn-gunicorn:python3.7
2+
3+
RUN mkdir /streamlit
4+
5+
COPY requirements.txt /streamlit
6+
7+
WORKDIR /streamlit
8+
9+
RUN pip install -r requirements.txt
10+
11+
COPY . /streamlit
12+
13+
EXPOSE 8501
14+
15+
CMD ["streamlit", "run", "ui.py"]

streamlit/requirements.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
streamlit==0.61.0
2+
requests==2.24.0
3+
requests-toolbelt==0.9.1

streamlit/ui.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import streamlit as st
2+
from requests_toolbelt.multipart.encoder import MultipartEncoder
3+
import requests
4+
from PIL import Image
5+
import io
6+
import zipfile
7+
import glob
8+
import os
9+
10+
11+
st.title('Image Decomposer')
12+
13+
# fastapi endpoint
14+
url = 'http://fastapi:8000'
15+
endpoint = '/segmentation'
16+
17+
st.write('''This application decomposes the image into multiple images of
18+
objects in the original image. Implemented using Mask R-CNN model of
19+
detectron2 library. The app can be used to get rid of the background, to
20+
separate specific objects from the rest of the image, or/and image analysis.''') # description and instructions
21+
22+
image = st.file_uploader('insert image') # image upload widget
23+
24+
25+
def process(image, server_url: str):
26+
27+
m = MultipartEncoder(
28+
fields={'file': ('filename', image, 'image/jpeg')}
29+
)
30+
31+
r = requests.post(server_url,
32+
data=m,
33+
headers={'Content-Type': m.content_type},
34+
timeout=8000)
35+
36+
return r
37+
38+
39+
if st.button('Get segmentation map'):
40+
r = process(image, url+endpoint)
41+
z = zipfile.ZipFile(io.BytesIO(r.content))
42+
z.extractall()
43+
image_list = []
44+
for filename in glob.glob('*.png'):
45+
im=Image.open(filename)
46+
image_list.append(im)
47+
st.image(image_list, width=300) # output dyptich
48+
for filename in glob.glob('*.png'):
49+
os.remove(filename)

0 commit comments

Comments
 (0)