Add All Folders
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
import os
|
||||
import pysera
|
||||
from api.module import Module
|
||||
from api.io_port import InPort, OutPort, NIFTIImageType, CSVTableType
|
||||
|
||||
|
||||
def factory():
|
||||
m = Module("PySERAExtractor")
|
||||
|
||||
in_image = InPort("image", NIFTIImageType())
|
||||
in_mask = InPort("mask", NIFTIImageType())
|
||||
|
||||
out_features = OutPort("features", CSVTableType(columns=["name", "value"]))
|
||||
|
||||
m.add_in_port(in_image)
|
||||
m.add_in_port(in_mask)
|
||||
m.add_out_port(out_features)
|
||||
|
||||
def execute(inputs):
|
||||
image_input = inputs["image"]
|
||||
mask_input = inputs["mask"]
|
||||
|
||||
output_dir = "results"
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
|
||||
result = pysera.process_batch(
|
||||
image_input=image_input,
|
||||
mask_input=mask_input,
|
||||
output_path=output_dir,
|
||||
num_workers="auto",
|
||||
enable_parallelism=True,
|
||||
apply_preprocessing=True,
|
||||
categories="all",
|
||||
dimensions="1st,2_5d,3d",
|
||||
feature_value_mode="REAL_VALUE",
|
||||
extraction_mode="handcrafted_feature",
|
||||
report="info",
|
||||
)
|
||||
|
||||
df = result.get("features_extracted")
|
||||
|
||||
features = []
|
||||
if df is not None:
|
||||
for idx, row in df.iterrows():
|
||||
features.append({
|
||||
"name": row[0],
|
||||
"value": row[1]
|
||||
})
|
||||
|
||||
return {
|
||||
"features": features
|
||||
}
|
||||
|
||||
m.execute = execute
|
||||
return m
|
||||
@@ -0,0 +1,108 @@
|
||||
import os
|
||||
import numpy as np
|
||||
import nibabel as nib
|
||||
import pydicom
|
||||
import nrrd
|
||||
import cv2
|
||||
|
||||
from api.module import Module
|
||||
from api.io_port import OutPort, NIFTIImageType
|
||||
|
||||
|
||||
def load_nifti(path):
|
||||
nii = nib.load(path)
|
||||
return nii.get_fdata().astype(np.float32)
|
||||
|
||||
|
||||
def load_dicom(path):
|
||||
if os.path.isdir(path):
|
||||
files = sorted([
|
||||
os.path.join(path, f)
|
||||
for f in os.listdir(path)
|
||||
if not f.startswith(".")
|
||||
])
|
||||
slices = [pydicom.dcmread(f).pixel_array for f in files]
|
||||
return np.stack(slices).astype(np.float32)
|
||||
|
||||
ds = pydicom.dcmread(path)
|
||||
return ds.pixel_array.astype(np.float32)
|
||||
|
||||
|
||||
def load_nrrd(path):
|
||||
data, _ = nrrd.read(path)
|
||||
return data.astype(np.float32)
|
||||
|
||||
|
||||
def load_numpy(path):
|
||||
return np.load(path).astype(np.float32)
|
||||
|
||||
def load_image(path):
|
||||
img = cv2.imread(path, cv2.IMREAD_UNCHANGED)
|
||||
if img is None:
|
||||
raise ValueError(f"Cannot read image file: {path}")
|
||||
return img.astype(np.float32)
|
||||
|
||||
|
||||
def load_any(path):
|
||||
path = path.replace("\\", "/").lower()
|
||||
|
||||
if path.endswith((".nii", ".nii.gz")):
|
||||
return load_nifti(path)
|
||||
|
||||
if path.endswith(".nrrd"):
|
||||
return load_nrrd(path)
|
||||
|
||||
if path.endswith(".npy"):
|
||||
return load_numpy(path)
|
||||
|
||||
if path.endswith((".png", ".jpg", ".jpeg", ".bmp", ".tif", ".tiff")):
|
||||
return load_image(path)
|
||||
|
||||
if os.path.isdir(path) or path.endswith(".dcm"):
|
||||
return load_dicom(path)
|
||||
|
||||
raise ValueError(f"Unsupported image format: {path}")
|
||||
|
||||
|
||||
def factory():
|
||||
m = Module("ImageReader")
|
||||
|
||||
out_image = OutPort("image", NIFTIImageType(metadata={"role": "image"}))
|
||||
out_mask = OutPort("mask", NIFTIImageType(metadata={"role": "mask"}))
|
||||
|
||||
m.add_out_port(out_image)
|
||||
m.add_out_port(out_mask)
|
||||
|
||||
def execute(inputs):
|
||||
image_dir = "data/images"
|
||||
mask_dir = "data/masks"
|
||||
|
||||
image_files = [f for f in os.listdir(image_dir) if not f.startswith(".")]
|
||||
mask_files = [f for f in os.listdir(mask_dir) if not f.startswith(".")]
|
||||
|
||||
if not image_files:
|
||||
raise ValueError("No image found in data/images")
|
||||
|
||||
if not mask_files:
|
||||
raise ValueError("No mask found in data/masks")
|
||||
|
||||
image_path = os.path.join(image_dir, image_files[0])
|
||||
mask_path = os.path.join(mask_dir, mask_files[0])
|
||||
|
||||
try:
|
||||
image = load_any(image_path)
|
||||
except Exception as e:
|
||||
raise ValueError(f"Cannot read image: {image_path} ({e})")
|
||||
|
||||
try:
|
||||
mask = load_any(mask_path)
|
||||
except Exception as e:
|
||||
raise ValueError(f"Cannot read mask: {mask_path} ({e})")
|
||||
|
||||
return {
|
||||
"image": image,
|
||||
"mask": mask
|
||||
}
|
||||
|
||||
m.execute = execute
|
||||
return m
|
||||
@@ -0,0 +1,43 @@
|
||||
import os
|
||||
import csv
|
||||
from datetime import datetime
|
||||
from api.module import Module
|
||||
from api.io_port import InPort, CSVTableType
|
||||
|
||||
|
||||
def factory():
|
||||
m = Module("CSVWriter")
|
||||
|
||||
inp = InPort("features", CSVTableType(columns=["name", "value"]))
|
||||
m.add_in_port(inp)
|
||||
|
||||
def execute(inputs):
|
||||
data = inputs["features"]
|
||||
|
||||
rows = []
|
||||
try:
|
||||
import pandas as pd
|
||||
if hasattr(data, "iterrows"):
|
||||
for _, row in data.iterrows():
|
||||
rows.append({"name": row[0], "value": row[1]})
|
||||
else:
|
||||
rows = list(data)
|
||||
except Exception:
|
||||
rows = list(data)
|
||||
|
||||
os.makedirs("results", exist_ok=True)
|
||||
ts = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||
path = os.path.join("results", f"features_{ts}.csv")
|
||||
|
||||
with open(path, "w", newline="", encoding="utf-8") as f:
|
||||
w = csv.writer(f)
|
||||
w.writerow(["name", "value"])
|
||||
for r in rows:
|
||||
w.writerow([r["name"], r["value"]])
|
||||
|
||||
return {
|
||||
"csv_path": path
|
||||
}
|
||||
|
||||
m.execute = execute
|
||||
return m
|
||||
Reference in New Issue
Block a user