mirror of
https://github.com/leaders-of-digital-9-task/backend.git
synced 2024-11-22 01:16:33 +03:00
after merge fixes
This commit is contained in:
parent
adccb5cf94
commit
1e19f7edd0
|
@ -5,6 +5,7 @@ from dicom.api.views import (
|
||||||
CreateRoiApi,
|
CreateRoiApi,
|
||||||
CreateRulerApi,
|
CreateRulerApi,
|
||||||
DeleteDicomProjectApi,
|
DeleteDicomProjectApi,
|
||||||
|
GeneratePatology,
|
||||||
ListCreateDicomApi,
|
ListCreateDicomApi,
|
||||||
ListCreateProjectApi,
|
ListCreateProjectApi,
|
||||||
ListUpdateDicomImageNumberApi,
|
ListUpdateDicomImageNumberApi,
|
||||||
|
@ -15,8 +16,6 @@ from dicom.api.views import (
|
||||||
RetrieveUpdateDeleteRoiApi,
|
RetrieveUpdateDeleteRoiApi,
|
||||||
RetrieveUpdateDeleteRulerApi,
|
RetrieveUpdateDeleteRulerApi,
|
||||||
SmartFileUploadApi,
|
SmartFileUploadApi,
|
||||||
GeneratePatology,
|
|
||||||
GeneratePointCloud
|
|
||||||
)
|
)
|
||||||
from django.urls import include, path
|
from django.urls import include, path
|
||||||
from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView
|
from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView
|
||||||
|
@ -123,12 +122,11 @@ urlpatterns = [
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
'generate/',
|
"generate/",
|
||||||
include(
|
include(
|
||||||
[
|
[
|
||||||
path('patology', GeneratePatology.as_view(), name='generate_patology'),
|
path("patology", GeneratePatology.as_view(), name="generate_patology"),
|
||||||
path('point_cloud', GeneratePointCloud.as_view(), name='generate_patology')
|
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -13,7 +13,13 @@ SECRET_KEY = env(
|
||||||
default="XgO9NMQfMY5CNeVNh98WrKRXiQZnvtPzHJrF9ROPhAFLVEG1FvDD2ZRKTdJKVu8p",
|
default="XgO9NMQfMY5CNeVNh98WrKRXiQZnvtPzHJrF9ROPhAFLVEG1FvDD2ZRKTdJKVu8p",
|
||||||
)
|
)
|
||||||
# https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts
|
# https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts
|
||||||
ALLOWED_HOSTS = ["localhost", "0.0.0.0", "127.0.0.1", "dev.akarpov.ru"]
|
ALLOWED_HOSTS = [
|
||||||
|
"localhost",
|
||||||
|
"0.0.0.0",
|
||||||
|
"127.0.0.1",
|
||||||
|
"dev.akarpov.ru",
|
||||||
|
"dev2.akarpov.ru",
|
||||||
|
]
|
||||||
|
|
||||||
# CACHES
|
# CACHES
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
|
@ -181,3 +181,9 @@ class ProjectSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Project
|
model = Project
|
||||||
fields = ["files", "slug", "created"]
|
fields = ["files", "slug", "created"]
|
||||||
|
|
||||||
|
|
||||||
|
class PatologyGenerateSerializer(serializers.Serializer):
|
||||||
|
project_slug = serializers.CharField()
|
||||||
|
points = serializers.ListField(child=CoordinateSerializer())
|
||||||
|
depth = serializers.ListField(child=serializers.IntegerField())
|
||||||
|
|
|
@ -6,7 +6,7 @@ from rest_framework.parsers import FormParser, MultiPartParser
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
|
||||||
from ..models import Circle, Dicom, Project, Roi
|
from ..models import Circle, Dicom, Project, Roi
|
||||||
from ..services import generate_3d_point_cloud, get_bbox, process_files
|
from ..services import process_files
|
||||||
from .serializers import (
|
from .serializers import (
|
||||||
BaseShapeLayerSerializer,
|
BaseShapeLayerSerializer,
|
||||||
BaseShapeSerializer,
|
BaseShapeSerializer,
|
||||||
|
@ -15,13 +15,12 @@ from .serializers import (
|
||||||
FreeHandSerializer,
|
FreeHandSerializer,
|
||||||
ListDicomSerializer,
|
ListDicomSerializer,
|
||||||
ListProjectSerializer,
|
ListProjectSerializer,
|
||||||
PointCloudSerializer,
|
PatologyGenerateSerializer,
|
||||||
ProjectSerializer,
|
ProjectSerializer,
|
||||||
RoiSerializer,
|
RoiSerializer,
|
||||||
RulerSerializer,
|
RulerSerializer,
|
||||||
SmartFileUploadSerializer,
|
SmartFileUploadSerializer,
|
||||||
create_coordinate,
|
create_coordinate,
|
||||||
PatologyGenerateSerializer
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -224,17 +223,6 @@ class GeneratePatology(generics.CreateAPIView):
|
||||||
serializer_class = PatologyGenerateSerializer
|
serializer_class = PatologyGenerateSerializer
|
||||||
|
|
||||||
def create(self, request, *args, **kwargs):
|
def create(self, request, *args, **kwargs):
|
||||||
data = self.get_serializer(request.data).data
|
# data = self.get_serializer(request.data).data
|
||||||
bbox = get_bbox(data['project_slug'], data['points'], data['depth'])
|
# bbox = get_bbox(data["project_slug"], data["points"], data["depth"])
|
||||||
return Response(data={}, status=200)
|
return Response(data={}, status=200)
|
||||||
|
|
||||||
|
|
||||||
class GeneratePointCloud(generics.CreateAPIView):
|
|
||||||
serializer_class = PointCloudSerializer
|
|
||||||
|
|
||||||
def create(self, request, *args, **kwargs):
|
|
||||||
print(request.data)
|
|
||||||
data = request.data
|
|
||||||
point_cloud = generate_3d_point_cloud(data['project_slug'])
|
|
||||||
print(point_cloud[0:5])
|
|
||||||
return Response(data={'voxels': point_cloud}, status=200)
|
|
|
@ -1,4 +1,3 @@
|
||||||
from functools import lru_cache
|
|
||||||
import glob
|
import glob
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
|
@ -6,18 +5,18 @@ import zipfile
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import magic
|
import magic
|
||||||
|
import numpy as np
|
||||||
|
import pydicom
|
||||||
from dicom.models import Coordinate, Dicom, Project
|
from dicom.models import Coordinate, Dicom, Project
|
||||||
from django.core.files import File
|
from django.core.files import File
|
||||||
from django.core.files.uploadedfile import InMemoryUploadedFile, TemporaryUploadedFile
|
from django.core.files.uploadedfile import InMemoryUploadedFile, TemporaryUploadedFile
|
||||||
|
from skimage import measure
|
||||||
|
from stl import mesh
|
||||||
from utils.generators import generate_charset
|
from utils.generators import generate_charset
|
||||||
from typing import List, Union
|
|
||||||
from django.conf import settings
|
|
||||||
import pydicom
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def process_files(
|
def process_files(
|
||||||
files: List[Union[TemporaryUploadedFile, InMemoryUploadedFile]], user, slug=None
|
files: list[TemporaryUploadedFile | InMemoryUploadedFile], user, slug=None
|
||||||
):
|
):
|
||||||
if slug:
|
if slug:
|
||||||
project = Project.objects.get(slug=slug)
|
project = Project.objects.get(slug=slug)
|
||||||
|
@ -60,35 +59,56 @@ def create_coordinate(coordinates, obj):
|
||||||
|
|
||||||
def get_bbox(project_id, points, image_range):
|
def get_bbox(project_id, points, image_range):
|
||||||
project: Project = Project.objects.get(slug=project_id)
|
project: Project = Project.objects.get(slug=project_id)
|
||||||
#print(Dicom.objects.all())
|
# print(Dicom.objects.all())
|
||||||
files = project.files.all()
|
files = project.files.all()
|
||||||
bbox_data = []
|
bbox_data = []
|
||||||
for file_number in range(image_range[0], image_range[1]+1):
|
for file_number in range(image_range[0], image_range[1] + 1):
|
||||||
print(points[0]['x'])
|
print(points[0]["x"])
|
||||||
bbox_data.append(
|
bbox_data.append(
|
||||||
pydicom.dcmread(
|
pydicom.dcmread(files[file_number].file.path)
|
||||||
files[file_number].file.path).pixel_array[int(points[0]['x']):int(points[1]['x']), int(points[0]['y']):int(points[1]['y'])].tolist())
|
.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(pydicom.dcmread(files[file_number].file.path).pixel_array)
|
||||||
print(bbox_data)
|
print(bbox_data)
|
||||||
#print(project.files.all(), "files", project)
|
# print(project.files.all(), "files", project)
|
||||||
return []
|
return []
|
||||||
|
|
||||||
@lru_cache(512)
|
|
||||||
def generate_3d_point_cloud(project_slug: str):
|
def generate_3d_point_cloud(project_slug: str):
|
||||||
project = Project.objects.get(slug=project_slug)
|
project = Project.objects.get(slug=project_slug)
|
||||||
|
|
||||||
point_clouds = []
|
point_clouds = []
|
||||||
|
|
||||||
for fileindex, file in enumerate(project.files.all()[::3]):
|
for file_index, file in enumerate(project.files.all()[::10]):
|
||||||
print(fileindex)
|
print(file_index)
|
||||||
pixel_array = pydicom.dcmread(
|
pixel_array = pydicom.dcmread(file.file.path).pixel_array
|
||||||
file.file.path
|
for iindex, i in enumerate(pixel_array[::10]):
|
||||||
).pixel_array
|
for jindex, j in enumerate(i[::10]):
|
||||||
for iindex, i in enumerate(pixel_array[::3]):
|
|
||||||
for jindex, j in enumerate(i[::3]):
|
|
||||||
if j <= 240:
|
if j <= 240:
|
||||||
pass
|
pass
|
||||||
#point_clouds.append({'x': jindex, 'y': iindex, 'z': fileindex, 'value': 0})
|
# point_clouds.append({'x': jindex, 'y': iindex, 'z': fileindex, 'value': 0})
|
||||||
else:
|
else:
|
||||||
point_clouds.append([jindex, iindex, fileindex, j])
|
point_clouds.append([jindex, iindex, file_index, j])
|
||||||
return point_clouds
|
return point_clouds
|
||||||
|
|
||||||
|
|
||||||
|
def generate_3d_model(project: Project, thr=800) -> str:
|
||||||
|
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)
|
||||||
|
return pth
|
||||||
|
|
9
image_markuper/dicom/tasks.py
Normal file
9
image_markuper/dicom/tasks.py
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
from celery import shared_task
|
||||||
|
from dicom.models import Project
|
||||||
|
from dicom.services import generate_3d_model
|
||||||
|
|
||||||
|
|
||||||
|
@shared_task()
|
||||||
|
def process_dicom(pk: int):
|
||||||
|
generate_3d_model(Project.objects.get(pk=pk))
|
||||||
|
return pk
|
|
@ -25,5 +25,9 @@ django-cors-headers==3.13.0 # https://github.com/adamchainz/django-cors-headers
|
||||||
djangorestframework-simplejwt==5.2.2
|
djangorestframework-simplejwt==5.2.2
|
||||||
# DRF-spectacular for api documentation
|
# DRF-spectacular for api documentation
|
||||||
drf-spectacular==0.24.2 # https://github.com/tfranzel/drf-spectacular
|
drf-spectacular==0.24.2 # https://github.com/tfranzel/drf-spectacular
|
||||||
numpy==1.23.4
|
|
||||||
|
|
||||||
pydicom==2.3.0
|
pydicom==2.3.0
|
||||||
|
numpy==1.23.4
|
||||||
|
numpy-stl==2.17.1
|
||||||
|
scikit-image==0.19.3
|
||||||
|
|
Loading…
Reference in New Issue
Block a user