03 Details

Details of idea(Setup environment~Web development)

Minju Lee

1. Development Environment Setup

Using Docker to set web development environment

1-1) Dockerfile
FROM python:3.7.8 # Base Image
LABEL maintainer "WLU" # Maincontainer
RUN pip install --upgrade pip # Upgrade pip
COPY . /path
WORKDIR /path # applied to RUN, CMD
RUN pip install --no-cache-dir -r requirements.txt # install Python modules
# copied files required for the app to run
COPY app.py /path/
COPY templates/ /path/templates/
COPY static/ /path/static/
EXPOSE 80 #Port number the container should expose
CMD ["python", "./app.py"] # Run the application

Docker+flask


1-2) docker-compose.yml

version: '3.3' #version
services:
welungu: #service name
build: . #current path
ports: #open port
- "80:80"

Specify the version at the beginning of the docker-compose.yml. Define a service named 'welungu' and it starts the container after building an image of the configuration defined in Dockerfile(build:) and exposing port 80 to the outside(port:).


1-3) requirements.txt
Flask==1.1.2
werkzeug
torchvision
torch

Put python modules needed by the app in requirements.txt.


reference: 완벽한 IT 인프라 구축을 위한 Docker 2판(Asa Shiho 지음, 이영란 옮김)




2. Web Development

2-1) File upload & Model load


def get_instance_segmentation_model(num_classes):
# Load a model pre-trained pre-trained on COCO
model = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=True)

# Replace the classifier with a new one, that has
# num_classes which is user-defined
# Get number of input features for the classifier
in_features = model.roi_heads.box_predictor.cls_score.in_features
# Replace the pre-trained head with a new one
model.roi_heads.box_predictor = FastRCNNPredictor(in_features, num_classes)
return model


def drawPrediction(img, prediction):
#image = Image.fromarray(img.mul(255).permute(1, 2, 0).byte().numpy())
draw = ImageDraw.Draw(img)
results = [0.0, 0.0, 0.0]

for element in range(len(prediction[0]["boxes"])):
boxes = prediction[0]["boxes"][element].detach().numpy()
score = np.round(prediction[0]["scores"][element].detach().numpy() , decimals=4)
temp = []

label = int(prediction[0]["labels"][element].detach().numpy())

if label == 1 : temp.extend(["covid-19", "red"])
elif label == 2 : temp.extend(["nodule", "blue"])
elif label == 3 : temp.extend(["cancer", "green"])

if results[label-1] < round(score*100, 2) : results[label-1] = round(score*100, 2)

if score > 0.5 :
draw.text((boxes[0], boxes[1]-20), text=temp[0])
draw.rectangle([(boxes[0], boxes[1]), (boxes[2], boxes[3])], outline=temp[1], width=3)
draw.text((boxes[0], boxes[1]-10), text=str(round(score*100, 2))+" %")

img.save("./static/img/predict.png")
return results
@app.route('/check', methods=['GET', 'POST'])
def check():
if request.method == 'POST':
# 파일이 없을 때
if request.files['file'] is None:
return render_template('check.html', title='Check', check_message_test='empty')
else:
file = request.files['file']
file.save(secure_filename(file.filename))

model = get_instance_segmentation_model(4)
model.load_state_dict(torch.load("model_epoch100.pth", map_location=torch.device('cpu')))

img = Image.open(file.filename).convert('RGB')
copy = torchvision.transforms.ToTensor()(img).unsqueeze(0)

model.eval()
prediction = model(copy)
results = drawPrediction(img, prediction)
disease = 'You are healty!'

if sum(results) == 0 : pass
elif results.index(max(results)) == 0 : disease = 'covid-19'
elif results.index(max(results)) == 1 : disease = 'nodule'
elif results.index(max(results)) == 2 : disease = 'cancer'

os.remove("./"+file.filename)

return render_template('check.html', title='Check', filepath="predict.png", result=disease,
c=results[0], n=results[1], LC=results[2])
else:
return render_template('check.html', title='Check', check_message_test='empty')


3. File Structure

we_Lung_u_flask

                 |-- static

                           |-- css

                           |-- fonts

                           |-- img

                           |-- js

                 |-- templates

                           |-- check.html

                           |-- contact.html

                           |-- index.html

                           |-- layout.html

                           |-- team.html

                 |-- Dockerfile

                 |-- app.py

                 |-- docker-compose.yml

                 |-- requirements.txt