Compare commits

..

No commits in common. "354d5fdbd56e85c2a7111df1caa4221ad70190c9" and "5da1ecb2e2fffc86d01a84a0e0bb9134f00e5243" have entirely different histories.

10 changed files with 111 additions and 192 deletions

4
.vscode/launch.json vendored
View File

@ -1,5 +1,5 @@
{ {
// Use IntelliSense to learn about possible attributes. // Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes. // Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
@ -11,7 +11,7 @@
"request": "launch", "request": "launch",
"module": "flask", "module": "flask",
"env": { "env": {
"FLASK_APP": "src/webApp.py", "FLASK_APP": "webApp.py",
"FLASK_DEBUG": "1" "FLASK_DEBUG": "1"
}, },
"args": ["run", "--no-debugger", "--no-reload"] "args": ["run", "--no-debugger", "--no-reload"]

View File

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

View File

@ -3,11 +3,14 @@ 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]:
''' '''
@ -15,6 +18,8 @@ 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()
@ -33,10 +38,19 @@ 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 = {
response = ontologyWorking.analyze(ontology_uid, object_properties, data_properties, queries) '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 results, response return results, response

View File

@ -2,18 +2,15 @@ import numpy as np
import requests import requests
url = 'http://kb.athene.tech/api/1.0/ontology/' def is_ontology_exists(uid: str, url: str) -> bool:
def is_ontology_exists(ontology_uid: str, url: str) -> bool:
''' '''
Проверяет, существует ли онтология в сервисе. Проверяет, существует ли онтология в сервисе.
@param ontology_uid: УИД онтологии. @param 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'] == ontology_uid: if onto['uid'] == uid:
return True return True
return False return False
@ -64,30 +61,3 @@ 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

View File

@ -1,48 +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_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,100 +1,49 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en" class="h-100"> <html lang="en">
<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> </head>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" <body>
integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" crossorigin="anonymous" /> <p>
<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> </p>
</head> <form id="uploadForm" action="analyze">
<div>
<body class="bg-body-secondary h-100 d-flex align-items-center"> <label for="image">Нажмите, чтобы загрузить изображение</label>
<div class="container py-3"> <input type="file" name="image" id="image" />
<div class="card">
<div class="card-body">
<div class="row">
<div class="col-lg">
<p class="alert alert-info">
Загрузите изображение в поле ниже, чтобы проверить, на
фотография пустая или заполненная аудитория.
</p>
<form id="uploadForm" action="analyze">
<div>
<label for="image" class="form-label">Нажмите, чтобы загрузить изображение</label>
<input type="file" class="form-control" name="image" id="image" />
</div>
<div>
<label for="ontology" class="form-label">Онтология предметной области</label>
<input type="file" class="form-control" name="ontology" id="ontology" />
</div>
<div>
<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>
</form>
</div>
<div class="col-lg">
<img src="none.png" alt="Результат" id="imgslot" class="w-100" />
<div id="queriesResult"></div>
</div>
</div>
</div> </div>
</div> <div>
</div> <label for="ontology">Онтология предметной области</label>
<script> <input type="file" name="ontology" id="ontology" />
document </div>
.getElementById("uploadForm") <div>
.addEventListener("submit", (event) => { <button type="submit">Отправить</button>
event.preventDefault(); </div>
const data = new FormData(event.target); </form>
fetch("/analyze", { method: "POST", body: data })
.then((res) => res.json())
.then((data) => {
const img = document.getElementById("imgslot");
const queriesResult = document.getElementById("queriesResult");
img.src = "none.png"; <img src="" alt="Результат" id="imgslot" />
if (data.image) {
img.src = "data:image/jpg;base64," + data.image;
}
queriesResult.innerHTML = ""; <script>
if (data.data && data.data.response) { document
for (const [query, result] of Object.entries( .getElementById("uploadForm")
data.data.response .addEventListener("submit", (event) => {
)) { event.preventDefault();
// Отрисовка результата запросов. const data = new FormData(event.target);
const markup = ` fetch("/analyze", { method: "POST", body: data })
<h1 class="display-6">${query}</h1> .then((res) => res.json())
<table class="table table-bordered table-striped"> .then((data) => {
<tr> debugger;
${result.columns.map((column) => `<th>${column}</th>`).join("")} if (data.image) {
</tr> document.getElementById("imgslot").src =
${result.rows.map( "data:image/jpg;base64," + data.image;
(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>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

36
webApp.py Normal file
View File

@ -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"),
}