Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Dockerfile
README.md
*.pyc
*.pyo
*.pyd
__pycache__
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,6 @@ venv.bak/
# mypy
.mypy_cache/

.vscode/
.vscode/

*.hdf5
20 changes: 20 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
FROM python:3.7-slim
LABEL maintainer "Manabu TERADA <[email protected]>"

RUN apt-get update -y
RUN apt-get install -y build-essential libssl-dev libxml2-dev libxslt1-dev libbz2-dev zlib1g-dev libreadline-gplv2-dev libpq-dev

RUN mkdir /code
RUN mkdir /code/log
WORKDIR /code

RUN pip install -U pip setuptools
ADD requirements.txt .
ADD . /code/
RUN pip install -e . -c requirements.txt

#RUN pip freeze > /work/requirements.txt

EXPOSE 8080
CMD ["uwsgi","--emperor","/code/uwsgi.ini", "--logto", "/code/log/emperor.log"]
# CMD ["/bin/sh"]
17 changes: 17 additions & 0 deletions Dockerfile.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
FROM tensorflow/tensorflow:1.12.0-py3

RUN mkdir /code
RUN mkdir /code/log
WORKDIR /code

RUN pip install -U pip setuptools
ADD requirements.txt .
ADD . /code/
RUN pip install -e . -c requirements-detector.txt

#RUN pip freeze > /work/requirements.txt

# EXPOSE 8080
CMD ["python","mahjong_sample_web_app/detector/detector.py"]
# CMD ["uwsgi","--emperor","/code/uwsgi.ini", "--logto", "/code/log/emperor.log"]
# CMD ["/bin/sh"]
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,15 @@ $ pip install -e .["test"]
$ pytest -v
```


# Docker環境

```
$ docker build . -t local/mahjong_sample
$ docker run --rm -it -p 8080:8080 -v $PWD/log:/code/log local/mahjong_sample
```

```
$ docker build -t local/mahjong_sample_tf -f Dockerfile.tf .
$ docker run --rm -it local/mahjong_sample_tf
```
Empty file.
83 changes: 83 additions & 0 deletions mahjong_sample_web_app/detector/detector.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
from pathlib import Path
import numpy as np

# from scipy.misc import imresize
from PIL import Image as pil_image
from keras.preprocessing import image
from postprocess import PostProcess
from ssd.ssd import SingleShotMultiBoxDetector


model_file = Path(__file__).parent / "models" / "weights.25-0.05.hdf5"
param_file = (
Path(__file__).parent / "models" / "ssd300_params_mahjong_vgg16_train_2.json"
)


def model_build(model_file, param_file):
ssd = SingleShotMultiBoxDetector(
overlap_threshold=0.5, nms_threshold=0.45, max_output_size=400
)
ssd.load_parameters(str(param_file))
ssd.build(init_weight=str(model_file))
return ssd


def _add_margin(img):
img_shape = list(img.shape)
if img_shape[0] == img_shape[1]:
return img
if img_shape[0] < img_shape[1]:
min_arg = 0
max_arg = 1
else:
min_arg = 1
max_arg = 0
margin_shape = img_shape
margin_shape[min_arg] = int((img_shape[max_arg] - img_shape[min_arg]) / 2.0)
margin = np.tile([0.0], margin_shape)
new_img = np.concatenate([margin, img], axis=min_arg)
new_img = np.concatenate([new_img, margin], axis=min_arg)
return new_img


def pred(ssd, img):
inputs = np.array([img.copy()])
results = ssd.detect(inputs, batch_size=1, verbose=1, do_preprocess=True)
return results


def load_image(img_obj, input_shape=(512, 512)):
# img = image.load_img(img_path)
img = pil_image.open(img_obj)
if img.mode != "RGB":
img = img.convert("RGB")

img_array = image.img_to_array(img)
new_img = _add_margin(img_array)
new_img_float = np.array(
pil_image.fromarray(new_img.astype("uint8")).resize(
size=input_shape # , resample=pil_image.BICUBIC
)
).astype("float32")
# new_img_float = imresize(new_img, input_shape).astype("float32")
return new_img_float


def detect(img_obj):
img = load_image(img_obj)
ssd = model_build(model_file, param_file)
pred_result = pred(ssd, img)

pp = PostProcess(ssd.class_names, pred_threshold=0.9)
pp.set_top_score(pred_result)
list_label = pp.get_list_pi()
# pp.save_image(img, pred_result, savepath)
# print(list_label)
return list_label


if __name__ == "__main__":
ssd = model_build(model_file, param_file)
print(ssd)

Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
{
"aspect_ratios": [
[
2.0,
0.5
],
[
2.0,
0.5,
3.0,
0.3333333333333333
],
[
2.0,
0.5,
3.0,
0.3333333333333333
],
[
2.0,
0.5,
3.0,
0.3333333333333333
],
[
2.0,
0.5,
3.0,
0.3333333333333333
],
[
2.0,
0.5,
3.0,
0.3333333333333333
]
],
"base_net": "vgg16",
"class_names": [
"bg",
"1m",
"2m",
"3m",
"4m",
"5m",
"6m",
"7m",
"8m",
"9m",
"1p",
"2p",
"3p",
"4p",
"5p",
"6p",
"7p",
"8p",
"9p",
"1s",
"2s",
"3s",
"4s",
"5s",
"6s",
"7s",
"8s",
"9s",
"c",
"e",
"f",
"h",
"n",
"s",
"w"
],
"input_shape": [
512,
512,
3
],
"model_type": "ssd300",
"n_classes": 35,
"scales": [
[
30.0
],
[
60.0,
114.0
],
[
114.0,
168.0
],
[
168.0,
222.0
],
[
222.0,
276.0
],
[
276.0,
330.0
]
],
"variances": [
0.1,
0.1,
0.2,
0.2
]
}
71 changes: 71 additions & 0 deletions mahjong_sample_web_app/detector/postprocess.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# import matplotlib.pyplot as plt
import numpy as np


class PostProcess:
def __init__(self, class_names, pred_threshold=0.9):
self.pred_threshold = pred_threshold
self.class_names = class_names

def set_top_score(self, pred_result):
# Parse the outputs.
det_label = pred_result[0][:, 0]
det_conf = pred_result[0][:, 1]

# get top score result
self.top_indices = [
i for i, conf in enumerate(det_conf) if conf >= self.pred_threshold
]
self.top_conf = det_conf[self.top_indices]
self.top_label_indices = det_label[self.top_indices].tolist()

def get_list_pi(self):
list_label = []
for i in range(self.top_conf.shape[0]):
label = int(self.top_label_indices[i])
label_name = self.class_names[label]
list_label.append(label_name)

return list_label

# def save_image(self, img, pred_result, savepath):
# colors = plt.cm.hsv(np.linspace(0, 1, 35)).tolist()
# plt.tick_params(
# labelbottom=False, labelleft=False, labelright=False, labeltop=False
# )
# plt.tick_params(bottom=False, left=False, right=False, top=False)

# plt.imshow(img / 255.0)
# currentAxis = plt.gca()

# det_xmin = pred_result[0][:, 2]
# det_ymin = pred_result[0][:, 3]
# det_xmax = pred_result[0][:, 4]
# det_ymax = pred_result[0][:, 5]

# top_xmin = det_xmin[self.top_indices]
# top_ymin = det_ymin[self.top_indices]
# top_xmax = det_xmax[self.top_indices]
# top_ymax = det_ymax[self.top_indices]

# for i in range(self.top_conf.shape[0]):
# xmin = int(round(top_xmin[i] * img.shape[1]))
# ymin = int(round(top_ymin[i] * img.shape[0]))
# xmax = int(round(top_xmax[i] * img.shape[1]))
# ymax = int(round(top_ymax[i] * img.shape[0]))

# label = int(self.top_label_indices[i])
# score = self.top_conf[i]
# label_name = self.class_names[label]
# display_txt = "{:0.2f}, {}".format(score, label_name)
# coords = (xmin, ymin), xmax - xmin + 1, ymax - ymin + 1
# color = colors[label]

# currentAxis.add_patch(
# plt.Rectangle(*coords, fill=False, edgecolor=color, linewidth=2)
# )
# currentAxis.text(
# xmin, ymin, display_txt, bbox={"facecolor": color, "alpha": 1.0}
# )

# plt.savefig(savepath)
Empty file.
33 changes: 33 additions & 0 deletions mahjong_sample_web_app/detector/ssd/layers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import numpy as np
import keras.backend as K
from keras.engine.topology import Layer
from keras.engine.topology import InputSpec


class L2Normalization(Layer):
"""
"""

def __init__(self, scale, **kwargs):
self.scale = scale
self.gamma = None
self.axis = None
# if K.image_dim_ordering() == "tf":
if K.image_data_format() == "tf":
self.axis = 3
else:
self.axis = 1
super(L2Normalization, self).__init__(**kwargs)

def build(self, input_shape):
self.input_spec = [InputSpec(shape=input_shape)]
shape = (input_shape[self.axis],)
self.gamma = K.variable(
self.scale * np.ones(shape), name="{}_gamma".format(self.name)
)
self.trainable_weights = [self.gamma]

def call(self, x, mask=None):
output = K.l2_normalize(x, self.axis)
output *= self.gamma
return output
Loading