mobile + new models
Gitea Actions Demo / build_and_push (push) Successful in 23s
Details
Gitea Actions Demo / build_and_push (push) Successful in 23s
Details
This commit is contained in:
parent
1ac9bc2ecb
commit
60e194b2c9
|
|
@ -0,0 +1 @@
|
|||
*.pth filter=lfs diff=lfs merge=lfs -text
|
||||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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__":
|
||||
|
|
|
|||
|
|
@ -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__":
|
||||
|
|
|
|||
10
ml/train.py
10
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 = []
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="yandex-verification" content="2d4efced567f0f7f" />
|
||||
<meta name="google-site-verification" content="gKPSnPZ1ULUF9amD0vw_JQqkS5GLqc937UxayaN_s-I" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
{% block meta %}{% endblock %}
|
||||
<link rel="icon" type="image/x-icon" href="static/favicon.ico">
|
||||
<title>{% block title %}{% endblock %}</title>
|
||||
<link rel="stylesheet" href="static/styles.css">
|
||||
<!-- Yandex.Metrika counter -->
|
||||
<script type="text/javascript" >
|
||||
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
|
||||
m[i].l=1*new Date();
|
||||
for (var j = 0; j < document.scripts.length; j++) {if (document.scripts[j].src === r) { return; }}
|
||||
k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
|
||||
(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
|
||||
|
||||
ym(93420354, "init", {
|
||||
clickmap:true,
|
||||
trackLinks:true,
|
||||
accurateTrackBounce:true
|
||||
});
|
||||
</script>
|
||||
<noscript><div><img src="https://mc.yandex.ru/watch/93420354" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
|
||||
<!-- /Yandex.Metrika counter -->
|
||||
</head>
|
||||
<body>
|
||||
<section id="main">
|
||||
<div id="menu">
|
||||
<ul>
|
||||
<li><a href = "/">Собаки</a></li>
|
||||
<li><a href = "/cats">Кошки</a></li>
|
||||
<li><a href = "/contacts">Контакты</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
{% block content %}{% endblock %}
|
||||
{% block form %}{% endblock %}
|
||||
</body>
|
||||
</section>
|
||||
<script src="static/scripts.js"></script>
|
||||
|
||||
</html>
|
||||
|
|
@ -1,50 +1,25 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="yandex-verification" content="2d4efced567f0f7f" />
|
||||
<meta name="google-site-verification" content="gKPSnPZ1ULUF9amD0vw_JQqkS5GLqc937UxayaN_s-I" />
|
||||
<meta name="description" content="Опередление породы кошки по фото. Определение породы происходит при помощи нейронной сети - точность опеределения составляет 70%." />
|
||||
<link rel="icon" type="image/x-icon" href="static/favicon.ico">
|
||||
<title>Определение породы кошки по фото</title>
|
||||
<link rel="stylesheet" href="static/styles.css">
|
||||
<!-- Yandex.Metrika counter -->
|
||||
<script type="text/javascript" >
|
||||
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
|
||||
m[i].l=1*new Date();
|
||||
for (var j = 0; j < document.scripts.length; j++) {if (document.scripts[j].src === r) { return; }}
|
||||
k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
|
||||
(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
|
||||
{% extends "base.html" %}
|
||||
|
||||
ym(93420354, "init", {
|
||||
clickmap:true,
|
||||
trackLinks:true,
|
||||
accurateTrackBounce:true
|
||||
});
|
||||
</script>
|
||||
<noscript><div><img src="https://mc.yandex.ru/watch/93420354" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
|
||||
<!-- /Yandex.Metrika counter -->
|
||||
</head>
|
||||
<body>
|
||||
<section id="main">
|
||||
<h1>Определить породу кошки по фото</h1>
|
||||
<p>Узнать породу <a href = "/">Собаки</a></p>
|
||||
<p>Загрузите фото, чтобы опеределить породу собаки или щенка. Если порода смешанная (или порода определена неточно), после загрузки будет показана вероятность породы животного.</p>
|
||||
<p>Определение породы происходит при помощи нейронной сети - точность опеределения составляет 60%, сеть обучена на 65 породах. Если на фото будет неизвестная порода или не кошка - сеть не сможет правильно опеределить, что это.</p>
|
||||
<p>Для распознования все фото отправляются на сервер, но там не сохраняются</p>
|
||||
<form enctype="multipart/form-data" method="post" action="/beerds/cats" onsubmit="SavePhoto(this);return false">
|
||||
<p><input type="file" name="f" id="file-input">
|
||||
<input type="submit" value="Определить"></p>
|
||||
</form>
|
||||
<div>
|
||||
<div id="upload-image">
|
||||
<div id="upload-image-text"></div>
|
||||
<img id="image" style="max-width: 200px;"/>
|
||||
</div>
|
||||
<div id="result"></div>
|
||||
</div>
|
||||
</body>
|
||||
</section>
|
||||
<script src="static/scripts.js"></script>
|
||||
|
||||
</html>
|
||||
{% block meta %}
|
||||
<meta name="description" content="Опередление породы кошки по фото. Определение породы происходит при помощи нейронной сети - точность опеределения составляет 70%." />
|
||||
{% endblock %}
|
||||
{% block title %}Определение породы кошки по фото{% endblock %}
|
||||
{% block content %}
|
||||
<h1>Определить породу кошки по фото</h1>
|
||||
<p>Загрузите фото, чтобы опеределить породу собаки или щенка. Если порода смешанная (или порода определена неточно), после загрузки будет показана вероятность породы животного.</p>
|
||||
<p>Определение породы происходит при помощи нейронной сети - точность опеределения составляет 60%, сеть обучена на 65 породах. Если на фото будет неизвестная порода или не кошка - сеть не сможет правильно опеределить, что это.</p>
|
||||
<p>Для распознования все фото отправляются на сервер, но там не сохраняются</p>
|
||||
{% endblock %}
|
||||
{% block form %}
|
||||
<form enctype="multipart/form-data" method="post" action="/beerds/cats" onsubmit="SavePhoto(this);return false">
|
||||
<input type="file" name="f" id="file-input">
|
||||
<input type="submit" value="Определить">
|
||||
</form>
|
||||
<div>
|
||||
<div id="upload-image">
|
||||
<div id="upload-image-text"></div>
|
||||
<img id="image" style="max-width: 200px;"/>
|
||||
</div>
|
||||
<div id="result"></div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block meta %}
|
||||
<meta name="description" content="Опередление породы собаки по фото. Определение породы происходит при помощи нейронной сети - точность опеределения составляет 80%." />
|
||||
{% endblock %}
|
||||
{% block title %}Контакты. Определение породы собаки или кошки по фото{% endblock %}
|
||||
{% block content %}
|
||||
<h1>Как можно связаться</h1>
|
||||
<ul>
|
||||
<li>Email: <i>artem@webart-tech.ru</i></li>
|
||||
<li>VK: <a href="https://vk.com/dogs_beers?from=groups" target="_blank">Группа VK</a></li>
|
||||
</ul>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block meta %}
|
||||
<meta name="description" content="Опередление породы собаки по фото. Определение породы происходит при помощи нейронной сети - точность опеределения составляет 80%." />
|
||||
{% endblock %}
|
||||
{% block title %}Определение породы собаки по фото{% endblock %}
|
||||
{% block content %}
|
||||
<h1>Определить породу собаки по фото</h1>
|
||||
<p>Загрузите фото, чтобы опеределить породу собаки или щенка. Если порода смешанная (или порода определена неточно), после загрузки будет показана вероятность породы животного.</p>
|
||||
<p>Определение породы происходит при помощи нейронной сети - точность опеределения составляет 80%, сеть обучена на <a href="https://vk.com/albums-220240483" target="_blank">125 породах</a>. Если на фото будет неизвестная порода или не собака - сеть не сможет правильно опеределить, что это.</p>
|
||||
<p>Для распознования все фото отправляются на сервер, но там не сохраняются</p>
|
||||
{% endblock %}
|
||||
{% block form %}
|
||||
<form enctype="multipart/form-data" method="post" action="/beerds/dogs" onsubmit="SavePhoto(this);return false">
|
||||
<input type="file" name="f" id="file-input">
|
||||
<input type="submit" value="Определить">
|
||||
</form>
|
||||
<div>
|
||||
<div id="upload-image">
|
||||
<div id="upload-image-text"></div>
|
||||
<img id="image" style="max-width: 200px;"/>
|
||||
</div>
|
||||
<div id="result"></div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="yandex-verification" content="2d4efced567f0f7f" />
|
||||
<meta name="google-site-verification" content="gKPSnPZ1ULUF9amD0vw_JQqkS5GLqc937UxayaN_s-I" />
|
||||
<meta name="description" content="Опередление породы собаки по фото. Определение породы происходит при помощи нейронной сети - точность опеределения составляет 80%." />
|
||||
<link rel="icon" type="image/x-icon" href="static/favicon.ico">
|
||||
<title>Определение породы собаки по фото</title>
|
||||
<link rel="stylesheet" href="static/styles.css">
|
||||
<!-- Yandex.Metrika counter -->
|
||||
<script type="text/javascript" >
|
||||
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
|
||||
m[i].l=1*new Date();
|
||||
for (var j = 0; j < document.scripts.length; j++) {if (document.scripts[j].src === r) { return; }}
|
||||
k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
|
||||
(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
|
||||
|
||||
ym(93420354, "init", {
|
||||
clickmap:true,
|
||||
trackLinks:true,
|
||||
accurateTrackBounce:true
|
||||
});
|
||||
</script>
|
||||
<noscript><div><img src="https://mc.yandex.ru/watch/93420354" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
|
||||
<!-- /Yandex.Metrika counter -->
|
||||
</head>
|
||||
<body>
|
||||
<section id="main">
|
||||
<h1>Определить породу собаки по фото</h1>
|
||||
<p>Узнать породу <a href = "/cats">Кошки</a></p>
|
||||
<p>Загрузите фото, чтобы опеределить породу собаки или щенка. Если порода смешанная (или порода определена неточно), после загрузки будет показана вероятность породы животного.</p>
|
||||
<p>Определение породы происходит при помощи нейронной сети - точность опеределения составляет 60%, сеть обучена на <a href="https://vk.com/albums-220240483" target="_blank">125 породах</a>. Если на фото будет неизвестная порода или не собака - сеть не сможет правильно опеределить, что это.</p>
|
||||
<p>Для распознования все фото отправляются на сервер, но там не сохраняются</p>
|
||||
<form enctype="multipart/form-data" method="post" action="/beerds/dogs" onsubmit="SavePhoto(this);return false">
|
||||
<p><input type="file" name="f" id="file-input">
|
||||
<input type="submit" value="Определить"></p>
|
||||
</form>
|
||||
<div>
|
||||
<div id="upload-image">
|
||||
<div id="upload-image-text"></div>
|
||||
<img id="image" style="max-width: 200px;"/>
|
||||
</div>
|
||||
<div id="result"></div>
|
||||
</div>
|
||||
</body>
|
||||
</section>
|
||||
<script src="static/scripts.js"></script>
|
||||
|
||||
</html>
|
||||
Loading…
Reference in New Issue