init
This commit is contained in:
commit
9be1dab6f3
|
|
@ -0,0 +1,3 @@
|
|||
assets/*
|
||||
*.jpg
|
||||
beerds.json
|
||||
Binary file not shown.
Binary file not shown.
|
|
@ -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}")
|
||||
|
|
@ -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}")
|
||||
|
|
@ -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])
|
||||
|
|
@ -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"]
|
||||
|
||||
|
|
@ -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>
|
||||
|
|
@ -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)
|
||||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue