I tried to deal with MHD image files with python and python-vtk. The file is placed in google drive : mhd . I want to convert it into numpy array and then split them according to a given value' 500 for instance '. then calculate the summary information. I followed the instruction of this [post] How to convert a 3D vtkDataSet into a numpy array? but it does not work for my case.
import vtk
imageReader = vtk.vtkMetaImageReader()
imageReader.SetFileName(testfile1)
imageReader.Update()
# from vtk.util.numpy_support import numpy_to_vtk, vtk_to_numpy does not work for the data type issue
image = imageReader.GetOutput()
# List the dimensions of the image, for example
print image.GetDimensions()
pixelspace = imageReader.GetPixelSpacing()
an error comes here:
AttributeError: GetPixelSpacing
How could I achieve the conversion?
When I finish the data splitting, how could I save them back to mhd (or a raw data would be better ?)
Adapting from this thread... you can do the following:
import numpy as np
import vtk
from vtk.util.numpy_support import vtk_to_numpy
imr = vtk.vtkMetaImageReader()
imr.SetFileName('t10-Subvolume-resample_scale-1.mhd')
imr.Update()
im = imr.GetOutput()
rows, cols, _ = im.GetDimensions()
sc = im.GetPointData().GetScalars()
a = vtk_to_numpy(sc)
a = a.reshape(rows, cols, -1)
assert a.shape==im.GetDimensions()
where a will be a NumPy array containing the image data.
To get the channels right for later use as OpenCV image:
import vtk
import numpy as np
from vtk.util import numpy_support
def vtkImgToNumpyArray(vtkImageData):
rows, cols, _ = vtkImageData.GetDimensions()
scalars = vtkImageData.GetPointData().GetScalars()
resultingNumpyArray = numpy_support.vtk_to_numpy(scalars)
resultingNumpyArray = resultingNumpyArray.reshape(cols, rows, -1)
red, green, blue, alpha = np.dsplit(resultingNumpyArray, resultingNumpyArray.shape[-1])
resultingNumpyArray = np.stack([blue, green, red, alpha], 2).squeeze()
resultingNumpyArray = np.flip(resultingNumpyArray, 0)
return resultingNumpyArray
Related
Here's the code:
'''
import vtk
import numpy as np
from vtk.util.numpy_support import vtk_to_numpy
# Load the data
reader = vtk.vtkXMLImageDataReader()
reader.SetFileName("Isabel_2D.vti")
reader.Update()
imageData = reader.GetOutput() #read data
# Export the data to a buffer
exporter = vtk.vtkImageExport()
exporter.SetInputData(imageData)
exporter.Update()
data_pointer = exporter.GetPointerToData().GetScalars()
# Get the image data as a numpy array
#imageDataArray = np.frombuffer(data_pointer, np.float32) #.encode()
#imageDataArray = imageDataArray.reshape(imageData.GetDimensions())
rows, cols, _ = exporter.GetDimensions()
imageDataArray = vtk_to_numpy(sc)
imageDataArray = imageDataArray.reshape(rows, cols, -1)
'''
How to resolve the following error :
AttributeError: 'str' object has no attribute 'GetScalars'
You do not need the exporter part.
You should get the desired array from the imageData (GetPointData().GetScalars()) and wrap it. See this same post on vtk forum.
import rasterio as rio
from rasterio.plot import show
from sklearn import cluster
import matplotlib.pyplot as plt
import numpy as np
import glob
for filepath in glob.iglob('./dengue3/*.tiff'):
elhas_raster = rio.open(filepath)
elhas_arr = elhas_raster.read() # read the opened image
vmin, vmax = np.nanpercentile(elhas_arr, (5,95)) # 5-95% contrast stretch
# create an empty array with same dimension and data type
imgxyb = np.empty((elhas_raster.height, elhas_raster.width, elhas_raster.count), elhas_raster.meta['dtype'])
# loop through the raster's bands to fill the empty array
for band in range(imgxyb.shape[2]):
imgxyb[:,:,band] = elhas_raster.read(band+1)
#print(imgxyb.shape)
# convert to 1d array
img1d=imgxyb[:,:,:7].reshape((imgxyb.shape[0]*imgxyb.shape[1],imgxyb.shape[2]))
#print(img1d.shape)
Above code I am using to read the tiff images in a folder and get the arrays. However, the output is -
ValueError: cannot reshape array of size 6452775 into shape (921825,12)
Images are 12 band. I tried using 12 in place of 7 in the above code, but the code doesnt execute. How do I resolve this? Thank you for your time.
You have changed the size of the index you're trying to reshape, but not the reshape command parameter:
img1d=imgxyb[:,:,:7].reshape((imgxyb.shape[0]*imgxyb.shape[1],imgxyb.shape[2]))
This should be:
img1d=imgxyb[:,:,:7].reshape((imgxyb.shape[0]*imgxyb.shape[1],7))
I have a 3D numpy array and I am trying to volume render it using VTK. However, I get a completely different volume rendering when I visualise it. I suspect it has something to do with my conversion of numpy array to the VTK image format but I can't seem to figure out where I am going wrong. I have uploaded the numpy array here.
Can someone help me figure out where I'm going wrong?
This is my code:
#!/usr/bin/env python
import os
import numpy as np
ArrayDicom = np.load('test3.npy')
data_matrix = ArrayDicom
w, d, h = ArrayDicom.shape
colors = vtkNamedColors()
iso_value = 200
reader = vtkImageImport()
data_string = data_matrix.tobytes()
reader.CopyImportVoidPointer(data_string, len(data_string))
reader.SetDataScalarTypeToUnsignedChar()
reader.SetNumberOfScalarComponents(1)
reader.SetDataExtent(0, w-1, 0, d-1, 0, h-1)
reader.SetWholeExtent(0, w-1, 0, d-1, 0, h-1)
reader.Update()
volume = vtkImageData()
volume.DeepCopy(reader.GetOutput())
surface = vtkMarchingCubes()
surface.SetInputData(volume)
surface.ComputeNormalsOn()
surface.SetValue(0, iso_value)
renderer = vtkRenderer()
renderer.SetBackground(colors.GetColor3d('DarkSlateGray'))
render_window = vtkRenderWindow()
render_window.AddRenderer(renderer)
render_window.SetWindowName('MarchingCubes')
interactor = vtkRenderWindowInteractor()
interactor.SetRenderWindow(render_window)
mapper = vtkPolyDataMapper()
mapper.SetInputConnection(surface.GetOutputPort())
mapper.ScalarVisibilityOff()
actor = vtkActor()
actor.SetMapper(mapper)
actor.GetProperty().SetColor(colors.GetColor3d('MistyRose'))
renderer.AddActor(actor)
render_window.Render()
interactor.Start()
This is my volume rendering:
This is my expected volume rendering:
Numpy uses a different array ordering than VTK. You should be able to re-order w, h and d to get the right thing.
This is how you want it:
h, d, w = ArrayDicom.shape
OK, here's a conversion script that I used to convert to a VTK file:
import numpy as np
import SimpleITK as sitk
x = np.load("test3.npy")
y = sitk.GetImageFromArray(x)
sitk.WriteImage(y, "test3.vtk")
It's not as nice as correctly getting the VTK image import to work, but, well, I'm a SimpleITK guy, and I know that converting numpy works in SimpleITK.
My code reads a DICOM file, takes the pixel information to a numpy array then it modifies the numpy array. It uses lists because im trying to operate with multiple DICOM files at the same time.
I havent found any information on how to take my modified numpy array and make it a DICOM file again so i can use it outside Python.
#IMPORT
import cv2
import numpy as np
from matplotlib import pyplot as plt
import matplotlib.pyplot as plt
import SimpleITK as sitk
from glob import glob
import pydicom as dicom
data_path = "C:\\Users\\oliva\\Desktop\\Py tesis\\dicom\\"
output_path = working_path = "C:\\Users\\oliva\\Desktop\\Py tesis\\dicom1\\"
path = glob(data_path + '/*.dcm')
#Checks if we are in the correct path
print ("Total of %d DICOM images.\nFirst 5 filenames:" % len(path))
print ('\n'.join(path[:14]))
data_set = []
for element in path:
imagen=sitk.ReadImage(element)
#imagen = cv2.imread(element)
array_imagen = sitk.GetArrayViewFromImage(imagen)
array2_imagen=array_imagen[0]
imagen_array_norm = np.uint8(cv2.normalize(array2_imagen, None, 0, 255, cv2.NORM_MINMAX))
data_set.append(imagen_array_norm)
#Check
print(len(data_set))
print(type(data_set[1]))
plt.imshow(data_set[4], cmap=plt.cm.gray)
#Equalization
data_set_eq = equal(data_set)
print(len(data_set_eq))
print(type(data_set_eq[6]))
plt.imshow(data_set_eq[7], cmap=plt.cm.gray)
#Filtering
data_set_m = median(data_set)
print(len(data_set_m))
print(type(data_set_m[6]))
plt.imshow(data_set_m[8], cmap=plt.cm.gray)
#Functions
def equal(data):
data_set_eq = []
for element in data_set:
imagen_array_eq = cv2.equalizeHist(element)
data_set_eq.append(imagen_array_eq)
return data_set_eq
def median(data):
data_set_m = []
for element in data_set:
imagen_array_m =cv2.medianBlur(element,5)
data_set_m.append(imagen_array_m)
return data_set_m
I would like some enlightenment on how to produce a DICOM file from my modified numpy array.
You can convert the numpy array back to a SimpleITK image, and then write it out as Dicom. The code would look something like this:
for x in data_set:
img = sitk.GetImageFromArray(x)
sitk.WriteImage(img, "your_image_name_here.dcm")
From the file name suffix, SimpleITK knows to write Dicom.
Note that the filtering you are doing can be accomplished within SimpleITK. You don't really need to use OpenCV. Check out the following filters in SimpleITK: IntensityWindowingImageFilter, AdaptiveHistogramEqualizationFilter, and MedianImageFilter.
https://itk.org/SimpleITKDoxygen/html/classitk_1_1simple_1_1IntensityWindowingImageFilter.html
https://itk.org/SimpleITKDoxygen/html/classitk_1_1simple_1_1AdaptiveHistogramEqualizationImageFilter.html
https://itk.org/SimpleITKDoxygen/html/classitk_1_1simple_1_1MedianImageFilter.html
I want to apply Hough Transform on stock prices (array of numbers).
I read OpenCV and scikit-image docs and examples ,but got nothing how to apply the transformation to the arrays of numbers instead of images.
I created 2D array from data. First dimension is X(simply index of data) and second dimension is close prices.
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import pywt as wt
from skimage.transform import (hough_line, hough_line_peaks,probabilistic_hough_line)
from matplotlib import cm
path = "22-31May-100Tick.csv"
df = pd.read_csv(path)
y = df.Close.values
x = np.arange(0,len(y),1)
data = []
for i in x:
a = [i,y[i]]
data.append(a)
data = np.array(data)
How is it possible to apply the transformation with OpenCV or sickit-image?
Thank you