This commit is contained in:
artem 2023-04-27 12:53:21 +03:00
commit 9be1dab6f3
11 changed files with 384 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
assets/*
*.jpg
beerds.json

BIN
beerd_25_04_2023.keras Normal file

Binary file not shown.

Binary file not shown.

107
beerds.py Normal file
View File

@ -0,0 +1,107 @@
import os
import random
import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras.utils import image_dataset_from_directory, split_dataset
img_size = (200, 200)
# обогащение выборки
data_augmentation = keras.Sequential(
[
layers.RandomFlip("horizontal"),
layers.RandomRotation(0.1),
layers.RandomZoom(0.2),
]
)
input_dir = "assets/dog"
labels_dict = {}
for fname in os.listdir(input_dir):
if fname in labels_dict:
continue
labels_dict[fname] = len(labels_dict)
model_name = "beerd_25_04_2023.keras"
train_dataset, val_ds = image_dataset_from_directory(
input_dir,
labels="inferred",
label_mode="categorical",
class_names=None,
color_mode="rgb",
batch_size=32,
seed=12,
image_size=img_size,
shuffle=True,
validation_split=0.1,
subset="both",
interpolation="bilinear",
follow_links=False,
crop_to_aspect_ratio=False
)
validation_dataset, test_dataset = split_dataset(val_ds, left_size=0.8)
inputs = keras.Input(shape=img_size + (3,))
x = data_augmentation(inputs)
x = layers.Rescaling(1./255)(x)
x = layers.Conv2D(filters=32, kernel_size=5, use_bias=False)(x)
for size in [32, 64, 128, 256, 512, 1024]:
residual = x
x = layers.BatchNormalization()(x)
x = layers.Activation("relu")(x)
x = layers.SeparableConv2D(size, 3, padding="same", use_bias=False)(x)
x = layers.BatchNormalization()(x)
x = layers.Activation("relu")(x)
x = layers.SeparableConv2D(size, 3, padding="same", use_bias=False)(x)
x = layers.MaxPooling2D(3, strides=2, padding="same")(x)
residual = layers.Conv2D(
size, 1, strides=2, padding="same", use_bias=False)(residual)
x = layers.add([x, residual])
x = layers.GlobalAveragePooling2D()(x)
x = layers.Dropout(0.5)(x)
outputs = layers.Dense(len(labels_dict), activation="softmax")(x)
model = keras.Model(inputs, outputs)
model.compile(optimizer="rmsprop",
loss="categorical_crossentropy", metrics=['accuracy'])
callbacks = [
keras.callbacks.ModelCheckpoint(model_name,
save_best_only=True)
]
history = model.fit(train_dataset,
epochs=200,
callbacks=callbacks,
validation_data=validation_dataset,)
epochs = range(1, len(history.history["loss"]) + 1)
loss = history.history["loss"]
val_loss = history.history["val_loss"]
acc = history.history["accuracy"]
val_acc = history.history["val_accuracy"]
plt.plot(epochs, acc, "bo", label="Точность на этапе обучения")
plt.plot(epochs, val_acc, "b", label="Точность на этапе проверки")
plt.title("Точность на этапах обучения и проверки")
plt.legend()
plt.figure()
plt.plot(epochs, loss, "bo", label="Потери на этапе обучения")
plt.plot(epochs, val_loss, "b", label="Потери на этапе проверки")
plt.title("Потери на этапах обучения и проверки")
plt.legend()
plt.show()
test_model = keras.models.load_model(model_name)
test_loss, test_acc = test_model.evaluate(test_dataset)
print(f"Test accuracy: {test_acc:.3f}")

100
beerds_imagenet.py Normal file
View File

@ -0,0 +1,100 @@
import os
import random
import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras.utils import image_dataset_from_directory, split_dataset
img_size = (180, 180)
conv_base = keras.applications.vgg16.VGG16(
weights="imagenet",
include_top=False,
input_shape=(180, 180, 3))
conv_base.trainable = False
# обогащение выборки
data_augmentation = keras.Sequential(
[
layers.RandomFlip("horizontal"),
layers.RandomRotation(0.1),
layers.RandomZoom(0.2),
])
input_dir = "assets/dog"
labels_dict = {}
for fname in os.listdir(input_dir):
if fname in labels_dict:
continue
labels_dict[fname] = len(labels_dict)
model_name = "beerd_imagenet_25_04_2023.keras"
train_dataset, val_ds = image_dataset_from_directory(
input_dir,
labels="inferred",
label_mode="categorical",
class_names=None,
color_mode="rgb",
batch_size=32,
seed=12,
image_size=img_size,
shuffle=True,
validation_split=0.1,
subset="both",
interpolation="bilinear",
follow_links=False,
crop_to_aspect_ratio=False
)
validation_dataset, test_dataset = split_dataset(val_ds, left_size=0.8)
inputs = keras.Input(shape=(180, 180, 3))
x = data_augmentation(inputs)
x = keras.applications.vgg16.preprocess_input(x)
x = conv_base(x)
x = layers.Flatten()(x)
x = layers.Dense(512)(x)
x = layers.Dropout(0.5)(x)
outputs = layers.Dense(len(labels_dict), activation="softmax")(x)
model = keras.Model(inputs, outputs)
model.compile(optimizer="rmsprop",
loss="categorical_crossentropy", metrics=['accuracy'])
callbacks = [
keras.callbacks.ModelCheckpoint(model_name,
save_best_only=True)
]
history = model.fit(train_dataset,
epochs=100,
callbacks=callbacks,
validation_data=validation_dataset,)
epochs = range(1, len(history.history["loss"]) + 1)
loss = history.history["loss"]
val_loss = history.history["val_loss"]
acc = history.history["accuracy"]
val_acc = history.history["val_accuracy"]
plt.plot(epochs, acc, "bo", label="Точность на этапе обучения")
plt.plot(epochs, val_acc, "b", label="Точность на этапе проверки")
plt.title("Точность на этапах обучения и проверки")
plt.legend()
plt.figure()
plt.plot(epochs, loss, "bo", label="Потери на этапе обучения")
plt.plot(epochs, val_loss, "b", label="Потери на этапе проверки")
plt.title("Потери на этапах обучения и проверки")
plt.legend()
plt.show()
test_model = keras.models.load_model(model_name)
test_loss, test_acc = test_model.evaluate(test_dataset)
print(f"Test accuracy: {test_acc:.3f}")

44
beerds_val.py Normal file
View File

@ -0,0 +1,44 @@
import os
os.environ['CUDA_VISIBLE_DEVICES'] = '-1'
import json
import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras.utils import load_img, img_to_array
from tensorflow.keras.utils import image_dataset_from_directory
# model_name = "beerd_25_04_2023.keras"
model_name = "beerd_imagenet_25_04_2023.keras"
img = load_img("photo_2023-04-25_10-02-25.jpg", color_mode="rgb")
img = tf.image.resize(img, (180, 180, ), "bilinear")
img_array = img_to_array(img)
test_model = keras.models.load_model(model_name)
test_loss = test_model.predict(np.expand_dims(img_array, 0))
list_labels = [fname for fname in os.listdir("assets/dog")]
list_labels.sort()
dict_names = {}
for i, label in enumerate(list_labels):
dict_names[i] = label
with open("beerds.json", "w") as f:
f.write(json.dumps(dict_names))
max_val = 0
max_num = 0
for i, val in enumerate(test_loss[0]):
if val < max_val:
continue
max_val = val
max_num = i
print("-----------------------")
print(list_labels)
print(test_loss)
print(max_num, max_val, dict_names[max_num])

14
server/Dockerfile Normal file
View File

@ -0,0 +1,14 @@
FROM python:3.10
COPY requirements.txt /app/requirements.txt
WORKDIR /app
RUN pip3 install --upgrade pip
RUN pip3 install -r requirements.txt
COPY . /app/
EXPOSE 4150
WORKDIR /app/external_api
ENTRYPOINT ["python", "main.py"]

17
server/index.html Normal file
View File

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Определение породы собаки по фото</title>
</head>
<body>
<form enctype="multipart/form-data" method="post" action="/beeds" onsubmit="SavePhoto();return false">
<p><input type="file" name="f" id="file-input">
<input type="submit" value="Отправить"></p>
</form>
<div id="result"></div>
<img id="image" />
</body>
<script src="static/scripts.js"></script>
</html>

65
server/main.py Normal file
View File

@ -0,0 +1,65 @@
from PIL import Image
from sanic import Sanic
from sanic.response import json as json_answer
import numpy as np
from tensorflow import keras
from tensorflow.keras.utils import img_to_array
import io
import os
import json
os.environ['CUDA_VISIBLE_DEVICES'] = '-1'
app = Sanic("Ai")
model_name = "../beerd_imagenet_25_04_2023.keras"
test_model_imagenet = keras.models.load_model(model_name)
model_name = "../beerd_25_04_2023.keras"
test_model = keras.models.load_model(model_name)
list_labels = [fname for fname in os.listdir("../assets/dog")]
list_labels.sort()
dict_names = {}
with open("beerds.json", "r") as f:
dict_names = json.loads(f.read())
app.static("/", "index.html", name="main")
app.static("/static/", "static/", name="static")
@app.post("/beeds")
async def beeds(request):
body = request.files.get("f").body
img = Image.open(io.BytesIO(body))
img = img.convert('RGB')
img_net = img.resize((180, 180, ), Image.BILINEAR)
img_array = img_to_array(img_net)
test_loss_image_net = test_model_imagenet.predict(
np.expand_dims(img_array, 0))
img = img.resize((200, 200, ), Image.BILINEAR)
img_array = img_to_array(img)
test_loss = test_model.predict(np.expand_dims(img_array, 0))
result = {}
for i, val in enumerate(test_loss[0]):
if val <= 0.09:
continue
result[val] = dict_names[str(i)]
result_net = {}
for i, val in enumerate(test_loss_image_net[0]):
if val <= 0.09:
continue
result_net[val] = dict_names[str(i)]
return json_answer({
"results": dict(sorted(result.items(), reverse=True)),
"results_net": dict(sorted(result_net.items(), reverse=True)),
})
if __name__ == "__main__":
app.run(auto_reload=True)

10
server/requirements.txt Normal file
View File

@ -0,0 +1,10 @@
keras==2.12.0
matplotlib==3.7.1
numpy==1.23.5
pandas==2.0.0
Pillow==9.4.0
sanic==23.3.0
scipy==1.10.1
tensorflow==2.12.0
ujson==5.7.0

24
server/static/scripts.js Normal file
View File

@ -0,0 +1,24 @@
async function SavePhoto()
{
let photo = document.getElementById("file-input").files[0];
let formData = new FormData();
formData.append("f", photo);
let response = await fetch('/beeds', {method: "POST", body: formData});
if (response.ok) {
let json = await response.json();
var text = ""
for (let key in json.results_net) {
text += "<div>" + json.results_net[key] + ": " + key + "</div>"
}
for (let key in json.results) {
text += "<div>" + json.results[key] + ": " + key + "</div>"
}
document.getElementById("result").innerHTML = text;
let urlCreator = window.URL || window.webkitURL;
let imageUrl = urlCreator.createObjectURL(photo);
document.getElementById("image").src = imageUrl;
} else {
alert("Ошибка HTTP: " + response.status);
}
}