diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..ec4a626 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.pth filter=lfs diff=lfs merge=lfs -text diff --git a/.gitea/workflows/ai.yaml b/.gitea/workflows/ai.yaml index 68db6eb..1788507 100644 --- a/.gitea/workflows/ai.yaml +++ b/.gitea/workflows/ai.yaml @@ -24,7 +24,7 @@ jobs: tags: gitea.webart-tech.ru/webart/beerds/backend:${{ gitea.sha }} - name: Deploy run: | - git clone https://gitea.webart-tech.ru/webart/kuber-deploy.git deploy + git clone https://${{ secrets.DOCKER_USERNAME }}:${{ secrets.DOCKER_PASSWORD }}@gitea.webart-tech.ru/webart/kuber-deploy.git deploy cd ./deploy/ai sed -i -E 's/backend:.+/backend:${{ gitea.sha }}/g' dogs.yml git config --global user.email "deploy@deploy.deploy" diff --git a/ml/cats.py b/ml/cats.py index 8ef8396..0cd6e95 100644 --- a/ml/cats.py +++ b/ml/cats.py @@ -10,9 +10,9 @@ from train import get_labels, load_model, get_loaders, train, show, DEVICE # ty ImageFile.LOAD_TRUNCATED_IMAGES = True print(f"Using device: {DEVICE}") -IMG_SIZE = (180, 180) +IMG_SIZE = (224, 224) INPUT_DIR = "assets/cat" -NUM_EPOCHS = 10 +NUM_EPOCHS = 50 MODEL_NAME = "cats_model.pth" if __name__ == "__main__": diff --git a/ml/dogs.py b/ml/dogs.py index 6d561aa..0bd531a 100644 --- a/ml/dogs.py +++ b/ml/dogs.py @@ -10,9 +10,9 @@ from train import get_labels, load_model, get_loaders, train, show, DEVICE # ty ImageFile.LOAD_TRUNCATED_IMAGES = True print(f"Using device: {DEVICE}") -IMG_SIZE = (180, 180) +IMG_SIZE = (224, 224) INPUT_DIR = "assets/dog" -NUM_EPOCHS = 100 +NUM_EPOCHS = 50 MODEL_NAME = "dogs_model.pth" if __name__ == "__main__": diff --git a/ml/train.py b/ml/train.py index de48614..649e01e 100644 --- a/ml/train.py +++ b/ml/train.py @@ -17,8 +17,9 @@ def get_labels(input_dir, img_size): transform = transforms.Compose( [ transforms.Resize(img_size), + transforms.RandomHorizontalFlip(), transforms.ToTensor(), - transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)), + transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]) ] ) dataset = ImageFolder(root=input_dir, transform=transform) @@ -44,7 +45,10 @@ def load_model(model_path: str, labels_dict: dict, device: str = "cuda") -> nn.M if not os.path.isfile(model_path): print("Start new model") model = torchvision.models.resnet50(weights=ResNet50_Weights.DEFAULT) - model.fc = torch.nn.Linear(model.fc.in_features, len(labels_dict)) + model.fc = nn.Sequential( + nn.Dropout(0.5), # Регуляризация + torch.nn.Linear(model.fc.in_features, len(labels_dict)) + ) return model model = torch.load(model_path, map_location=device, weights_only=False) model.eval() @@ -59,7 +63,7 @@ def train( val_loader: DataLoader, ) -> Tuple[list[float], list[float], list[float], list[float]]: criterion = torch.nn.CrossEntropyLoss() - optimizer = torch.optim.Adam(model.fc.parameters(), lr=0.001, weight_decay=0.001) # type: ignore[union-attr] + optimizer = torch.optim.Adam(model.fc.parameters(), lr=1e-4) # type: ignore[union-attr] # История метрик train_loss_history = [] train_acc_history = [] diff --git a/server/main.py b/server/main.py index a905ac2..45c41af 100644 --- a/server/main.py +++ b/server/main.py @@ -48,7 +48,7 @@ with open("server/meta/labels_cats.json", "r") as f: def predict_image(image, model, device="cuda") -> list[tuple]: - img_size = (180, 180) + img_size = (224, 224) preprocess = transforms.Compose( [ transforms.Resize(img_size), @@ -119,12 +119,16 @@ class BaseController(Controller): path = "/" @get("/") - async def main(self) -> Template: - return Template(name="index.html") + async def dogs(self) -> Template: + return Template(name="dogs.html") @get("/cats") async def cats(self) -> Template: return Template(name="cats.html") + + @get("/contacts") + async def contacts(self) -> Template: + return Template(name="contacts.html") @get("/sitemap.xml", media_type=MediaType.XML) async def sitemaps(self) -> bytes: diff --git a/server/models/cats_model.pth b/server/models/cats_model.pth index 339ce16..1267412 100644 Binary files a/server/models/cats_model.pth and b/server/models/cats_model.pth differ diff --git a/server/models/dogs_model.pth b/server/models/dogs_model.pth index 032efbf..594c972 100644 Binary files a/server/models/dogs_model.pth and b/server/models/dogs_model.pth differ diff --git a/server/static/styles.css b/server/static/styles.css index b83be46..e2f16dd 100644 --- a/server/static/styles.css +++ b/server/static/styles.css @@ -25,7 +25,9 @@ h1 { form { border: 1px solid #696969; - padding: 0 10px 0 10px; + padding: 2px 10px 2px 10px; + display: flex; + justify-content: space-between; } #main { @@ -54,4 +56,66 @@ form { .image-results { text-align: center; -} \ No newline at end of file +} + +#menu { + padding: 0.5rem 0; + border-bottom: 1px solid #dee2e6; /* Серая разделительная линия */ +} + +#menu ul { + list-style-type: none; + margin: 0; + padding: 0; + display: flex; + gap: 2rem; +} + +#menu li { + margin: 0; + padding: 0; +} + +#menu a { + text-decoration: none; + color: #696969; /* Темно-серый цвет */ + font-size: 1.1rem; + transition: color 0.2s ease; + position: relative; +} + +#menu a:hover { + color: #212529; /* Чёрный при наведении */ +} + +/* Стиль для активной ссылки */ +#menu a.active { + color: #212529; + font-weight: 500; +} + +#menu a.active::after { + content: ""; + position: absolute; + width: 100%; + height: 2px; + background-color: #696969; /* Чёрная линия для активной ссылки */ + bottom: -4px; + left: 0; +} + +input[type="submit"] { + padding: 10px; + color: #fff; + background-color: #696969; + cursor: pointer; + } + + input[type="submit"]:hover { + background-color: #212529; + } + + input[type="text"]:hover { + margin: 8px 0; + } + \ No newline at end of file diff --git a/server/templates/base.html b/server/templates/base.html new file mode 100644 index 0000000..ca79912 --- /dev/null +++ b/server/templates/base.html @@ -0,0 +1,44 @@ + + + + + + + + {% block meta %}{% endblock %} + + {% block title %}{% endblock %} + + + + + + + +
+ + {% block content %}{% endblock %} + {% block form %}{% endblock %} + +
+ + + diff --git a/server/templates/cats.html b/server/templates/cats.html index 03d10a4..29999a6 100644 --- a/server/templates/cats.html +++ b/server/templates/cats.html @@ -1,50 +1,25 @@ - - - - - - - - - Определение породы кошки по фото - - - - - - - -
-

Определить породу кошки по фото

-

Узнать породу Собаки

-

Загрузите фото, чтобы опеределить породу собаки или щенка. Если порода смешанная (или порода определена неточно), после загрузки будет показана вероятность породы животного.

-

Определение породы происходит при помощи нейронной сети - точность опеределения составляет 60%, сеть обучена на 65 породах. Если на фото будет неизвестная порода или не кошка - сеть не сможет правильно опеределить, что это.

-

Для распознования все фото отправляются на сервер, но там не сохраняются

-
-

-

-
-
-
-
- -
-
-
- -
- - - +{% block meta %} + +{% endblock %} +{% block title %}Определение породы кошки по фото{% endblock %} +{% block content %} +

Определить породу кошки по фото

+

Загрузите фото, чтобы опеределить породу собаки или щенка. Если порода смешанная (или порода определена неточно), после загрузки будет показана вероятность породы животного.

+

Определение породы происходит при помощи нейронной сети - точность опеределения составляет 60%, сеть обучена на 65 породах. Если на фото будет неизвестная порода или не кошка - сеть не сможет правильно опеределить, что это.

+

Для распознования все фото отправляются на сервер, но там не сохраняются

+{% endblock %} +{% block form %} +
+ + +
+
+
+
+ +
+
+
+{% endblock %} \ No newline at end of file diff --git a/server/templates/contacts.html b/server/templates/contacts.html new file mode 100644 index 0000000..5209bb8 --- /dev/null +++ b/server/templates/contacts.html @@ -0,0 +1,15 @@ +{% extends "base.html" %} + +{% block meta %} + +{% endblock %} +{% block title %}Контакты. Определение породы собаки или кошки по фото{% endblock %} +{% block content %} +

Как можно связаться

+ +{% endblock %} + + diff --git a/server/templates/dogs.html b/server/templates/dogs.html new file mode 100644 index 0000000..31da96f --- /dev/null +++ b/server/templates/dogs.html @@ -0,0 +1,25 @@ +{% extends "base.html" %} + +{% block meta %} + +{% endblock %} +{% block title %}Определение породы собаки по фото{% endblock %} +{% block content %} +

Определить породу собаки по фото

+

Загрузите фото, чтобы опеределить породу собаки или щенка. Если порода смешанная (или порода определена неточно), после загрузки будет показана вероятность породы животного.

+

Определение породы происходит при помощи нейронной сети - точность опеределения составляет 80%, сеть обучена на 125 породах. Если на фото будет неизвестная порода или не собака - сеть не сможет правильно опеределить, что это.

+

Для распознования все фото отправляются на сервер, но там не сохраняются

+{% endblock %} +{% block form %} +
+ + +
+
+
+
+ +
+
+
+{% endblock %} \ No newline at end of file diff --git a/server/templates/index.html b/server/templates/index.html deleted file mode 100644 index dfe620b..0000000 --- a/server/templates/index.html +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - Определение породы собаки по фото - - - - - - - -
-

Определить породу собаки по фото

-

Узнать породу Кошки

-

Загрузите фото, чтобы опеределить породу собаки или щенка. Если порода смешанная (или порода определена неточно), после загрузки будет показана вероятность породы животного.

-

Определение породы происходит при помощи нейронной сети - точность опеределения составляет 60%, сеть обучена на 125 породах. Если на фото будет неизвестная порода или не собака - сеть не сможет правильно опеределить, что это.

-

Для распознования все фото отправляются на сервер, но там не сохраняются

-
-

-

-
-
-
-
- -
-
-
- -
- - -