backend/image_markuper/dicom/services.py
Alexander-D-Karpov 9019d31d48 added layers
2022-11-06 03:35:27 +03:00

121 lines
4.0 KiB
Python

import glob
import os
import shutil
import zipfile
from pathlib import Path
import magic
import numpy as np
import pydicom
from dicom import tasks
from dicom.models import Coordinate, Dicom, Project
from django.core.files import File
from django.core.files.uploadedfile import InMemoryUploadedFile, TemporaryUploadedFile
from skimage import measure
from stl import mesh
from utils.generators import generate_charset
def process_files(
files: list[TemporaryUploadedFile | InMemoryUploadedFile], user, slug=None
):
if slug:
project = Project.objects.get(slug=slug)
else:
project = Project.objects.create(user=user)
for file in files:
content_type = magic.from_file(file.temporary_file_path())
if content_type == "DICOM medical imaging data":
Dicom.objects.create(file=file, project=project, user=user)
elif "Zip" in content_type:
dit_path = f"/tmp/{generate_charset(10)}"
os.mkdir(dit_path)
with zipfile.ZipFile(file.temporary_file_path(), "r") as zip_ref:
zip_ref.extractall(dit_path)
files = glob.glob(dit_path + "/**/*", recursive=True)
for file_in_d in files:
if not os.path.isdir(file_in_d):
content_type = magic.from_file(file_in_d)
if content_type == "DICOM medical imaging data":
path = Path(file_in_d)
with path.open(mode="rb") as f:
Dicom.objects.create(
file=File(f, name=file_in_d.split("/")[-1]),
project=project,
)
shutil.rmtree(dit_path)
tasks.process_project.apply_async(kwargs={"pk": project.pk}, countdown=3)
return project
def create_coordinate(coordinates, obj):
for coordinate in coordinates:
Coordinate.objects.create(
x=coordinate["x"],
y=coordinate["y"],
shape=obj,
)
def get_bbox(project_id, points, image_range):
project: Project = Project.objects.get(slug=project_id)
# print(Dicom.objects.all())
files = project.files.all()
bbox_data = []
for file_number in range(image_range[0], image_range[1] + 1):
print(points[0]["x"])
bbox_data.append(
pydicom.dcmread(files[file_number].file.path)
.pixel_array[
int(points[0]["x"]) : int(points[1]["x"]), # noqa
int(points[0]["y"]) : int(points[1]["y"]), # noqa
]
.tolist()
)
print(pydicom.dcmread(files[file_number].file.path).pixel_array)
print(bbox_data)
# print(project.files.all(), "files", project)
return []
def generate_3d_point_cloud(project_slug: str):
project = Project.objects.get(slug=project_slug)
point_clouds = []
for file_index, file in enumerate(project.files.all()[::10]):
print(file_index)
pixel_array = pydicom.dcmread(file.file.path).pixel_array
for iindex, i in enumerate(pixel_array[::10]):
for jindex, j in enumerate(i[::10]):
if j <= 240:
pass
# point_clouds.append({'x': jindex, 'y': iindex, 'z': fileindex, 'value': 0})
else:
point_clouds.append([jindex, iindex, file_index, j])
return point_clouds
def generate_3d_model(project: Project, thr=800):
image = []
for file in project.files.all():
image.append(pydicom.dcmread(file.file.path).pixel_array)
p = np.array(image).transpose(2, 1, 0)
verts, faces, normals, values = measure.marching_cubes(p, thr, step_size=1)
solid = mesh.Mesh(np.zeros(faces.shape[0], dtype=mesh.Mesh.dtype))
for i, f in enumerate(faces):
for j in range(3):
solid.vectors[i][j] = verts[f[j], :]
pth = f"/tmp/{generate_charset(4)}.stl"
solid.save(pth)
path = Path(pth)
with path.open(mode="rb") as f:
project.stl = File(f, name=pth.split("/")[-1])
project.save()
os.remove(pth)