Compare commits

..

4 Commits

Author SHA1 Message Date
Vladislav Moiseev
354d5fdbd5 Немного красоты 2023-07-07 23:34:24 +04:00
Vladislav Moiseev
d70592fc64 Немного унифицирована работа с запросами к KB 2023-07-07 23:21:12 +04:00
Vladislav Moiseev
52335870fd Перемещение исходников в директорию src 2023-07-07 22:14:30 +04:00
Vladislav Moiseev
b7c7f8e066 Небольшое приведение кода и README в порядок 2023-07-07 22:10:13 +04:00
10 changed files with 193 additions and 112 deletions

2
.vscode/launch.json vendored
View File

@ -11,7 +11,7 @@
"request": "launch", "request": "launch",
"module": "flask", "module": "flask",
"env": { "env": {
"FLASK_APP": "webApp.py", "FLASK_APP": "src/webApp.py",
"FLASK_DEBUG": "1" "FLASK_DEBUG": "1"
}, },
"args": ["run", "--no-debugger", "--no-reload"] "args": ["run", "--no-debugger", "--no-reload"]

View File

@ -2,21 +2,23 @@
Сервис: http://kb.athene.tech/swagger-ui/index.html Сервис: http://kb.athene.tech/swagger-ui/index.html
Ручная установка зависимостей: Настройка виртуальной среды и установка зависимостей:
```commandline ```commandline
pip install -r requirements.txt python -m venv --clear .venv
```
Ручная установка зависимостей для mac с Apple Silicon: .venv\Scripts\activate.bat
# или
.\.venv\Scripts\Activate.ps1
# или
source .venv/bin/activate
```commandline python -m pip install -r requirements.txt
pip install -r requirements-mac.txt
``` ```
Запуск: Запуск:
```commandline ```commandline
main.py <Ontology UID> <Image Path> python main.py <Ontology UID> <Image Path>
main.py 5cc5570b-6ed9-3b33-9db4-bdb8ecb9f890 "test-data/lectionAudi/2021-03-12 13-48-31.JPG" python main.py 5cc5570b-6ed9-3b33-9db4-bdb8ecb9f890 "test-data/lectionAudi/2021-03-12 13-48-31.JPG"
``` ```

View File

@ -3,14 +3,11 @@ import sys
import cv2 as cv import cv2 as cv
import numpy as np import numpy as np
import requests
import imageWorking import imageWorking
import neuralNetwork import neuralNetwork
import ontologyWorking import ontologyWorking
url = 'http://kb.athene.tech/api/1.0/ontology/'
def analyze_base(ontology_uid: str, image: np.ndarray, queries: list[str]) -> tuple[2]: def analyze_base(ontology_uid: str, image: np.ndarray, queries: list[str]) -> tuple[2]:
''' '''
@ -18,8 +15,6 @@ def analyze_base(ontology_uid: str, image: np.ndarray, queries: list[str]) -> tu
@param ontology_uid: УИД онтологии. @param ontology_uid: УИД онтологии.
@param image: Изображение. @param image: Изображение.
''' '''
if not ontologyWorking.is_ontology_exists(ontology_uid, url):
raise Exception(f'Онтология с uid {ontology_uid} не существует')
if image is None: if image is None:
raise Exception(f'Изображение не указано') raise Exception(f'Изображение не указано')
model = neuralNetwork.load_model() model = neuralNetwork.load_model()
@ -38,18 +33,9 @@ def analyze_base(ontology_uid: str, image: np.ndarray, queries: list[str]) -> tu
object_properties += request[0] object_properties += request[0]
data_properties += request[1] data_properties += request[1]
# Формирование данных для запроса к сервису работы с онтологиями.
data = {
'data':
{
'objectPropertyAssertions': object_properties,
'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() response = ontologyWorking.analyze(ontology_uid, object_properties, data_properties, queries)
return results, response return results, response

View File

@ -2,15 +2,18 @@ import numpy as np
import requests import requests
def is_ontology_exists(uid: str, url: str) -> bool: url = 'http://kb.athene.tech/api/1.0/ontology/'
def is_ontology_exists(ontology_uid: str, url: str) -> bool:
''' '''
Проверяет, существует ли онтология в сервисе. Проверяет, существует ли онтология в сервисе.
@param uid: УИД онтологии. @param ontology_uid: УИД онтологии.
@param url: Базовый URL сервиса. @param url: Базовый URL сервиса.
''' '''
list_ontologies = requests.get(url).json()['response']['items'] list_ontologies = requests.get(url).json()['response']['items']
for onto in list_ontologies: for onto in list_ontologies:
if onto['uid'] == uid: if onto['uid'] == ontology_uid:
return True return True
return False return False
@ -61,3 +64,30 @@ def get_request_data(entities: dict, objects: np.ndarray, confs: np.ndarray, box
data_properties.append({'domain': entity, 'property': 'hasConfidence', 'value': float(conf)}) data_properties.append({'domain': entity, 'property': 'hasConfidence', 'value': float(conf)})
return object_properties, data_properties return object_properties, data_properties
def analyze(ontology_uid: str, object_properties: list, data_properties: list, queries: list[str]) -> tuple[2]:
'''
Базовая функция анализа.
@param ontology_uid: УИД онтологии.
@param object_properties: Объектные свойства.
@param data_properties: Свойства данных.
@param queries: Список запросов для запуска.
'''
if not is_ontology_exists(ontology_uid, url):
raise Exception(f'Онтология с uid {ontology_uid} не существует')
# Формирование данных для запроса к сервису работы с онтологиями.
data = {
'data':
{
'objectPropertyAssertions': object_properties,
'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 response

48
src/webApp.py Normal file
View File

@ -0,0 +1,48 @@
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_folder = "../static", 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': 'Загрузка онтологии ещё не реализована',
}
# Подготовка исходного изображения.
image_source = request.files['image'].read();
image_source = numpy.fromstring(image_source, numpy.uint8)
image_source = get_image_buf_as_array(image_source)
# Подготовка прочих данных и выполнение запроса.
queries = request.form['queries'].split(',') if request.form['queries'] is not None else [ ]
results, response = analyze_base('5cc5570b-6ed9-3b33-9db4-bdb8ecb9f890', image_source, queries)
# Подготовка изображения с ответом.
image_result = results[0].plot()
image_result = cv.cvtColor(image_result, cv.COLOR_BGR2RGB)
image_result = cv.imencode(".jpg", image_result)[1]
image_result = base64.b64encode(image_result).decode("utf-8")
# Вывод ответа.
return {
'success': True,
'data': response,
'image': image_result,
}

View File

@ -1,32 +1,57 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en" class="h-100">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Анализ аудиторий</title> <title>Анализ аудиторий</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" crossorigin="anonymous" />
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"
integrity="sha384-geWF76RCwLtnZ8qwWowPQNguL3RmwHVBC9FhGdlKrxdiJJigb/j/68SIy3Te4Bkz"
crossorigin="anonymous"></script>
</head> </head>
<body>
<p> <body class="bg-body-secondary h-100 d-flex align-items-center">
Загрузите изображение в поле ниже, чтобы проверить, на фотография пустая <div class="container py-3">
или заполненная аудитория. <div class="card">
<div class="card-body">
<div class="row">
<div class="col-lg">
<p class="alert alert-info">
Загрузите изображение в поле ниже, чтобы проверить, на
фотография пустая или заполненная аудитория.
</p> </p>
<form id="uploadForm" action="analyze"> <form id="uploadForm" action="analyze">
<div> <div>
<label for="image">Нажмите, чтобы загрузить изображение</label> <label for="image" class="form-label">Нажмите, чтобы загрузить изображение</label>
<input type="file" name="image" id="image" /> <input type="file" class="form-control" name="image" id="image" />
</div> </div>
<div> <div>
<label for="ontology">Онтология предметной области</label> <label for="ontology" class="form-label">Онтология предметной области</label>
<input type="file" name="ontology" id="ontology" /> <input type="file" class="form-control" name="ontology" id="ontology" />
</div> </div>
<div> <div>
<button type="submit">Отправить</button> <label for="queries" class="form-label">Набор запросов для запуска</label>
<input type="text" class="form-control" name="queries" id="queries"
value="QueryGetNotEmpty,QueryGetCheck,QueryGetEmpty" />
</div>
<div class="my-3">
<button type="submit" class="btn btn-primary">
Отправить
</button>
</div> </div>
</form> </form>
</div>
<img src="" alt="Результат" id="imgslot" /> <div class="col-lg">
<img src="none.png" alt="Результат" id="imgslot" class="w-100" />
<div id="queriesResult"></div>
</div>
</div>
</div>
</div>
</div>
<script> <script>
document document
.getElementById("uploadForm") .getElementById("uploadForm")
@ -36,14 +61,40 @@
fetch("/analyze", { method: "POST", body: data }) fetch("/analyze", { method: "POST", body: data })
.then((res) => res.json()) .then((res) => res.json())
.then((data) => { .then((data) => {
debugger; const img = document.getElementById("imgslot");
const queriesResult = document.getElementById("queriesResult");
img.src = "none.png";
if (data.image) { if (data.image) {
document.getElementById("imgslot").src = img.src = "data:image/jpg;base64," + data.image;
"data:image/jpg;base64," + data.image; }
queriesResult.innerHTML = "";
if (data.data && data.data.response) {
for (const [query, result] of Object.entries(
data.data.response
)) {
// Отрисовка результата запросов.
const markup = `
<h1 class="display-6">${query}</h1>
<table class="table table-bordered table-striped">
<tr>
${result.columns.map((column) => `<th>${column}</th>`).join("")}
</tr>
${result.rows.map(
(row) =>
`<tr>${Object.entries(row)
.map(([key, value]) => `<td>${value.value}</td>`)
.join("")}</tr>`
)}
</table>
`;
queriesResult.innerHTML += markup;
}
} }
console.log(data);
}); });
}); });
</script> </script>
</body> </body>
</html> </html>

BIN
static/none.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -1,36 +0,0 @@
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"),
}