backend/image_markuper/dicom/services.py

122 lines
4.1 KiB
Python
Raw Normal View History

2022-10-29 22:46:19 +03:00
import glob
import os
import shutil
import zipfile
from pathlib import Path
import magic
2022-11-03 22:16:11 +03:00
import numpy as np
import pydicom
2022-11-04 14:51:11 +03:00
from dicom import tasks
2022-11-01 12:20:43 +03:00
from dicom.models import Coordinate, Dicom, Project
2022-10-29 22:46:19 +03:00
from django.core.files import File
from django.core.files.uploadedfile import InMemoryUploadedFile, TemporaryUploadedFile
2022-11-03 22:16:11 +03:00
from skimage import measure
from stl import mesh
2022-10-29 22:46:19 +03:00
from utils.generators import generate_charset
2022-11-01 12:20:43 +03:00
def process_files(
2022-11-03 22:16:11 +03:00
files: list[TemporaryUploadedFile | InMemoryUploadedFile], user, slug=None
2022-11-01 12:20:43 +03:00
):
if slug:
project = Project.objects.get(slug=slug)
else:
project = Project.objects.create(user=user)
2022-10-29 22:46:19 +03:00
for file in files:
content_type = magic.from_file(file.temporary_file_path())
if content_type == "DICOM medical imaging data":
2022-11-01 12:20:43 +03:00
Dicom.objects.create(file=file, project=project, user=user)
2022-10-29 22:46:19 +03:00
elif "Zip" in content_type:
2022-11-03 23:15:25 +03:00
dit_path = f"/tmp/{generate_charset(10)}"
2022-10-29 22:46:19 +03:00
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]),
2022-11-01 12:20:43 +03:00
project=project,
2022-10-29 22:46:19 +03:00
user=user,
)
shutil.rmtree(dit_path)
2022-11-04 14:51:11 +03:00
tasks.process_project.apply_async(kwargs={"pk": project.pk}, countdown=3)
2022-11-01 12:20:43 +03:00
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)
2022-11-03 22:16:11 +03:00
# print(Dicom.objects.all())
files = project.files.all()
bbox_data = []
2022-11-03 22:16:11 +03:00
for file_number in range(image_range[0], image_range[1] + 1):
print(points[0]["x"])
bbox_data.append(
2022-11-03 22:16:11 +03:00
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)
2022-11-03 22:16:11 +03:00
# print(project.files.all(), "files", project)
return []
2022-11-03 22:16:11 +03:00
def generate_3d_point_cloud(project_slug: str):
project = Project.objects.get(slug=project_slug)
point_clouds = []
2022-11-03 22:16:11 +03:00
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
2022-11-03 22:16:11 +03:00
# point_clouds.append({'x': jindex, 'y': iindex, 'z': fileindex, 'value': 0})
else:
2022-11-03 22:16:11 +03:00
point_clouds.append([jindex, iindex, file_index, j])
return point_clouds
2022-11-03 22:16:11 +03:00
2022-11-03 23:15:25 +03:00
def generate_3d_model(project: Project, thr=800):
2022-11-03 22:16:11 +03:00
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)
2022-11-03 23:15:25 +03:00
path = Path(pth)
with path.open(mode="rb") as f:
project.stl = File(f, name=pth.split("/")[-1])
project.save()
os.remove(pth)