diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..657cb3b --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,21 @@ +{ + + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Python: Current File", + "type": "python", + "request": "launch", + "module": "flask", + "env": { + "FLASK_APP": "webApp.py", + "FLASK_DEBUG": "1" + }, + "args": ["run", "--no-debugger", "--no-reload"] + //"args": [ "5cc5570b-6ed9-3b33-9db4-bdb8ecb9f890", "test-data/lectionAudi/2021-03-12 13-51-19.JPG" ] + } + ] +} diff --git a/imageWorking.py b/imageWorking.py index eb63ade..f5e30c9 100644 --- a/imageWorking.py +++ b/imageWorking.py @@ -1,18 +1,18 @@ import cv2 as cv import numpy as np -from main import img_size as size +img_size = (1280, 720) # Размер изображения для нормализации. def image_transform(image: np.ndarray) -> np.ndarray: ''' Трансформирует изображение нужным образом. @param image: Исходная матрица с представлением изображения. ''' - image = cv.resize(image, (size[0], size[1])) + image = cv.resize(image, (img_size[0], img_size[1])) return image[:, :, ::-1] -def get_image_as_array(image_name: str) -> np.ndarray: +def get_image_file_as_array(image_name: str) -> np.ndarray: ''' Получает изображение из файла и нормализует его. @param image_name: Путь до изображения. @@ -21,3 +21,13 @@ def get_image_as_array(image_name: str) -> np.ndarray: image: np.ndarray # приведение типов image = image_transform(image) return image + +def get_image_buf_as_array(buf) -> np.ndarray: + ''' + Получает изображение из буфера и нормализует его. + @param image_name: Путь до изображения. + ''' + image = cv.imdecode(buf, cv.IMREAD_COLOR) + image: np.ndarray # приведение типов + image = image_transform(image) + return image diff --git a/main.py b/main.py index 643f279..5132f36 100644 --- a/main.py +++ b/main.py @@ -2,6 +2,7 @@ import os import sys import cv2 as cv +import numpy as np import requests import imageWorking @@ -9,24 +10,22 @@ import neuralNetwork import ontologyWorking url = 'http://kb.athene.tech/api/1.0/ontology/' -img_path = 'data' -img_size = (1280, 720) # Размер изображения для нормализации. -def analyze_file(uid: str, image_path: str) -> None: +def analyze_base(ontology_uid: str, image: np.ndarray, queries: list[str]) -> tuple[2]: ''' - Анализирует файл и выводит результат в консоль. - @param uid: УИД онтологии. - @param url: Базовый URL сервиса. + Базовая функция анализа файла и вывода результатов обработки. + @param ontology_uid: УИД онтологии. + @param image: Изображение. ''' - if not ontologyWorking.is_ontology_exists(uid, url): - raise Exception(f'Онтология с uid {uid} не существует') - if not os.path.isfile(image_path): - raise Exception(f'Изображение {image_path} не существует') + if not ontologyWorking.is_ontology_exists(ontology_uid, url): + raise Exception(f'Онтология с uid {ontology_uid} не существует') + if image is None: + raise Exception(f'Изображение не указано') model = neuralNetwork.load_model() # Распознавание изображения. - results = model.predict(source=imageWorking.get_image_as_array(image_path)) + results = model.predict(source=image) # Создание аксиом онтологии на основе результатов распознавания. object_properties = list() @@ -47,15 +46,33 @@ def analyze_file(uid: str, image_path: str) -> None: 'dataPropertyAssertions': data_properties } } + params = '&'.join([f'names={query}' for query in queries]) + + # Выполнение запроса. + response = requests.post(url + f'{ontology_uid}/query/multi?{params}', json=data).json() + + return results, response + + +def analyze_file(ontology_uid: str, image_path: str) -> None: + ''' + Анализирует файл и выводит результат в консоль. + @param ontology_uid: УИД онтологии. + @param image_path: Путь до изображения. + ''' + if not os.path.isfile(image_path): + raise Exception(f'Изображение {image_path} не существует') + image = imageWorking.get_image_file_as_array(image_path) + queries = [ 'QueryGetNotEmpty', 'QueryGetCheck', 'QueryGetEmpty' ] + + # Распознавание изображения. + results, response = analyze_base(ontology_uid, image, queries) + result = { 'QueryGetNotEmpty': '', 'QueryGetCheck': '', 'QueryGetEmpty': '' } - params = '&'.join([f'names={query}' for query in result.keys()]) - - # Выполнение запроса. - response = requests.post(url + f'{uid}/query/multi?{params}', json=data).json() if response['error']: raise Exception(response['error']) for query in response['response']: @@ -79,6 +96,7 @@ def analyze_file(uid: str, image_path: str) -> None: cv.waitKey(0) cv.destroyAllWindows() + # Точка входа в приложение. if __name__ == '__main__': if len(sys.argv) != 3: diff --git a/requirements.txt b/requirements.txt index 545ff0b..008fb9b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,52 +1,41 @@ -absl-py==1.4.0 -astunparse==1.6.3 -cachetools==5.3.0 +blinker==1.6.2 certifi==2023.5.7 charset-normalizer==3.1.0 -flatbuffers==23.5.9 -gast==0.4.0 -google-auth==2.18.1 -google-auth-oauthlib==1.0.0 -google-pasta==0.2.0 -grpcio==1.54.2 -h5py==3.8.0 +click==8.1.3 +colorama==0.4.6 +contourpy==1.1.0 +cycler==0.11.0 +filelock==3.12.2 +Flask==2.3.2 +fonttools==4.40.0 idna==3.4 -jax==0.4.10 -keras==2.12.0 -libclang==16.0.0 -Markdown==3.4.3 -MarkupSafe==2.1.2 +itsdangerous==2.1.2 +Jinja2==3.1.2 +kiwisolver==1.4.4 +MarkupSafe==2.1.3 matplotlib==3.7.1 -ml-dtypes==0.1.0 -numpy==1.23.5 -oauthlib==3.2.2 +mpmath==1.3.0 +networkx==3.1 +numpy==1.25.0 opencv-python==4.7.0.72 -opt-einsum==3.3.0 packaging==23.1 -pandas==2.0.1 +pandas==2.0.2 Pillow==9.5.0 -protobuf==4.23.1 psutil==5.9.5 +pyparsing==3.1.0 +python-dateutil==2.8.2 +pytz==2023.3 PyYAML==6.0 -pyasn1==0.5.0 -pyasn1-modules==0.3.0 -requests==2.30.0 -requests-oauthlib==1.3.1 -rsa==4.9 -scipy==1.10.1 +requests==2.31.0 +scipy==1.11.0 +seaborn==0.12.2 six==1.16.0 -tensorboard==2.12.3 -tensorboard-data-server==0.7.0 -tensorflow==2.12.0 -tensorflow-estimator==2.12.0 -tensorflow-intel==2.12.0 -tensorflow-io-gcs-filesystem==0.31.0 -termcolor==2.3.0 +sympy==1.12 torch==2.0.1 torchvision==0.15.2 tqdm==4.65.0 -typing_extensions==4.5.0 -ultralytics==8.0.105 -urllib3==1.26.15 -Werkzeug==2.3.4 -wrapt==1.14.1 +typing_extensions==4.6.3 +tzdata==2023.3 +ultralytics==8.0.123 +urllib3==2.0.3 +Werkzeug==2.3.6 diff --git a/static/index.html b/static/index.html new file mode 100644 index 0000000..b2f9ab0 --- /dev/null +++ b/static/index.html @@ -0,0 +1,49 @@ + + +
+ + + ++ Загрузите изображение в поле ниже, чтобы проверить, на фотография пустая + или заполненная аудитория. +
+ + + + + + + diff --git a/webApp.py b/webApp.py new file mode 100644 index 0000000..a364496 --- /dev/null +++ b/webApp.py @@ -0,0 +1,36 @@ +import base64 +import cv2 as cv +from flask import Flask, redirect, request +import numpy +from imageWorking import get_image_buf_as_array +from main import analyze_base + +app = Flask(__name__, static_url_path = "/") + +@app.route("/") +def main(): + return redirect('index.html') + +@app.route("/analyze", methods=["POST"]) +def analyze(): + if 'image' not in request.files or request.files['image'].filename == '': + return { + 'success': False, + 'error': 'Укажите изображение', + } + if 'ontology' in request.files and request.files['ontology'].filename != '': + return { + 'success': False, + 'error': 'Загрузка онтологии ещё не реализована', + } + img = request.files['image'].read(); + img = numpy.fromstring(img, numpy.uint8) + img = get_image_buf_as_array(img) + queries = [ 'QueryGetNotEmpty', 'QueryGetCheck', 'QueryGetEmpty' ] + results, response = analyze_base('5cc5570b-6ed9-3b33-9db4-bdb8ecb9f890', img, queries) + imencoded = cv.imencode(".jpg", results[0].plot())[1] + return { + 'success': True, + 'data': response, + 'image': base64.b64encode(imencoded).decode("utf-8"), + }