0

I am learning CNN and I have found a script online that classifies building rooftops from satellite images. The script works just fine but I am not able to figure out a way to test the script on a new single image. I am showing the code briefly and then I will show what I have tried:

seq = iaa.Sequential([
    iaa.imgcorruptlike.Fog(severity=1),
    iaa.imgcorruptlike.Spatter(severity =1),
])

batch_size = 16
size = 512
epochs =50
version = 1 # version 2 for MobilV2unet
data_augmentation = True
model_type = 'UNet%d' % (version)
translearn = True

from tensorflow.keras.applications import MobileNetV2

def m_u_net(input_shape):
    inputs = Input(shape=input_shape, name="input_image")
    
    encoder = MobileNetV2(input_tensor=inputs, weights="imagenet", include_top=False, alpha=1.3)
    #encoder.trainable=False
    skip_connection_names = ["input_image", "block_1_expand_relu", "block_3_expand_relu", "block_6_expand_relu"]
    encoder_output = encoder.get_layer("block_13_expand_relu").output
    
    f = [16, 32, 48, 64]
    x = encoder_output
    for i in range(1, len(skip_connection_names)+1, 1):
        x_skip = encoder.get_layer(skip_connection_names[-i]).output
        x = UpSampling2D((2, 2))(x)
        x = Concatenate()([x, x_skip])
        
        x = Conv2D(f[-i], (3, 3), padding="same")(x)
        x = BatchNormalization()(x)
        x = Activation("relu")(x)
        
        x = Conv2D(f[-i], (3, 3), padding="same")(x)
        x = BatchNormalization()(x)
        x = Activation("relu")(x)
        
    x = Conv2D(1, (1, 1), padding="same")(x)
    x = Activation("sigmoid")(x)
    
    model = Model(inputs, x)
    return model

def load_rasters_simple(path, pathX, pathY ):  # Subset from original raster with extent and upperleft coord
    """Load training data pairs (two high resolution images and two low resolution images)"""
    pathXabs = os.path.join(path, pathX)
    pathYabs = os.path.join(path, pathY)
    le = len(os.listdir(pathXabs) )
        
    stackX = []
    stackY = []
    for i in range(0, le):
        fileX = os.path.join(pathXabs, os.listdir(pathXabs)[i])
        fileY = os.path.join(pathYabs, os.listdir(pathXabs)[i])
        dataX = gdal_array.LoadFile(fileX) #.astype(np.int),ysize=extent[1],xsize=extent[0]
        stackX.append(dataX)
        dataY = gdal_array.LoadFile(fileY) #.astype(np.int),ysize=extent[1],xsize=extent[0]
        stackY.append(dataY)
    stackX = np.array(stackX)
    stackY = np.array(stackY)
    return stackX, stackY 
X, Y= load_rasters_simple('/Users/vaibhavsaxena/Desktop/segmentation/Classification/Satellite dataset ó± (global cities)','image','label') 

def slice (arr, size, inputsize,stride):
    result = []
    if stride is None:
        stride = size
    for i in range(0, (inputsize-size)+1, stride):
        for j in range(0, (inputsize-size)+1, stride):
        
            s = arr[i:(i+size),j:(j+size), ]
            result.append(s)
 
    result = np.array(result)
    return result

def batchslice (arr, size, inputsize, stride, num_img):
    result = []
    for i in range(0, num_img):
        s= slice(arr[i,], size, inputsize, stride )
        result.append(s )
    result = np.array(result)
    result = result.reshape(result.shape[0]*result.shape[1], result.shape[2], result.shape[3], -1)
    return result

Y=batchslice(Y, size, Y.shape[1], size, Y.shape[0]).squeeze()
X_cl =batchslice(X_cl, size, X_cl.shape[1], size, X_cl.shape[0]) 

X_train = X_cl[:int(X_cl.shape[0]*0.8),]
Y_train = Y[:int(Y.shape[0]*0.8),]
X_test = X_cl[int(X_cl.shape[0]*0.8)+1:,] 
Y_test = Y[int(Y.shape[0]*0.8)+1:,] 

THEN the big unet model architecture. The whole script can be found here.

This model just works fine with the dataset. I am trying to test it with my own out of dataset image and this is what I have tried:

model = load_model('no_aug_unet_model.h5', custom_objects=dependencies)
model.compile(loss='binary_crossentropy', metrics=[iou],
              optimizer=Adam(learning_rate=lr_schedule(0)))

from keras.preprocessing import image

test_image= image.load_img('bangkok_noi_2.jpg', target_size = (2000, 2000))  
test_image = image.img_to_array(test_image)
test_image1 = test_image.reshape((1,2000,2000,3))
testpre = model.predict(test_image1)
img = Image.fromarray(test_image, 'RGB')
img.show()

The original shape of my test image is (1852, 3312, 3). I am getting a weirdly predicted image that makes no sense unlike the expectations. I believe, I am doing the wrong preprocessing with my test image. Any help would be extremely appreciated.

The whole script can be found here.

  • Have you seen how they predict? I didn't test or anything, but they use their own function plot_imgs to plot predictions. If you ctrl-f for plot_imgs, you will find ```plot_imgs( org_imgs=X_test [ :,:,:], mask_imgs=Y_test[ :,:,:], pred_imgs=testpre[:,:,: ], nm_img_to_plot=3) # optional - number of images to plot ``` – cbolwerk Oct 29 '20 at 12:44
  • They use plot_imgs() to plot the predictions. Predictions are done like following: `testpre = unet_model.predict(X_test[0:1 ,])` – Vaibhav Saxena Oct 29 '20 at 12:51
  • So why don't you do that? – cbolwerk Oct 29 '20 at 12:54
  • They are doing for the test dataset. I am asking for a new foreign image. How to approach that? – Vaibhav Saxena Oct 29 '20 at 12:55
  • They load their data using the load_rasters_simple function. It seems that they use the gdal package for geodata(?). I'm not really sure, sorry. But their images are 512x512x3, so smaller than yours. But you can maybe download their dataset and see if you can get it working with their images. That would give some info to get it working on your own images. – cbolwerk Oct 29 '20 at 13:01
  • Thank you. That is a good idea. I will try that. – Vaibhav Saxena Oct 29 '20 at 13:04

0 Answers0