flask-ML #5
@ -3,4 +3,5 @@
|
|||||||
<component name="MarkdownSettingsMigration">
|
<component name="MarkdownSettingsMigration">
|
||||||
<option name="stateVersion" value="1" />
|
<option name="stateVersion" value="1" />
|
||||||
</component>
|
</component>
|
||||||
|
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.11 (Projekt_IO)" project-jdk-type="Python SDK" />
|
||||||
</project>
|
</project>
|
6
docker/.dockerignore
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
*.md
|
||||||
|
/venv
|
||||||
|
.git
|
||||||
|
__pycache__
|
||||||
|
.pytest_cache
|
||||||
|
/tests
|
17
docker/Dockerfile
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# Użyj obrazu bazowego Python 3.8
|
||||||
|
FROM python:3.11
|
||||||
|
|
||||||
|
# Ustaw katalog roboczy na /app
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Skopiuj zawartość bieżącego katalogu do /app w kontenerze
|
||||||
|
COPY . /app
|
||||||
|
|
||||||
|
# Zainstaluj zależności
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
# Wyeksponuj port 5000
|
||||||
|
EXPOSE 5000
|
||||||
|
|
||||||
|
# Uruchom aplikację po uruchomieniu kontenera
|
||||||
|
CMD ["python", "main.py"]
|
10
docker/docker-compose.yml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
version: '3.3'
|
||||||
|
|
||||||
|
services:
|
||||||
|
cat-detection:
|
||||||
|
image: cat-detection
|
||||||
|
build:
|
||||||
|
context: ../
|
||||||
|
dockerfile: ./docker/Dockerfile
|
||||||
|
ports:
|
||||||
|
- "5000:5000"
|
BIN
img/cat.png
Before Width: | Height: | Size: 204 KiB |
@ -1,3 +1,5 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
from jproperties import Properties
|
from jproperties import Properties
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@ -10,9 +12,11 @@ from jproperties import Properties
|
|||||||
def translate(to_translate, lang):
|
def translate(to_translate, lang):
|
||||||
try:
|
try:
|
||||||
config = Properties()
|
config = Properties()
|
||||||
|
script_directory = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
resources_path = os.path.join(script_directory, "./resources")
|
||||||
|
|
||||||
# Load properties file for given lang
|
# Load properties file for given lang
|
||||||
with open(f"resources/{lang}.properties", 'rb') as config_file:
|
with open(os.path.join(resources_path, f"./{lang}.properties"), 'rb') as config_file:
|
||||||
config.load(config_file, encoding='UTF-8')
|
config.load(config_file, encoding='UTF-8')
|
||||||
|
|
||||||
# Translate labels for given to_translate dictionary
|
# Translate labels for given to_translate dictionary
|
||||||
|
2
main.py
@ -103,4 +103,4 @@ def upload_file():
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
app.run(debug=True)
|
app.run(host='0.0.0.0')
|
||||||
|
@ -3,3 +3,6 @@ numpy==1.26.3
|
|||||||
pillow==10.2.0
|
pillow==10.2.0
|
||||||
keras==2.15.0
|
keras==2.15.0
|
||||||
jproperties==2.1.1
|
jproperties==2.1.1
|
||||||
|
tensorflow==2.15.0
|
||||||
|
werkzeug==3.0.1
|
||||||
|
pytest==7.4.4
|
24
scripts/build_image.bat
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
@echo off
|
||||||
|
chcp 65001 >nul
|
||||||
|
|
||||||
|
docker -v >nul 2>&1
|
||||||
|
if %errorlevel% neq 0 (
|
||||||
|
echo [31mDocker is not installed.[0m
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
docker info >nul 2>&1
|
||||||
|
if %errorlevel% neq 0 (
|
||||||
|
echo [31mDocker engine is not running.[0m
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
cd ../docker
|
||||||
|
echo [32mBuilding docker image...[0m
|
||||||
|
docker compose build cat-detection
|
||||||
|
if %errorlevel% neq 0 (
|
||||||
|
echo [31mBuilding cdocker imagew failed.[0m
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
echo [32mThe image was built successfully.[0m
|
27
scripts/build_image.sh
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
export LC_ALL=C.UTF-8
|
||||||
|
export LANG=C.UTF-8
|
||||||
|
|
||||||
|
docker -v > /dev/null 2>&1
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo -e "\033[31mDocker is not installed.\033[0m"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
docker info > /dev/null 2>&1
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo -e "\033[31mDocker engine is not running.\033[0m"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd ../docker
|
||||||
|
echo -e "\033[32mBuilding docker image...\033[0m"
|
||||||
|
docker-compose build cat-detection
|
||||||
|
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo -e "\033[31mBuilding docker image failed.\033[0m"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "\033[32mThe image was built successfully.\033[0m"
|
14
scripts/run_tests.bat
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
@echo off
|
||||||
|
echo [32mRunning unit tests.[0m
|
||||||
|
|
||||||
|
set PYTHONPATH=%CD%;%PYTHONPATH%
|
||||||
|
|
||||||
|
cd %~dp0
|
||||||
|
pytest ../tests
|
||||||
|
|
||||||
|
if %ERRORLEVEL% equ 0 (
|
||||||
|
echo [32mTests passed successfully.[0m
|
||||||
|
) else (
|
||||||
|
Tests failed.
|
||||||
|
echo [31mTests failed.[0m
|
||||||
|
)
|
8
scripts/start.bat
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
@echo off
|
||||||
|
chcp 65001 >nul
|
||||||
|
|
||||||
|
docker compose -f ../docker/docker-compose.yml up cat-detection -d
|
||||||
|
if %errorlevel% neq 0 (
|
||||||
|
echo [31mStarting docker container failed.[0m
|
||||||
|
exit /b 1
|
||||||
|
)
|
11
scripts/start.sh
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
export LC_ALL=C.UTF-8
|
||||||
|
export LANG=C.UTF-8
|
||||||
|
|
||||||
|
docker-compose -f ../docker/docker-compose.yml up cat-detection -d
|
||||||
|
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo -e "\033[31mStarting docker container failed.\033[0m"
|
||||||
|
exit 1
|
||||||
|
fi
|
BIN
tests/img/Egyptian_cat/Egyptian-Mau-Bronze-750.jpg
Normal file
After Width: | Height: | Size: 360 KiB |
BIN
tests/img/Persian_cat/PER_Fluffy_Fancy_Antony_(5468896948).jpg
Normal file
After Width: | Height: | Size: 100 KiB |
BIN
tests/img/Siamese_cat/siamese-cat-cover.jpg
Normal file
After Width: | Height: | Size: 159 KiB |
BIN
tests/img/cheetah/TheCheethcat.jpg
Normal file
After Width: | Height: | Size: 180 KiB |
BIN
tests/img/cougar/Cougar_at_Cougar_Mountain_Zoological_Park_2.jpg
Normal file
After Width: | Height: | Size: 216 KiB |
BIN
tests/img/jaguar/Junior-Jaguar-Belize-Zoo.jpg
Normal file
After Width: | Height: | Size: 326 KiB |
BIN
tests/img/leopard/African_leopard_male_(cropped).jpg
Normal file
After Width: | Height: | Size: 221 KiB |
BIN
tests/img/lion/Lion_waiting_in_Namibia.jpg
Normal file
After Width: | Height: | Size: 281 KiB |
BIN
tests/img/lynx/552661_poster.jpg
Normal file
After Width: | Height: | Size: 469 KiB |
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 7.1 KiB |
BIN
tests/img/snow_lopard/Snow-Leopard.jpg
Normal file
After Width: | Height: | Size: 255 KiB |
BIN
tests/img/tabby/Cat_November_2010-1a.jpg
Normal file
After Width: | Height: | Size: 2.7 MiB |
After Width: | Height: | Size: 345 KiB |
Before Width: | Height: | Size: 105 KiB After Width: | Height: | Size: 105 KiB |
19
tests/test_1.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
from werkzeug.datastructures import FileStorage
|
||||||
|
|
||||||
|
from main import app
|
||||||
|
|
||||||
|
|
||||||
|
def test_upload_file():
|
||||||
|
with app.test_client() as test_client:
|
||||||
|
script_directory = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
image_path = os.path.join(script_directory, "./img/tiger_cat/cat1.jpg")
|
||||||
|
image = FileStorage(
|
||||||
|
stream=open(image_path, "rb"),
|
||||||
|
filename="cat1.jpg",
|
||||||
|
content_type="image/jpeg",
|
||||||
|
)
|
||||||
|
|
||||||
|
response = test_client.post('/api/v1/detect-cat', data={'image': image}, content_type='multipart/form-data')
|
||||||
|
assert response.status_code == 200
|
@ -1,5 +1,3 @@
|
|||||||
import imghdr
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Validation method.
|
Validation method.
|
||||||
If everything fine then returns empty list.
|
If everything fine then returns empty list.
|
||||||
|