Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
10371cd
zeroLoadBackend
reithosa Oct 25, 2025
91067b8
Worked ML pipeline
reithosa Nov 18, 2025
5f12c54
Editor is done
reithosa Jan 3, 2026
8a88c10
Main menu
reithosa Jan 4, 2026
1f2604c
доделал все контейнеры
reithosa Jan 8, 2026
c13e2f5
Все кнопки, кроме save
reithosa Jan 8, 2026
e9a147d
Сделал дизайн image, подправил дизайн editor
reithosa Jan 12, 2026
6b0db19
еще немного изменений дизайна в image и editor
reithosa Jan 12, 2026
568c367
минимамальное количество страниц для работы приложения готово
reithosa Jan 12, 2026
13c6138
поставил линию по центру
reithosa Jan 12, 2026
7c770df
подправил gap и padding
reithosa Jan 12, 2026
d55c75d
Страница images со всеми изображениями - готово
reithosa Jan 21, 2026
7ec5b44
загрузка страницы, отправка изображения, загрузка в бд, предикт мл
reithosa Jan 27, 2026
e4cc069
Merge pull request #2 from reithosa/API
reithosa Jan 27, 2026
ae88534
image загрузка и отображение изображения, загрузка разметки
reithosa Jan 28, 2026
bc24903
Загрузка labels на изображение готова
reithosa Jan 29, 2026
6501668
перемещение между страницами, кликабельные ссылки на изображения
reithosa Jan 29, 2026
ad7a68e
новая иконка
reithosa Jan 29, 2026
d3a749e
removed files
reithosa Feb 4, 2026
9575b1a
обновлённый гитигнор
reithosa Feb 4, 2026
c6ec863
удаление файлов
reithosa Feb 4, 2026
05ed7c8
обновлённый гитигнор 2
reithosa Feb 4, 2026
eeac9a0
график, рек, незагруженные файлы
reithosa Feb 4, 2026
c7b9221
Merge branch 'backend' of github.com:reithosa/webBloodDetectionClassi…
reithosa Feb 4, 2026
ff02728
images
reithosa Feb 4, 2026
eb8f306
удаление данных и изображения по нажатию
reithosa Feb 5, 2026
c9cc801
Страница редактирования результатов детекции и классификации
reithosa Feb 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,25 @@ ML_modul/DifferentColorData/
ML_modul/LS_Backend/
ML_modul/labeling/*
ML_modul/MyDataset/*/*
ML_modul/special_venv/
special_venv/
test.py/

Backend_modul/v1/__pycache__/*
Backend_modul/v1/config/__pycache__/*
Backend_modul/v1/core/__pycache__/*
Backend_modul/v1/ml/__pycache__/*
Backend_modul/v1/routers/__pycache__/*
Backend_modul/__pycache__/*
Backend_modul/app/*
Backend_modul/db/*

#файлы
ML_modul/PBC_dataset_normal_DIB.zip
ML_modul/result.txt
ML_modul/labeling.rar
Backend_modul/static/images/Buttons.ai
Backend_modul/database_min.sql


#игнор
!ML_modul/labeling/export
Expand All @@ -18,4 +32,4 @@ ML_modul/result.txt
!ML_modul/MyDataset/lymphocyte/_copied_files.txt
!ML_modul/MyDataset/monocyte/_copied_files.txt
!ML_modul/MyDataset/neutrophil/_copied_files.txt
!ML_modul/MyDataset/platelet/_copied_files.txt
!ML_modul/MyDataset/platelet/_copied_files.txt
Binary file added Backend_modul/ML/plt_model.pt
Binary file not shown.
Binary file added Backend_modul/ML/rbc_model.pt
Binary file not shown.
Binary file added Backend_modul/ML/wbc_model.pt
Binary file not shown.
Binary file added Backend_modul/app/__pycache__/app.cpython-313.pyc
Binary file not shown.
Binary file not shown.
Binary file added Backend_modul/app/__pycache__/test.cpython-313.pyc
Binary file not shown.
59 changes: 59 additions & 0 deletions Backend_modul/app/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
from fastapi import FastAPI, File, UploadFile, Form
from ultralytics import YOLO

import supervision as sv
import pandas as pd
import numpy as np
import shutil
import cv2

app = FastAPI()
model = YOLO(r"D:\webBloodDetection\Backend_modul\ML\rbc_model.pt")


@app.get("/")
def read_root():
return {"message" : "Hello, World"}

@app.post("/analyze")
async def analyze(file: UploadFile = File(...)):
#D:\webBloodDetection\Backend_modul>curl -v -X POST http://127.0.0.1:8000/analyze -F "file=@sample.jpg"
#Отправка в предобработку и тд.
#Генерация id
#Отправка данных о вводе в БД
#Отправка клиенту ответа об начале анализа.

contents = await file.read()
nparr = np.frombuffer(contents, np.uint8)
image = cv2.imdecode(nparr, cv2.IMREAD_COLOR)

results = model(
image,
verbose=False,
conf=0.3,
iou=0.3
)
if len(results)!=0:
result = results[0]
annotated_image = result.plot()
cv2.imwrite('D:/webBloodDetection/Backend_modul/images/annotated.jpg', annotated_image)
return {"analyze_status" : "good"}
else:
return {"analyze_status" : "bad"}


@app.get("/status/{id}")
async def search(id: int):
#поиск в PostgreSQL
if id==1:
return {"status" : "processed"}
if id==2:
return {"status" : "ready"}

@app.get("/result/{id}")
async def get_result(id: int):
#поиск в PostgreSQL
if id==1:
return {"result" : "report1"}
if id==2:
return {"result" : "report2"}
24 changes: 24 additions & 0 deletions Backend_modul/conn.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from sqlalchemy import create_engine
from model_type1 import create_db, drop_db, Images, Labels, Statistics_image
from sqlalchemy.orm import sessionmaker
from data_generator import generate


def main():
engine = create_engine(
"postgresql+psycopg2://postgres:1414@localhost:5432/bloodcells",
echo=True
)
#drop_db(engine)
#create_db(engine)

Sessions = sessionmaker(bind=engine)
with Sessions() as session:
#stats, labels, images = generate()
#session.add_all(stats + labels + images)
session.commit()
return


if __name__ == "__main__":
main()
37 changes: 37 additions & 0 deletions Backend_modul/data_generator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from ultralytics import YOLO
from pathlib import Path
from model_type1 import Images, Statistics_image, Labels

def generate():
stats, labels, images = [], [], []
model = YOLO(r"D:\webBloodDetection\Backend_modul\ML\rbc_model.pt")
folder = Path(r".\images")
i = 1
for file in folder.iterdir():
if file.is_file():
image = file.resolve()
results = model(
image,
verbose=False,
conf=0.3,
iou=0.3
)

result = results[0]
#print(f"image{i} = Images(file_name='{file.name}', file_path='{image}')")
#print(f"stat{i} = Statistics_image(id_image={i}, descriptions='test')")
stats.append(Images(file_name=str(file.name), file_path=str(image)))
images.append(Statistics_image(id_image=i, descriptions="test"))
n = 0
for box in result.boxes:
x, y, w, h = box.xywh[0][0].item(), box.xywh[0][1].item(), box.xywh[0][2].item(), box.xywh[0][3].item() #там почему-то тензор двумерный массив, так что надо так писать [0][3]
conf = box.conf[0].item()
cls = int(box.cls[0].item()) #box.cls возвращается тензор, поэтому нужно использова обращение к первому и единственному элементу [0]
#print(f"cls:{model.names[cls]}, conf:{conf:.2f}, x: {x:.2f}, y:{y:.2f}, w:{w:.2f}, h:{h:.2f}")
#print(f"label{n}_img{i} = Labels(id_image={i}, cls='{model.names[cls]}', conf={conf:.2f}, x={x:.2f}, y={y:.2f}, w={w:.2f}, h={h:.2f})")
labels.append(Labels(id_image=i, cls=model.names[cls], conf=conf, x=round(x, 2), y=round(y, 2), w=round(w, 2), h=round(h, 2)))
i += 1
return labels, images, stats

if __name__=="__main__":
pass
Binary file added Backend_modul/header/avatar.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
156 changes: 156 additions & 0 deletions Backend_modul/header/header.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
@font-face {
font-family: 'Local Fonts';
src: local("RobotoSerif-Regular");
}

/* база */
* {
margin: 0;
}
#content {
display: flex;
height: 100vh;
flex-direction: column;
overflow: hidden;
}

/* head */
#nav_head {
display: flex;
flex-direction: row;
justify-content: space-between;
width: 100%;
height: 3rem;
max-width: 100%;
padding: 0.5rem;
box-sizing: border-box;
}
#nameSite {
font-size: 2.3rem;
margin-right: auto;
font-family: "RobotoSerif-Regular", Local Fonts;
cursor: pointer;
user-select: none;
}
#hub_link {
padding-left: 10rem;
}
#navigation {
border-radius: 0rem 0rem 1.5rem 1.5rem;
border-bottom: 0.1rem solid black;
z-index: 998;
flex-shrink: 0;
}
#avatar {
height: 3rem;
width: auto;
border-radius: 50%;
cursor: pointer;
-webkit-user-drag: none;
user-select: none;
}

/* выдвигающиеся окно */
#win_nav {
position: fixed;
right: -20rem;
transition: 0.2s right ease-in-out;
display: flex;
flex-direction: column;

height: 100%;
width: 20rem;
border-left: 0.1rem solid black;
box-sizing: border-box;
background: white;
z-index: 1000;
gap: 1rem;
}
#win_nav.open {
right: 0;
}

#win_title {
display: flex;
flex-direction: row;
gap: 1rem;
padding: 1rem;
align-items: center;
user-select: none;
font-family: "RobotoSerif-Regular", Local Fonts;
}

#win_nav_avatar {
height: 3rem;
width: auto;
border-radius: 50%;
margin-left: auto;
-webkit-user-drag: none;
}
#win_nav_cross {
height: 2rem;
width: auto;
border-radius: 50%;
cursor: pointer;
-webkit-user-drag: none;
}
#win_nav_name {
font-size: 1rem;
}

#list_buttons {
display: flex;

flex-direction: column;
justify-content: space-around;
margin-top: 10rem;
}

.win_nav_buttons {
display: flex;
flex-direction: row;
padding: 0.5rem 0rem;
gap: 1rem;
padding: 1rem;
align-items: center;
cursor: pointer;
user-select: none;
font-family: "RobotoSerif-Regular", Local Fonts;
}

.win_nav_buttons:hover {
background-color: lightgray;
}
.win_nav_images {
-webkit-user-drag: none;
height: 1.5rem;
width: 1.5rem;
border-radius: 14%;
}

.menu_overlay {
display: none;
z-index: 999;
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
background-color: rgba(0, 0, 0, 0.25);
}

.menu_overlay.active {
display: block;
}

/* Canvas */
#body {
display: flex;
flex-direction: row;
gap: 0.2rem;
padding: 3rem;
height: 100%;
box-sizing: border-box;
flex: 1;
min-height: 0;
}
Loading