I am new in python can anyone help me how can I save the prediction mask as image I want to save y_batch_pred as image

Hi @Aya_Elfatyany, You can save the prediction mask as image using the below code

from PIL import Image
y_batch_pred=tf.random.normal((80,80,1)) #lets assume tf.random.normal is model predictions 
image_array = np.squeeze(y_batch_pred) 
image = Image.fromarray((image_array).astype('uint8'))
image.save('prediction_mask.png')

Thank You!

I run the above code and give me this error

KeyError Traceback (most recent call last)
File /usr/lib/python3/dist-packages/PIL/Image.py:2680, in fromarray(obj, mode)
2679 try:
→ 2680 mode, rawmode = _fromarray_typemap[typekey]
2681 except KeyError:

KeyError: ((1, 1, 256), ‘|u1’)

During handling of the above exception, another exception occurred:

TypeError Traceback (most recent call last)
Cell In[22], line 10
8 # for saving predict as png image
9 image_array = np.squeeze(y_batch_pred)
—> 10 image = Image.fromarray((image_array).astype(‘uint8’))
11 image.save(‘prediction_mask.png’)
12 #y_batch_pred = np.squeeze(y_batch_pred, axis=0)
13 #tf.keras.preprocessing.image.save_img(‘/home/aya/mywork/training/saved/y_batch_pred.png’,y_batch_pred)

File /usr/lib/python3/dist-packages/PIL/Image.py:2682, in fromarray(obj, mode)
2680 mode, rawmode = _fromarray_typemap[typekey]
2681 except KeyError:
→ 2682 raise TypeError(“Cannot handle this data type: %s, %s” % typekey)
2683 else:
2684 rawmode = mode

TypeError: Cannot handle this data type: (1, 1, 256), |u1

Hi @Aya_Elfatyany, As your y_batch_pred has a shape of (32,160,256), you have to use iterate through each image for saving it.

y_batch_pred=tf.random.normal((32,160,256))
image_array = np.squeeze(y_batch_pred)
for i in range(32):
  image=Image.fromarray((image_array[i].astype('uint8')))
  image.save(output_path[i])

Thank You.

Thanks for helping me but I tried this before but give me black image, my image is (batch_size, img_height, img_weight) as (32, 160, 256), the first one is batch_size not number of image

Hi @Aya_Elfatyany, The batch_size refer to a number of samples.

You’re getting black images because the y_batch_pred does not contain channel information. so while converting numpy to image it is considered a single channel. so the images are saved in gray scale(black and white) format.

This is my following code:

training model and draw loss and iou

from keras.callbacks import Callback
try:
with tf.device(‘/device:GPU:2’):
from livelossplot import PlotLossesKeras
loss_history = model.fit(
kitti_train,
steps_per_epoch=40,
epochs=2,
validation_data=kitti_val,
callbacks=[ PlotLossesKeras()]
)
except RuntimeError as e:
print(e)

validation sample

X_batch, y_batch = kitti_val.sample()

print(X_batch.shape, y_batch.shape)

import tensorflow as tf
from PIL import Image
try:
with tf.device(‘/device:GPU:2’):
y_batch_pred = model.predict(X_batch)
print(X_batch.shape, y_batch.shape, y_batch_pred[:,:,:,0].shape)
print(calc_IOU_loss(y_batch,y_batch_pred))
# for saving predict as png image
#y_batch_pred = np.squeeze(y_batch_pred, axis=0)
#tf.keras.preprocessing.image.save_img(‘/home/aya/mywork/training/saved/y_batch_pred.png’,y_batch_pred)
except RuntimeError as e:
print(e)

output of the last step

(32, 160, 256, 3) (32, 160, 256) (32, 160, 256)
tf.Tensor(-0.18904544, shape=(), dtype=float32)

I want to pass the y_batch_predict to another model that is why I want to save it as png images I tried many many things but not working do you know any way to pass this output as numpy arrray to model instead of png images ? Thanks for your helping and replying to me

Hi @Aya_Elfatyany, As model.predict( ) gives numpy array you can direct pass that array to the another model. If you want to create a dataset you can use dataset=tf.data.Dataset.from_tensor_slices(y_batch_pred). Thank You.

I am sorry for ditrubing you all time and Thanks for your replying, but for another model need this numpy array as png image show how can i pass it like this instead of png images because it is part of the dataset not the whole dataset

Hi @Aya_Elfatyany, Even for passing images to the model the images should be converted to numpy array or tensors. The image array or tensor contains the values of the pixels of the image. Thank You.

this is my whole code: i tried all the code but nothing is working with me so could you please accorrding to that code can I save y_batch_predict as png images ? Thanks
import numpy as np # linear algebra
import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)
import cv2
import matplotlib.pyplot as plt
import os

from collections import defaultdict
import os
for dirname, _, filenames in os.walk(‘/home/aya/mywork/training’):
print(‘data amount::’, len(filenames), ': ', dirname)
from os import listdir
from os.path import isfile, join
from sklearn.model_selection import train_test_split
import gc; gc.enable() # memory is tight
import random
import random

plt.rcParams[‘figure.figsize’] = (25, 14)

import tensorflow.keras as keras
print(tf.version)

SEED = 5000

def set_seed(SEED):
np.random.seed(SEED)
random.seed(SEED)
tf.random.set_seed(SEED)

return SEED

set_seed(SEED)
BASE_DIR = ‘/home/aya/mywork/training’
LABEL_PATH = os.path.join(BASE_DIR,‘/home/aya/mywork/training/label_2’)
IMAGE_PATH = os.path.join(BASE_DIR,‘/home/aya/mywork/training/image_2’)
#IMAGE_STEREO_PATH = os.path.join(BASE_DIR,‘data_object_image_3/training’)
CALIB_PATH = os.path.join(BASE_DIR,‘/home/aya/mywork/training/calib’)
LIDAR_PATH = os.path.join(BASE_DIR,‘/home/aya/mywork/training/velodyne’)

IMAGE_WIDTH = 256
IMAGE_HEIGHT = 160

repair data as dataset as csv file

images = [(f) for f in listdir(IMAGE_PATH) if isfile(join(IMAGE_PATH, f))]
masks = [(f) for f in listdir(LABEL_PATH) if isfile(join(LABEL_PATH, f))]
masks.sort()

df = pd.DataFrame(np.column_stack([masks]), columns=[‘masks’])
df[‘images’] = df[‘masks’].apply(lambda x: x[:-3]+‘png’)

We check that all masks have associated images

no_images = df[df[‘images’].apply(lambda i: i not in images)]
if(len(no_images)>0):
print(“Some masks do not have their own images”)
print(no_images)
else:
print(“VERY GOOD: All masks have their images”)

img = cv2.imread(os.path.join(IMAGE_PATH, ‘000074.png’) )
print('Image shape: ', img.shape)
print(df.shape)
df.head()

determine labels for each image

def get_labels(label_filename):
data = pd.read_csv(os.path.join(LABEL_PATH,label_filename), sep=" ",
names=[‘label’, ‘truncated’, ‘occluded’, ‘alpha’,
‘bbox_xmin’, ‘bbox_ymin’, ‘bbox_xmax’,
‘bbox_ymax’, ‘dim_height’, ‘dim_width’, ‘dim_length’,
‘loc_x’, ‘loc_y’, ‘loc_z’, ‘rotation_y’, ‘score’])

return data

get_labels(‘000074.txt’)

2d boundbox for object in each image

def open_image(image_filename):
return cv2.imread(os.path.join(IMAGE_PATH, image_filename))
def draw_box2d_id(id):
return draw_box2d(open_image(id + ‘.png’),
get_labels(id + ‘.txt’))
LABEL_COLORS = {
‘Car’: (255,0,0),
‘Van’: (255,255,0),
‘Truck’: (255,255,255),
‘Pedestrian’: (0,255,255),
‘Person_sitting’: (0,255,255),

'Cyclist': (0,128,255), 
'Tram': (128,0,0),
'Misc': (0,255,255),
'DontCare': (255,255,0)

}
def draw_box2d(image, labels, ax = None):

img = image.copy()
for index, row in labels.iterrows():
    left_corner = (int(row.bbox_xmin), int(row.bbox_ymin))
    right_corner = (int(row.bbox_xmax), int(row.bbox_ymax))
    label_color = LABEL_COLORS.get(row.label,(0,255,0))
    
    img = cv2.rectangle(img, 
                        left_corner, right_corner, label_color, 1)
    img = cv2.putText(img, str(row.label), 
                      (left_corner[0] + 10, left_corner[1] - 4) , 
                      cv2.FONT_HERSHEY_SIMPLEX, 0.5, 
                      label_color, 1)
if ax == None:
    plt.imshow(img)
else:
    ax.imshow(img)

draw_box2d_id(‘000074’)

3d pointnet for object

3d pointnet for object

def get_calibration(id):
filepath = os.path.join(CALIB_PATH, id + ‘.txt’)

""" Read in a calibration file and parse into a dictionary.
Ref: https://github.com/utiasSTARS/pykitti/blob/master/pykitti/utils.py
"""
data = {}
with open(filepath, "r") as f:
    for line in f.readlines():
        line = line.rstrip()
        if len(line) == 0:
            continue
        key, value = line.split(":", 1)
    
        try:
            data[key] = np.array([float(x) for x in value.split()])
        except ValueError:
            pass
data['P'] = np.reshape(data['P2'], [3, 4])

return data

def rotx(t):
“”" 3D Rotation about the x-axis. “”"
c = np.cos(t)
s = np.sin(t)
return np.array([[1, 0, 0], [0, c, -s], [0, s, c]])

def roty(t):
“”" Rotation about the y-axis. “”"
c = np.cos(t)
s = np.sin(t)
return np.array([[c, 0, s], [0, 1, 0], [-s, 0, c]])

def rotz(t):
“”" Rotation about the z-axis. “”"
c = np.cos(t)
s = np.sin(t)
return np.array([[c, -s, 0], [s, c, 0], [0, 0, 1]])
def project_to_image(pts_3d, P):
“”" Project 3d points to image plane.
Usage: pts_2d = projectToImage(pts_3d, P)
input: pts_3d: nx3 matrix
P: 3x4 projection matrix
output: pts_2d: nx2 matrix
P(3x4) dot pts_3d_extended(4xn) = projected_pts_2d(3xn)
=> normalize projected_pts_2d(2xn)
<=> pts_3d_extended(nx4) dot P’(4x3) = projected_pts_2d(nx3)
=> normalize projected_pts_2d(nx2)
“”"
n = pts_3d.shape[0]
pts_3d_extend = np.hstack((pts_3d, np.ones((n, 1))))
# print(('pts_3d_extend shape: ', pts_3d_extend.shape))
pts_2d = np.dot(pts_3d_extend, np.transpose(P)) # nx3
pts_2d[:, 0] /= pts_2d[:, 2]
pts_2d[:, 1] /= pts_2d[:, 2]
return pts_2d[:, 0:2]
def compute_box_3d(obj, P):
# compute rotational matrix around yaw axis
R = roty(obj.rotation_y)

# 3d bounding box dimensions
l = obj.dim_length
w = obj.dim_width
h = obj.dim_height

# 3d bounding box corners
x_corners = [l / 2, l / 2, -l / 2, -l / 2, l / 2, l / 2, -l / 2, -l / 2]
y_corners = [0, 0, 0, 0, -h, -h, -h, -h]
z_corners = [w / 2, -w / 2, -w / 2, w / 2, w / 2, -w / 2, -w / 2, w / 2]

corners_3d = np.dot(R, np.vstack([x_corners, y_corners, z_corners]))
# print corners_3d.shape
corners_3d[0, :] = corners_3d[0, :] + obj.loc_x
corners_3d[1, :] = corners_3d[1, :] + obj.loc_y
corners_3d[2, :] = corners_3d[2, :] + obj.loc_z
# print 'cornsers_3d: ', corners_3d
# only draw 3d bounding box for objs in front of the camera
if np.any(corners_3d[2, :] < 0.1):
    corners_2d = None
    return corners_2d, np.transpose(corners_3d)

# project the 3d bounding box into the image plane
corners_2d = project_to_image(np.transpose(corners_3d), P)
# print 'corners_2d: ', corners_2d
return corners_2d, np.transpose(corners_3d)

def draw_projected_box3d(image, qs, color=(0, 255, 0), thickness=2):

qs = qs.astype(np.int32)

for k in range(0, 4):
    # Ref: http://docs.enthought.com/mayavi/mayavi/auto/mlab_helper_functions.html
    i, j = k, (k + 1) % 4
    # use LINE_AA for opencv3
    # cv2.line(image, (qs[i,0],qs[i,1]), (qs[j,0],qs[j,1]), color, thickness, cv2.CV_AA)
    cv2.line(image, (qs[i, 0], qs[i, 1]), (qs[j, 0], qs[j, 1]), color, thickness)
    i, j = k + 4, (k + 1) % 4 + 4
    cv2.line(image, (qs[i, 0], qs[i, 1]), (qs[j, 0], qs[j, 1]), color, thickness)

    i, j = k, k + 4
    cv2.line(image, (qs[i, 0], qs[i, 1]), (qs[j, 0], qs[j, 1]), color, thickness)
return image

def draw_box3d_id(id):
“”"
pozwala zobazyc jakie BoundingBox sa dla naszego zestawu danych
“”"
calib = get_calibration(id)
return draw_box3d(open_image(id + ‘.png’),
get_labels(id + ‘.txt’), calib)
def draw_box3d(image, labels, calib, ax = None):
img = image.copy()
for index, row in labels.iterrows():
label_color = LABEL_COLORS.get(row.label,(0,255,0))
if row.label == “DontCare”:
left_corner = (int(row.bbox_xmin), int(row.bbox_ymin))
right_corner = (int(row.bbox_xmax), int(row.bbox_ymax))
img = cv2.rectangle(img,
left_corner, right_corner, label_color, 1)
continue

    box3d_pts_2d, _ = compute_box_3d(row, calib['P'])
    if box3d_pts_2d is None:
        continue
    
    img = draw_projected_box3d(img, box3d_pts_2d , label_color, 1)

if ax == None:
    plt.imshow(img)
else:
    ax.imshow(img)

draw_box3d_id(‘000074’)

generate mask for the object in image

DTYPE = np.float64

def get_image(path):
return cv2.imread(path)

def create_mask(mask_dir, img_shape):

mask = np.zeros(shape=(img_shape[0], img_shape[1], 1), dtype = DTYPE)

with open(mask_dir) as f:
    content = f.readlines()
content = [x.split() for x in content] 
for item in content:
    if item[0]=='Car' or item[0]=='Truck' or item[0]=='Van' or item[0]=='Pedestrian':
        ul_col, ul_row = int(float(item[4])), int(float(item[5]))
        lr_col, lr_row = int(float(item[6])), int(float(item[7]))
        
        mask[ul_row:lr_row, ul_col:lr_col, 0] = 1 
return mask

def draw_mask(image, mask, ax = None):
rgb_mask = np.repeat(mask, 3, axis = 2)
img = cv2.addWeighted( image, 0.5, rgb_mask, 0.5, 0)
if ax == None:
plt.imshow(img)
else:
ax.imshow(img)
def draw_mask_id(id):
img = np.array(get_image(os.path.join(IMAGE_PATH,id + ‘.png’)) / 255.0, dtype = DTYPE)
mask = create_mask(os.path.join(LABEL_PATH, id + ‘.txt’), img.shape )
draw_mask(img,mask)
plt.show()
draw_mask_id(‘000074’)

data generator

from abc import ABCMeta, abstractmethod
import imgaug.augmenters as iaa
from imgaug.augmentables.segmaps import SegmentationMapsOnImage

class DataGenerator(tf.keras.utils.Sequence):
“”"
Ta abstrakcyjna klasa to jest wszystko co trzeba zaprogramować dla ImageDataGenerator.
Dodaliśmy metodę get_data(), która pobierze nam potrzeby batch size.
“”"
def init(self,indices, batch_size, shuffle):
self.indices = indices
self.batch_size = batch_size
self.shuffle = shuffle

    self.on_epoch_end()
    
def __len__(self):
    return len(self.indices) // self.batch_size

def __getitem__(self, index):
    index = self.index[index * self.batch_size:(index + 1) * self.batch_size]
    batch = [self.indices[k] for k in index]
    
    return self.get_data(batch)

def sample(self):
    return self[random.randint(0,len(self))]

def on_epoch_end(self):
    self.index = np.arange(len(self.indices))
    if self.shuffle == True:
        np.random.shuffle(self.index)

def get_data(self, batch):
    raise NotImplementedError

prepare ktti dataset put images and masks with the same shape

class KittiDataGenerator(DataGenerator):
“”"
Bounding Box dla obiektow.
“”"
def init(self,
df,
shape = (IMAGE_WIDTH, IMAGE_HEIGHT),

             batch_size=32, 
             shuffle=True, 
             
             augmentation = None,
             
             image_col = 'images',
             mask_col = 'masks',
             
             label_path = LABEL_PATH,
             image_path = IMAGE_PATH
            ):
    
    self.df = df
    self.shape = shape

    self.image_col = image_col
    self.mask_col = mask_col
    self.label_path = label_path
    self.image_path = image_path
    self.augmentation = augmentation
    super().__init__(self.df.index.tolist(), batch_size, shuffle)

def get_x(self, index):
    return get_image(
        os.path.join(self.image_path, self.df.loc[index][self.image_col])
    ) 

def get_y(self, index, shape):
    return create_mask(os.path.join(self.label_path, self.df.loc[index][self.mask_col]),shape) 
def get_data(self, batch):
    batch_X = []
    batch_y = []
    
    for i in batch:
        image_r = self.get_x(i)
        mask_r = self.get_y(i, image_r.shape)
        
        # w for cv2.resize, we reverse the size, first the height, then the width
        image_r = cv2.resize(image_r, (self.shape[0], self.shape[1]))
        # mask_r after transformation will not have a value of 0.1 and a value between 0 and 1
        mask_r = cv2.resize(mask_r,(self.shape[0], self.shape[1]))
        
        if self.augmentation is not None:
            mask_r = np.array(mask_r, dtype=np.int32)
            segmap = SegmentationMapsOnImage(mask_r, shape=image_r.shape)
            image_r, segmap = self.augmentation(image = image_r, segmentation_maps = segmap)
            mask_r = segmap.get_arr().astype(np.float64)
            
            
        batch_X.append(image_r)
        batch_y.append(mask_r)
    
    batch_X = np.array(batch_X)
    batch_y = np.array(batch_y)
    return batch_X  / 255.0, batch_y

seq = iaa.Sequential([
iaa.Dropout([0.00, 0.06]), # drop 5% or 20% of all pixels
iaa.Sharpen((0.0, 0.1)), # sharpen the image
iaa.Multiply((0.5, 1.5), per_channel=0.5), # brightness
iaa.Affine(rotate=(-10, 10)), # rotate by -45 to 45 degrees (affects segmaps)
iaa.GammaContrast((0.5, 2.0))
])

image_generator = KittiDataGenerator(df,
shape = (IMAGE_WIDTH, IMAGE_HEIGHT),
augmentation = seq)
batch_X,batch_y = image_generator.sample()
print('Input : ‘, batch_X.shape, batch_X.dtype,’ max: ', batch_X.max(),
'\nOutput: ', batch_y.shape, batch_y.dtype, ’ max: ', batch_y.max())

calculate the IOU

def calc_IOU(y_true, y_pred, smooth=1):
y_true_f = keras.layers.Flatten()(y_true)
y_pred_f = keras.layers.Flatten()(y_pred)

intersection = keras.backend.sum(y_true_f*y_pred_f)

return (2*(intersection + smooth) / (keras.backend.sum(y_true_f) + keras.backend.sum(y_pred_f) + smooth))

def calc_IOU_loss(y_true, y_pred):
return -calc_IOU(y_true, y_pred)

calc_IOU_loss(batch_y,batch_y) #

show data

def show_data(X,y, y_pred = None):
if y_pred is None:
y_pred = y

for x_i,y_i,y_pred_i in zip(X,y,y_pred):
    im = np.array(255*x_i,dtype=np.uint8)
    im_mask = np.array(255*y_i,dtype=np.uint8)
    im_pred = np.array(255*y_pred_i,dtype=np.uint8)
    im_pred1 = np.array(255*y_pred_i,dtype=np.uint8)

    rgb_mask_pred = cv2.cvtColor(im_pred,cv2.COLOR_GRAY2RGB)
    rgb_mask_pred1 = cv2.cvtColor(im_pred,cv2.COLOR_GRAY2RGB)
    temp1 = rgb_mask_pred[:,:,1:3]
    temp2 = rgb_mask_pred[:,:,1:2]
    rgb_mask_pred[:,:,1:3] = 0*rgb_mask_pred[:,:,1:3]
    rgb_mask_true= cv2.cvtColor(im_mask,cv2.COLOR_GRAY2RGB)
    rgb_mask_true[:,:,0] = 0*rgb_mask_true[:,:,0]
    rgb_mask_true[:,:,2] = 0*rgb_mask_true[:,:,2]

print(im.shape, rgb_mask_pred.shape)

    img_pred = cv2.addWeighted(rgb_mask_pred,0.5,im,0.5,0)
    img_true = cv2.addWeighted(rgb_mask_true,0.5,im,0.5,0)
    
    loss = calc_IOU_loss(np.array([y_i]),np.array([y_pred_i]))

    plt.figure(figsize=(20,8))
    plt.subplot(1,3,1)
    plt.imshow(im)
    plt.title('Original image')
    plt.axis('off')
    plt.subplot(1,3,2)
    plt.imshow(img_pred)
    plt.title(f'Predicted masks {loss:0.4f}')
    plt.axis('off')
    plt.subplot(1,3,3)
    plt.imshow(img_true)
    plt.title('ground truth datasets')
    plt.axis('off')
    plt.tight_layout(pad=0)
    plt.show()

show_data(batch_X[:2], batch_y[:2])

spilt data train and test

set_seed(SEED)

df_train, df_val = train_test_split(df, test_size=0.25, shuffle=True)
df_train.head()

kitti train and validation

kitti_train = KittiDataGenerator(df_train,
shape = (IMAGE_WIDTH, IMAGE_HEIGHT), augmentation = seq)

kitti_val = KittiDataGenerator(df_val,
shape = (IMAGE_WIDTH, IMAGE_HEIGHT))

batch_X, batch_y = kitti_train.sample()
show_data(batch_X[:2], batch_y[:2])

unet model

from tensorflow.keras import layers
from tensorflow.keras import models
from tensorflow.keras.optimizers import Adam

def upsample_conv(filters, kernel_size, strides, padding):
return layers.Conv2DTranspose(filters, kernel_size, strides=strides, padding=padding)

def upsample_simple(filters, kernel_size, strides, padding):
return layers.UpSampling2D(strides)

def create_model(image_width = IMAGE_WIDTH,image_height = IMAGE_HEIGHT,
upsample = upsample_simple ):
# input_img = layers.Input(batch_img.shape[1:], name = ‘RGB_Input’)
input_img = layers.Input((image_height, image_width,3), name = ‘RGB_Input’)
pp_in_layer = input_img

c1 = layers.Conv2D(8, (3, 3), activation='relu', padding='same')(pp_in_layer) # 
c1 = layers.Conv2D(8, (3, 3), activation='relu', padding='same')(c1)
p1 = layers.MaxPooling2D((2, 2))(c1)

c2 = layers.Conv2D(16, (3, 3), activation='relu', padding='same')(p1)
c2 = layers.Conv2D(16, (3, 3), activation='relu', padding='same')(c2)
p2 = layers.MaxPooling2D((2, 2))(c2)

c3 = layers.Conv2D(32, (3, 3), activation='relu', padding='same')(p2)
c3 = layers.Conv2D(32, (3, 3), activation='relu', padding='same')(c3)
p3 = layers.MaxPooling2D((2, 2)) (c3)

c4 = layers.Conv2D(64, (3, 3), activation='relu', padding='same')(p3)
c4 = layers.Conv2D(64, (3, 3), activation='relu', padding='same')(c4)
p4 = layers.MaxPooling2D(pool_size=(2, 2)) (c4)
c5 = layers.Conv2D(128, (3, 3), activation='relu', padding='same')(p4)
c5 = layers.Conv2D(128, (3, 3), activation='relu', padding='same')(c5)


u6 = upsample(64, (2, 2), strides=(2, 2), padding='same')(c5)

u6 = layers.concatenate([u6, c4])
c6 = layers.Conv2D(64, (3, 3), activation='relu', padding='same')(u6)
c6 = layers.Conv2D(64, (3, 3), activation='relu', padding='same')(c6)

u7 = upsample(32, (2, 2), strides=(2, 2), padding='same')(c6)
u7 = layers.concatenate([u7, c3])
c7 = layers.Conv2D(32, (3, 3), activation='relu', padding='same')(u7)
c7 = layers.Conv2D(32, (3, 3), activation='relu', padding='same')(c7)

u8 = upsample(16, (2, 2), strides=(2, 2), padding='same')(c7)
u8 = layers.concatenate([u8, c2])
c8 = layers.Conv2D(16, (3, 3), activation='relu', padding='same')(u8)
c8 = layers.Conv2D(16, (3, 3), activation='relu', padding='same')(c8)

u9 = upsample(8, (2, 2), strides=(2, 2), padding='same') (c8)
u9 = layers.concatenate([u9, c1], axis=3)
c9 = layers.Conv2D(8, (3, 3), activation='relu', padding='same')(u9)
c9 = layers.Conv2D(8, (3, 3), activation='relu', padding='same')(c9)

d = layers.Conv2D(1, (1, 1), activation='sigmoid')(c9)
seg_model = models.Model(inputs=[input_img], outputs=[d])

seg_model.compile(optimizer=Adam(lr=1e-4),
          loss=calc_IOU_loss, metrics=[calc_IOU])

seg_model.summary()

return seg_model

model = create_model()

training model and draw loss and iou

from keras.callbacks import Callback
try:
with tf.device(‘/device:GPU:2’):
from livelossplot import PlotLossesKeras
loss_history = model.fit(
kitti_train,
steps_per_epoch=40,
epochs=2,
validation_data=kitti_val,
callbacks=[ PlotLossesKeras()]
)
except RuntimeError as e:
print(e)

validation sample

X_batch, y_batch = kitti_val.sample()

print(X_batch.shape, y_batch.shape)

predict object

import tensorflow as tf
from PIL import Image
try:
with tf.device(‘/device:GPU:2’):
y_batch_pred = model.predict(X_batch)
print(X_batch.shape, y_batch.shape, y_batch_pred[:,:,:,0].shape)
print(calc_IOU_loss(y_batch,y_batch_pred))
except RuntimeError as e:
print(e)