26-7-31-1
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
from fastapi import APIRouter, File, Form, HTTPException, UploadFile
|
||||
|
||||
from app.schemas.models import ImagingAnalyzeResponse
|
||||
from app.services.monai_preprocess import load_image_bgr, preprocess
|
||||
from app.services.report_generator import build_imaging_texts, generate_imaging_report, make_full_report
|
||||
from app.schemas.models import ImagingReportRequest
|
||||
from app.services.yolo_detector import get_detector
|
||||
from app.services.yolo_manager import get_yolo_manager
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
router = APIRouter(prefix="/imaging", tags=["imaging"])
|
||||
|
||||
|
||||
@router.post("/analyze", response_model=ImagingAnalyzeResponse)
|
||||
async def analyze_imaging(
|
||||
file: UploadFile | None = File(default=None),
|
||||
image_path: str | None = Form(default=None),
|
||||
study_type: str = Form(default="CT"),
|
||||
body_part: str = Form(default=""),
|
||||
patient_summary: str = Form(default=""),
|
||||
) -> ImagingAnalyzeResponse:
|
||||
raw = await _read_bytes(file, image_path)
|
||||
try:
|
||||
image_bgr = load_image_bgr(raw)
|
||||
prep = preprocess(image_bgr)
|
||||
detector = get_detector()
|
||||
detections = detector.detect(image_bgr, study_type=study_type)
|
||||
annotated = detector.annotate(image_bgr, detections)
|
||||
findings, diagnosis, recommendations, confidence = build_imaging_texts(
|
||||
study_type, body_part, detections, detector.mode
|
||||
)
|
||||
report = generate_imaging_report(
|
||||
ImagingReportRequest(
|
||||
study_type=study_type,
|
||||
body_part=body_part,
|
||||
patient_summary=patient_summary,
|
||||
preliminary_diagnosis=diagnosis,
|
||||
findings=findings,
|
||||
detections=detections,
|
||||
confidence=confidence,
|
||||
)
|
||||
)
|
||||
backend = prep.get("backend", "opencv")
|
||||
model_version = f"yolo-{detector.mode}+{backend}+{report.model_version}"
|
||||
try:
|
||||
get_yolo_manager().record_inference(
|
||||
mode=detector.mode,
|
||||
detections=detections,
|
||||
study_type=study_type,
|
||||
model_version=model_version,
|
||||
)
|
||||
except Exception as e:
|
||||
logger.warning("记录 YOLO 统计失败: %s", e)
|
||||
return ImagingAnalyzeResponse(
|
||||
detections=detections,
|
||||
annotated_image_base64=annotated,
|
||||
preliminary_diagnosis=report.impression or diagnosis,
|
||||
findings=report.findings or findings,
|
||||
recommendations=report.recommendations or recommendations,
|
||||
confidence=confidence,
|
||||
model_version=model_version,
|
||||
mode=detector.mode, # type: ignore[arg-type]
|
||||
full_report=report.full_report
|
||||
or make_full_report(study_type, body_part, findings, diagnosis, recommendations, patient_summary),
|
||||
)
|
||||
except ValueError as e:
|
||||
raise HTTPException(status_code=400, detail=str(e)) from e
|
||||
except Exception as e:
|
||||
logger.exception("影像分析失败")
|
||||
raise HTTPException(status_code=500, detail=f"影像分析失败: {e}") from e
|
||||
|
||||
|
||||
async def _read_bytes(file: UploadFile | None, image_path: str | None) -> bytes:
|
||||
if file is not None:
|
||||
data = await file.read()
|
||||
if not data:
|
||||
raise HTTPException(status_code=400, detail="上传文件为空")
|
||||
return data
|
||||
if image_path:
|
||||
path = Path(image_path)
|
||||
if not path.is_file():
|
||||
raise HTTPException(status_code=400, detail=f"影像路径不存在: {image_path}")
|
||||
return path.read_bytes()
|
||||
raise HTTPException(status_code=400, detail="请提供 file 或 image_path")
|
||||
Reference in New Issue
Block a user