I have problem with preprocessing data set for deep learning.
I am using U-net.
I have training data, label data, test data size of 512x512.
I want patch based learning so i am trying to change 512x512 slices to multiple 64x64 slices so that I can train image with 64x64 patches. In my case I want to make 64x64 patches stride 32 pixel from original 512x512 Images.
For example, first patch is formed from (0,0) ~ (64,64) and the next patch is formed from (32,0) ~ (64 + 32, 64)
This is full code of data.py
#from keras.preprocessing.image import ImageDataGenerator, array_to_img, img_to_array, load_img
import numpy as np
import os
import glob
import cv2
from os.path import *
#from libtiff import TIFF
import matplotlib.pyplot as plt
class dataProcess(object):
def __init__(self, out_rows, out_cols):
"""
"""
self.out_rows = out_rows
self.out_cols = out_cols
def load_train_data(self):
imgs_row, imgs_col = 512,512
train_list = []
train_img = []
label_list = []
label_img = []
train_path = 'C:\\Users\\Lee Doyle\\unet\\data\\Train'
label_path = 'C:\\Users\\Lee Doyle\\unet\\data\\Label'
######################Traindata################################
print('-' * 30)
print('load train images...')
print('-' * 30)
for i in glob.glob(train_path + '/*.[tT][iI][fF]'):
train_list.append(abspath(i))
print(len(train_list))
for i in train_list:
# print(i)
img = cv2.imread(i, cv2.IMREAD_GRAYSCALE)
train_img.append(img.astype(np.float32)/255.0)
train_img = np.array(train_img)
print(train_img)
######################Labeldata################################
for i in glob.glob(label_path + '/*.[tT][iI][fF]'):
label_list.append(abspath(i))
for i in label_list:
img = cv2.imread(i, cv2.IMREAD_GRAYSCALE)
label_img.append(img.astype(np.float32) / 255.0)
label_img = np.array(label_img)
fig = plt.figure()
a=fig.add_subplot(1,2,1)
plt.imshow(train_img[0],cmap='gray')
a.set_title('trian image')
a=fig.add_subplot(1,2,2)
plt.imshow(label_img[0]+train_img[0],cmap='gray')
plt.imshow(label_img[0],cmap='gray')
a.set_title('Image with GT SEG ')
plt.show()
print(train_img.shape)
train_img = train_img.reshape(train_img.shape[0], imgs_row, imgs_col, 1)
label_img = label_img.reshape(label_img.shape[0], imgs_row, imgs_col, 1)
return train_img,label_img
def load_test_data(self):
imgs_row, imgs_col = 512,512
test_list = []
test_img = []
test_path = 'C:\\Users\\Lee Doyle\\unet\\data\\Test'
######################Testdata#################################
print('-' * 30)
print('load test images...')
print('-' * 30)
for i in glob.glob(test_path + '/*.[tT][iI][fF]'):
test_list.append(abspath(i))
for i in test_list:
img = cv2.imread(i, cv2.IMREAD_GRAYSCALE)
# img=cv2.resize(img,(512,512))
test_img.append(img.astype(np.float32) / 255.0)
test_img = np.array(test_img)
# mean = test_img.mean(axis=0)
# test_img -= mean
test_img=test_img.reshape(test_img.shape[0],imgs_row,imgs_col,1)
print(test_img.shape)
return test_img
if __name__ == "__main__":
mydata = dataProcess(512,512)
mydata.load_train_data()
mydata.load_test_data()
I think I need to add patch making code near this code.
for i in glob.glob(train_path + '/*.[tT][iI][fF]'):
train_list.append(abspath(i))
print(len(train_list))
for i in train_list:
# print(i)
img = cv2.imread(i, cv2.IMREAD_GRAYSCALE)
train_img.append(img.astype(np.float32)/255.0)
train_img = np.array(train_img)
print(train_img)
I apppreciate your help.
Related
I am using the following code to generate the GradCam maps for the input images. I am not able to resize the subplot to visualise them properly as soon in the figure below.
Code:
import cv2
def NormalizeData(data):
return (data - np.min(data)) / (np.max(data) - np.min(data))
for i in range(5):
img = train_loader.dataset[i][0].to(device)
mdlOut = model(img)
#img = torch.tensor(img, requires_grad=True)
img=img.clone().detach().requires_grad_(True) #newline
out = model(img)
idx = out.argmax()
yc = out[0,idx]
yc.backward()
rawGrad = img.grad.cpu().detach().numpy()
grad = NormalizeData(rawGrad)
avgGrad = np.mean(np.abs(grad),axis=(1,2))
img = NormalizeData(img.cpu().detach().numpy())
CAM = NormalizeData(avgGrad[0]*img[0,:,:] \+ avgGrad[1]*img[1,:,:] \+ avgGrad[2]*img[2,:,:])
plt.subplot(20,2,2*i+1)
plt.imshow(CAM,cmap='jet')
plt.subplot(20,2,2*i+2)
plt.imshow(np.einsum('kli->lik',img))
I'm doing semantic segmentation for microscope image stacks.
My code works fine but the thing is it only uses one core of my CPU which makes me wait a long time to get the segmented images.
I recently knew that there are ways to use multicore processing with other python libraries, but I don't know how to implement it.
So someone can help me edit my code with one of the multiprocessing libraries?
My code is in the below.
import numpy as np
from patchify import patchify, unpatchify
import os
import cv2
from tqdm import tqdm
from tensorflow import keras
from tensorflow.keras.utils import normalize
import natsort
model = keras.models.load_model("C:/mymodel.h5", compile=False)
#creating recon image directory
recon_image_directory = "C:/Users/recon"
if not os.path.exists(recon_image_directory):
os.makedirs(recon_image_directory)
large_image_path = "C:/original_images/"
check_images = natsort.natsorted(os.listdir(large_image_path))
for num, large_image_name in tqdm(enumerate(check_images), total=len(check_images)):
if (large_image_name.split('.')[1] == "tif"):
img = cv2.imread(large_image_path + large_image_name, 0)
patches = patchify(img, (256, 256), step=256)
predicted_patches = []
for i in range(patches.shape[0]):
for j in range(patches.shape[1]):
single_patch = patches[i,j,:,:] #(256, 256)
single_patch_norm = normalize(np.array(single_patch), axis=1)
single_patch_input = np.stack((single_patch_norm,)*3, axis=-1) # (256, 256, 3)
single_patch_input = np.expand_dims(single_patch_input, 0) #(1,256,256,3)
single_patch_prediction = (model.predict(single_patch_input)[0,:,:,0]>0.5).astype(np.uint8)
predicted_patches.append(single_patch_prediction)
predicted_patches = np.array(predicted_patches)
predicted_patches_reshaped = np.reshape(predicted_patches, (patches.shape[0], patches.shape[1], 256,256) )
reconstructed_image = unpatchify(predicted_patches_reshaped, img.shape)
cv2.imwrite(recon_image_directory + "/recon"+'_' + str(num) + ".tif", reconstructed_image)
Does this snippet work? It should run each prediction in a separate process.
#ray.remote
def predict(large_image_name: str) -> None:
img = cv2.imread(large_image_path + large_image_name, 0)
patches = patchify(img, (256, 256), step=256)
predicted_patches = []
for i in range(patches.shape[0]):
for j in range(patches.shape[1]):
single_patch = patches[i,j,:,:] #(256, 256)
single_patch_norm = normalize(np.array(single_patch), axis=1)
single_patch_input = np.stack((single_patch_norm,)*3, axis=-1) # (256, 256, 3)
single_patch_input = np.expand_dims(single_patch_input, 0) #(1,256,256,3)
single_patch_prediction = (model.predict(single_patch_input)[0,:,:,0]>0.5).astype(np.uint8)
predicted_patches.append(single_patch_prediction)
predicted_patches = np.array(predicted_patches)
predicted_patches_reshaped = np.reshape(predicted_patches, (patches.shape[0], patches.shape[1], 256,256) )
reconstructed_image = unpatchify(predicted_patches_reshaped, img.shape)
cv2.imwrite(recon_image_directory + "/recon"+'_' + str(num) + ".tif", reconstructed_image)
futures = []
for num, large_image_name in tqdm(enumerate(check_images), total=len(check_images)):
if (large_image_name.split('.')[1] == "tif"):
futures.append(predict.remote(large_image_name))
ray.get(futures)
We also have a high-level abstraction for doing this sort of thing. If you're interested, you should check out the Ray AI Runtime (AIR).
i am trying to convert nrrd file into jpg by reading that nrrd image using pynrrd and then using the pixel i am trying to form an image but the out i am getting is terrible contrast image. Below is waht i have tried
import numpy as np
import nrrd
from PIL import Image
import numpy as np
filename = "/content/drive/MyDrive/CT.nrrd"
readdata, header = nrrd.read(filename)
print(readdata.shape) # (512, 512, 504)
for i in range(504):
if i == 200:
img = np.array(readdata[:,:,i])
print(img.shape)
print(np.amax(img))
img = (np.maximum(img, 0) / img.max()) * 255.0
img = Image.fromarray(np.uint8(img), mode = "L")
img.save(f'/content/testrgb{i}.png')
break
The output i am getting is this
Can someone please help me this
from PIL import Image
import numpy as np
import nrrd
def manipulating_nrrd_contrast(img, level):
img_c = img.astype(int).copy()
factor = (8 * (level+255)) / (255 * (259-level)) #This 8 here is the value that i changes manually by try and test and found out that this works best
img_c = factor * (img_c - 128) + 128
img_c = np.clip(img_c, 0, 255)
return img_c.astype(np.uint8)
filename = "/content/drive/MyDrive/CT.nrrd"
readdata, header = nrrd.read(filename)
tag_info = get_meta_data(header)
print(tag_info)
print(readdata.shape)
for i in range(readdata.shape[2]):
b = np.asarray(readdata[:,:,i]).astype(int)
final = Image.fromarray(manipulating_nrrd_contrast(b, 128))
final.save(f'/content/png/testrgb{i}.png')
And, The Result that i got is below
The problem: I am unable to process CNN model for training 8-channel .TIF images.
Expected Output: Map training data (train_ds) via gdal and train model.
data (images):
n = 600
shape = (256, 256, 8)
data structure:
project_photos/
....classes/
......barren/
......agriculture/
......wooded/
import numpy as np
import os
import PIL
import PIL.Image
import tensorflow as tf
import tensorflow_datasets as tfds
import pathlib
>print (tf.__version__)
2.1.0
data_dir = ".\projects\keras\projectA\project_photos\classes")
data_dir = pathlib.Path(data_dir)
image_count = len(list(data_dir.glob('*/*.tif')))
>print(image_count)
600
list_ds = tf.data.Dataset.list_files(str(data_dir/'*/*'), shuffle=False)
list_ds = list_ds.shuffle(image_count, reshuffle_each_iteration=False)
batch_size = 32
img_height = 256
img_width = 256
>for f in list_ds.take(5):
> print(f.numpy())
b'/home/projects/keras/projectA/project_photos/classes/barren/12345_b0001.tif'
b'/home/projects/keras/projectA/project_photos/classes/wooded//12345_w0001.tif'
b'/home/projects/keras/projectA/project_photos/classes/barren/12345_b0002.tif'
b'/home/projects/keras/projectA/project_photos/classes/agriculture//12345_a0001.tif'
b'/home/projects/keras/projectA/project_photos/classes/wooded/12345_w0002.tif'
# tree structure
>class_names = np.array(sorted([item.name for item in data_dir.glob('*')]))
print(class_names)
['barren' 'agriculture' 'wooded']
# train/validation split
val_size = int(image_count * 0.2)
train_ds = list_ds.skip(val_size)
val_ds = list_ds.take(val_size)
def get_label(file_path):
# convert the path to a list of path components
parts = tf.strings.split(file_path, os.path.sep)
# The second to last is the class-directory
one_hot = parts[-2] == class_names
# Integer encode the label
return tf.argmax(one_hot)
def decode_img(img):
# convert the compressed string to a 3D uint8 tensor
img = tf.image.decode_jpeg(img, channels=3)
# resize the image to the desired size
return tf.image.resize(img, [img_height, img_width])
def process_path(file_path):
label = get_label(file_path)
# load the raw data from the file as a string
img = tf.io.read_file(file_path)
img = decode_img(img)
return img, label
# Set `num_parallel_calls` so multiple images are loaded/processed in parallel.
train_ds = train_ds.map(process_path, num_parallel_calls=AUTOTUNE)
val_ds = val_ds.map(process_path, num_parallel_calls=AUTOTUNE)
I understand that tensorflow has limited support (experimental) for decode_tiff, and even if that did work - I am unable to use the latest version of TF that has that update.
This leaves me with attempting workarounds, the following - which have not succeeded:
"""
Updating decode_img(img) in attempt to process 8-channel .TIF raster
"""
#attempt, adding gdal_Open variable to decode_img
## fails due to image path (train_ds) being stored as byte.
x = gdal.Open(file_path)
Error: Not a string.
#attempt, modifying to extract PATH as str().
def process_path(file_path):
label = get_label(file_path)
# load the raw data from the file as a string
img = ''
for fpath in file_path:
img = fpath.numy()
img = decode_img(img)
return img, label
>train_ds = train_ds.map(process_path, num_parallel_calls=AUTOTUNE)
ValueError: len requires a non-scalar tensor, got one of shape Tensor("Shape:0", shape=(0,), dtype=int32)
#attempt, processing outside of `.map`, works just fine.
imgList = []
for elem in train_ds:
img = elem.numpy()
img = img.decode()
imgList.append(img)
file_path = imgList[0]
raster = gdal.Open(file_path)
bands = [raster.GetRasterBand(k + 1).ReadAsArray() for k in range (raster.RasterCount)]
n_bands = len(bands)
img_array = np.stack(bands,2)
img = tf.convert_to_tensor(img_array, dtype = tf.float32)
img = tf.image.resize(img, [img_height, img_width])
print(type(img))
print(img.numpy().shape)
<class: 'tensorflow.python.framework.ops.EagerTensor'>
(256, 256, 8)
So, any ideas on how I can get this to work within the TF framework - getting TF to process the raster via .map?
I've created a keras sequential LeNet model for predicting plant types and diseases using this dataset. The problem is, model.predict(x) gives me an array of long decimals. model.predict_classes(x) gives me a single number inside a list like [30] or [7]. I don't know which one I should use and how I would get a label. I've tried matching the numbers up myself, but some of them make no sense, even though my model had 80% val_acc. Here is my script for predicting:
import numpy as np
import tensorflow as tf
from tensorflow import keras
from keras.models import load_model, Sequential
from PIL import Image
import matplotlib.pyplot as plt
import cv2
import os
# width is [0]
# height it [1]
x = 0
def prep_pic(img_path):
img = Image.open(img_path)
old_width = img.size[0]
old_height = img.size[1]
square_width = 150
square_height = 150
if old_height > old_width:
square_width = old_width
square_height = old_width
if old_height <= old_width:
square_width = old_height
square_height = old_height
left = (old_width - square_width)/2
top = (old_height - square_height)/2
right = (old_width + square_width)/2
bottom = (old_height + square_height)/2
img2 = img.crop((left, top, right, bottom))
img2.resize = (-1, 150, 150, 3)
img2.save("pic.png")
img3 = plt.imread("pic.png")
#os.remove("pic.png")
img3 = cv2.resize(img3, (150, 150))
print(img3.shape)
return img3.reshape(-1, 150, 150, 3) # return the image with shaping that TF wants.
# I know that my data prep is terrible, but it works. If you have any suggestion for this, please feel free to add it.
prep_pic('../input/project-plantus/applescab.jpg')
model = Sequential()
model = load_model('../input/project-plantus/plantus_model.h5')
print(model.predict_classes([prep_pic('../input/project-plantus/applescab.jpg')]))
My model completely being inaccurate might be because of my data, or it isn't incorrect at all. I'll include my data prep for training my model here:
def train_data_gen(DIR, ID):
for img in os.listdir(DIR)[:1000]:
try:
path = DIR + '/' + img
img = plt.imread(path)
img = cv2.resize(img, (150, 150))
if img.shape == (150, 150, 3):
x.append(img)
y.append(ID)
except:
None