Stitching multiple pngs into a h5 image h5py - python

I created an model in blender. From here I took 2d slices through the y-plane of that model leading to the following.
600 png files each corresponding to a ylocation i.e y=0, y=0.1 etc
Each png file has a resolution of 500 x 600.
I am now trying to merge the 600 pngs into a h5 file using python before loading the .h5 into some software. I find that each individual png file is read fine and looks great. However when I look at the final 3d image there is some stretching of the image, and im not sure how this is being created.
The images are resized (from 600x600 to 500x600, but I have checked and this is not the cause of the stretching). I would like to know why I am introducing such stretching in other planes (not y-plane).
Here is my code, please note that there is some work in progress here, hence why I append the dataset to a list (this is to be used for later code)
from PIL import Image
import sys
import os
import h5py
import numpy as np
import cv2
from datetime import datetime
dir_path = os.path.dirname(os.path.realpath(__file__))
sys.path.append(dir_path + '//..//..')
Xlen=500
Ylen=600
Zlen=600
directory=dir_path+"/LowPolyA21/"
for filename in os.listdir(directory):
if fnmatch.fnmatch(filename, '*.png'):
image = Image.open(directory+filename)
new_image = image.resize((Zlen, Xlen))
new_image.save(directory+filename)
dataset = np.zeros((Xlen, Zlen, Ylen), np.float)
# traverse all the pictures under the specified address
cnt_num = 0
img_list = sorted(os.listdir(directory))
os.chdir(directory)
for img in (img_list):
if img.endswith(".png"):
gray_img = cv2.imread(img, 0)
dataset[:, :, cnt_num] = gray_img
cnt_num += 1
dataset[dataset == 0] = -1
dataset=dataset.swapaxes(1,2)
datasetlist=[]
datasetlist.append(dataset)
dz_dy_dz = (float(0.001),float(0.001),float(0.001))
for j in range(Xlen):
for k in range(Ylen):
for l in range(Zlen):
if datasetlist[i][j,k,l]>1:
datasetlist[i][j,k,l]=1
now = datetime.now()
timestamp = now.strftime("%d%m%Y_%H%M%S%f")
out_h5_path='voxelA_'+timestamp+'_flipped'
out_h5_path2='voxelA_'+timestamp+'_flipped.h5'
with h5py.File(out_h5_path2, 'w') as f:
f.attrs['dx_dy_dz'] = dz_dy_dz
f['data'] = datasetlist[i] # Write data to the file's primary key data below
Example of image without stretching (in y-plane)
Example of image with stretching (in x-plane)

Related

How to merge images after spliting into grids?

I'm trying to split single image into multiple grids in order to reduce dimension and do some image processing on that and then combine back splitted image to single image.
currently Im splitting single image into 72 multiple grids as shown in below code
from imutils import paths
from PIL import Image
from itertools import product
import os
source_path = r'D:\Data\images'
dest_path = r'D:\Data\cropped_data\\'
all_images = list(paths.list_images(source_path))
for img_path in all_images:
img = Image.open(img_path)
w,h = img.size
d = 500
grid = product(range(0, h-h%d, d), range(0, w-w%d, d))
file_name = img_path.split('\\')[-1].split('.')[0]
print(file_name)
save_path = dest_path+file_name
print(save_path)
os.makedirs(save_path,exist_ok=True)
for i, j in grid:
box = (j, i, j+d, i+d)
out = save_path+'\\'+'cropped'+f'_{i}_{j}'+'.jpg'
print(out)
img.crop(box).save(out)
above code snippet crop image into 72 mulitple grids and saves it in folder, I'm doing some preprocessing and saving it in same folder, I want to merge these images again back to original size in same sequence , I'm trying below code to achieve this
import glob
from PIL import Image
from itertools import product
all_images = glob.glob(r'splitted_image_folder\*.png')
d = 500
w = 6016
h = 3376
new_im = Image.new('RGB',(w,h),(250,250,250))
grid = product(range(0,h-h%d,d),range(0,w-w%d,d))
for u,(i,j) in enumerate(grid):
img = Image.open(all_images[u])
new_im.paste(img,(i,j))
new_im.save("merged_img.png","PNG")
executing this code merge only half of images at the first half of image and leaving other half in white,instead of merging all grid images it only pasting half of the images , I'm not able to understand why its missing other half .
Any guide or suggestion to achieve this will be appreciated

cropping and slicing multiple images in a folder using python PIL or cv2, then saving in another folder

I am trying to crop all images in a folder and save them in another folder. Then split all the images I have cropped using the image_slicer library.
I know a similar question like this has been asked but the difference is that I don't want the original folder to contain the cropped photos.
Here is my code so far; it runs but does nothing:
from PIL import Image
import image_slicer
import os
path = 'BeforeAfter'
arr = os.listdir(path)
def crop():
for i in arr:
if os.path.isfile(i):
img = Image.open(i)
f, e = os.path.splitext(i)
left = 66.6
top = 37.4
right = 1212.4
bottom = 550.7
imCrop = img.crop((left, top, right, bottom))
imCrop.save("CroppedImages/", "PNG", quality= 100)
# tiles = image_slicer.slice(toslice, 12, save=False)
# image_slicer.save_tiles(tiles, directory='frames')
crop()

How to handle image with extension .nii.gz? Is it possible to convert them in grayscale format like (240,240)?

I have always work with images with extensions .png, .jpg, .jpeg Now, I have seen medical images with extension .nii.gz
I'm using python and I have read it with the following code:
path = "./Task01_BrainTumour/imagesTr"
path_list = glob.glob(path+'/*.gz') #list with all paths of image.nii.gz
img = nib.load(path_list[0]).get_data() #load a single image
Now the image is an array of float32 and it has the following shape (240, 240, 155, 4). I have read online that (240, 240, 155, 4) indicates that the image has size (240,240), 155 indicates the depth of the image object, namely there are 155 layers in every image object. However, this information related to the layer/depth is not clear to me, what does it mean that an image has some layers? Finally, 4 indicates the channel of the image.
I would like to convert these images in the classical format (240,240,3) for rgb or (240,240) in grayscale. I don't know if it is possible to do that.
You're halfway there.
It looks like you're using the Brain Tumours data from the Medical Segmentation Decathlon, and NiBabel to read the images. You can install e.g. scikit-image to save the JPGs.
from pathlib import Path
import numpy as np
import nibabel as nib
from skimage import io
def to_uint8(data):
data -= data.min()
data /= data.max()
data *= 255
return data.astype(np.uint8)
def nii_to_jpgs(input_path, output_dir, rgb=False):
output_dir = Path(output_dir)
data = nib.load(input_path).get_fdata()
*_, num_slices, num_channels = data.shape
for channel in range(num_channels):
volume = data[..., channel]
volume = to_uint8(volume)
channel_dir = output_dir / f'channel_{channel}'
channel_dir.mkdir(exist_ok=True, parents=True)
for slice in range(num_slices):
slice_data = volume[..., slice]
if rgb:
slice_data = np.stack(3 * [slice_data], axis=2)
output_path = channel_dir / f'channel_{channel}_slice_{slice}.jpg'
io.imsave(output_path, slice_data)

how to convert a nift folder to png images?

*library
there is a mostly known library imported from NumPy and imageio
import NumPy as np
import os
import nibabel as nib
import imageio
// method where I have I write code to convert a nift to png
Method
convert a nift(.nii) image to png image
def nii_to_image(niifile):
filenames = os.listdir(filepath) #read nii folder
slice_trans = []
#filename is the path of nii image
for f in filenames:
#Start reading nii files
img_path = os.path.join(filepath, f)
img = nib.load(img_path) #read nii
img_fdata = img.get_fdata()
fname = f.replace('.nii','')
# Remove the nickname of nii
img_f_path = os.path.join(imgfile, fname)
#Create a folder corresponding to the image of nii
if not os.path.exists(img_f_path):
os.mkdir(img_f_path) #New folder
# to image
(x,y,z) = img.shape
for i in range(z): #x is the sequence of images
silce = img_fdata[i, :, :] #Select which direction the slice can be
imageio.imwrite(os.path.join(img_f_path,'{}.png'.format(i)), silce) #Save image
#main function where fill path was gived
main
if __name__ == '__main__':
filepath = '/content/drive/MyDrive/sem 8/dataset/pr'
imgfile = '/content/drive/MyDrive/sem 8/dataset/propi'
nii_to_image(filepath)
After you load the nifti file as NumPy array as you did, run on every slice (z from img.shape) and then save the array to png.
Make sure that when you run on each slice you save only the existing one (the z_slice_number):
slice = img_fdata[:, :, z_slice_numer]
And to save this slice you can do as follow (or another way from here):
matplotlib.image.imsave('name.png', slice)

Write an array of Dicom images

I have a folder of dicom images and I stored these images in an array and I would like to print them out in a different folder.
I cannot find a method that will write out each of the images like the cv2.imwrite
import pydicom
import skimage, os
import numpy as np
FolderPathName = r'FolderPathName'
slices = [pydicom.read_file(FolderPathName + imagename) for imagename in os.listdir(FolderPathName)]
# Sort the dicom slices in their respective order
slices.sort(key=lambda x: int(x.InstanceNumber))
for x in range(len(slices)):
#write the images in a new folder
Method 1:
In your case,
The answer is ...
import pydicom
import skimage, os
import numpy as np
FolderPathName = r'FolderPathName'
slices = [pydicom.read_file(FolderPathName + imagename) for imagename in os.listdir(FolderPathName)]
# Sort the dicom slices in their respective order
slices.sort(key=lambda x: int(x.InstanceNumber))
jpg_folder = '' # Set your jpg folder
for idx in range(len(slices)):
#write the images in a new folder
jpg_filepath = os.path.join( jpg_folder, "pic-{}.jpg".format(idx) )
np_pixel_array = slices[idx].pixel_array
cv2.imwrite(jpg_filepath, np_pixel_array)
Method 2:
But, there is better way to process dicom files ...
import pydicom
import os
import numpy as np
import cv2
dicom_folder = '' # Set the folder of your dicom files that inclued images
jpg_folder = '' # Set the folder of your output folder for jpg files
# Step 1. prepare your input(.dcm) and output(.jpg) filepath
dcm_jpg_map = {}
for dicom_f in os.listdir(dicom_folder):
dicom_filepath = os.path.join(dicom_folder, dicom_f)
jpg_f = dicom_f.replace('.dcm', '.jpg')
jpg_filepath = os.path.join(jpg_folder,jpg_f)
dcm_jpg_map[dicom_filepath] = jpg_filepath
# Now, dcm_jpg_map is key,value pair of input dcm filepath and output jpg filepath
# Step 2. process your image by input/output information
for dicom_filepath, jpg_filepath in dcm_jpg_map.items():
# convert dicom file into jpg file
dicom = pydicom.read_file(dicom_filepath)
np_pixel_array = dicom.pixel_array
cv2.imwrite(jpg_filepath, np_pixel_array)
In above code,
the Step 1 is focus on file path processing. It's good for your to porting your code into different environment easily.
The Step 2 is major code which focus on any kind of image processing.

Categories

Resources