def predict_one_window_averaged(predict_model, image, window_size, num_output_channels): image_height = image.shape[0] image_width = image.shape[1] # Input image is expected to be a square, pad width or height as needed, # the padding will be cropped before returning the predicted image if image_height != image_width: pad_height = 0 pad_width = 0 if image_height > image_width: pad_width = image_height - image_width else: pad_height = image_width - image_height image = np.pad(image, ((0, pad_height), (0, pad_width), (0, 0)), 'edge') # Use the algorithm. The `pred_func` is passed and will process all the image 8-fold by tiling small # patches with overlap, called once with all those image as a batch outer dimension. Note that # model.predict(...) accepts a 4D tensor of shape (batch, x, y, nb_channels), such as a Keras model. prediction = predict_img_with_smooth_windowing( image, window_size=window_size, subdivisions= 2, # Minimal amount of overlap for windowing. Must be an even number. nb_classes=num_output_channels, pred_func=( lambda img_batch_subdiv: predict_model.predict(img_batch_subdiv))) return prediction[0:image_height, 0:image_width]
def main(flags): model = flags.model image = flags.image saver = tf.train.import_meta_graph(model + ".meta") config = tf.ConfigProto() config.gpu_options.allow_growth = True sess = tf.InteractiveSession(config=config) saver.restore(sess, model) X, mode = tf.get_collection("inputs") pred = tf.get_collection("outputs")[0] print('loading image') proj, geotrans, input_img = read_img(image) input_img = input_img[:, :, :3] input_img = np.asarray(input_img, dtype='uint8') label_pred = predict_img_with_smooth_windowing( input_img, window_size=256, subdivisions=2, batch_size=256, pred_func=( lambda img: sess.run(pred, feed_dict={X: img, mode: False}) ) ) label_pred = label_pred[:, :, 0] label_pred[np.where(label_pred >= 0.5)] = 1 label_pred[np.where(label_pred < 0.5)] = 0 label_pred = label_pred.astype(np.uint8) prd_name = "%s_%s_m%s_prd.tif" % (image[:-4], model.split('/')[0], model[-7:-5]) write_img(prd_name, proj, geotrans, label_pred)
def predict(model, type): """Predicts the test set images using the given model and its type. Parameters ---------- model : tf.keras.Model The TensorFlow model used for the predictions type : int The TensorFlow model type (0: U-Net, 1: UNet++, 2: UNet++ with deep supervision, 3: UNet++ with DS and custom loss) """ def img_float_to_uint8(img): rimg = img - np.min(img) rimg = (rimg / np.max(rimg) * PIXEL_DEPTH).round().astype(np.uint8) return rimg print("[INFO] Running prediction on submission set") if not os.path.isdir(PREDICTION_SUBMISSION_DIR): os.mkdir(PREDICTION_SUBMISSION_DIR) for i in range(1, 51): pimg = imread(SUBMISSION_DATA_DIR + f"test_{i}.png")[:, :, :IMG_CHANNELS] prediction = predict_img_with_smooth_windowing( pimg, window_size=IMG_WIDTH, subdivisions=2, # Minimal amount of overlap for windowing nb_classes=1, pred_func=(lambda img_batch_subdiv: model.predict(img_batch_subdiv) if type < 2 else model.predict(img_batch_subdiv)[0])) pimg = prediction w = pimg.shape[0] h = pimg.shape[1] cimg = np.zeros((w, h, 3), dtype=np.uint8) pimg *= 255 pimg = pimg.astype(np.uint8) pimg8 = np.squeeze(img_float_to_uint8(pimg)) cimg[:, :, 0] = pimg8 cimg[:, :, 1] = pimg8 cimg[:, :, 2] = pimg8 Image.fromarray(cimg).save(PREDICTION_SUBMISSION_DIR + f"gt_{i}.png") print(f"[INFO] Wrote test image number {i} on disk")
def predict(data_dir, output_dir, X, mode, pred): if not os.path.exists(output_dir): os.mkdir(output_dir) for i in range(0, 15000, 5000): for j in range(0, 15000, 5000): one_data = '%s/tile_%d_%d.tif' % (data_dir, i, j) one_data_output = '%s/pred_tile_%d_%d.tif' % (output_dir, i, j) print ("predict tile_%d_%d.tif" % (i, j)) proj, geotrans, input_img = read_img(one_data) label_pred_tiny = predict_img_with_smooth_windowing( input_img, window_size=768, subdivisions=2, batch_size=8, pred_func=( lambda img: sess.run(pred, feed_dict={X: img, mode: False}) ) ) label_pred_tiny = label_pred_tiny[:, :, 0] # label_pred_tiny[np.where(label_pred_tiny >= 0.3)] = 255 label_pred_tiny[label_pred_tiny<0.1] = 0 label_pred_tiny = label_pred_tiny.astype(np.float32) write_img(one_data_output, proj, geotrans, label_pred_tiny)
def main(epochs): # RTX fix #config = tf.compat.v1.ConfigProto() #config.gpu_options.allow_growth = True #allow_growth_session = tf.compat.v1.Session(config=config) #tf.compat.v1.keras.backend.set_session(allow_growth_session) gpu = tf.config.experimental.list_physical_devices('GPU') tf.config.experimental.set_memory_growth(gpu[0], True) # NON TWEAKABLE CONSTANTS # Image definition IMG_WIDTH = 400 IMG_HEIGHT = 400 IMG_CHANNELS = 3 PIXEL_DEPTH = 255 # Folder definitions IMAGE_DATA_PATH = 'training/images/' MASK_DATA_PATH = 'training/groundtruth/' MODEL_SAVE_LOCATION = 'road_segmentation_model.h5' SUBMISSION_DATA_DIR = 'test_set_images/' PREDICTION_SUBMISSION_DIR = 'predictions_submission/' IMAGES_FILENAMES = os.listdir(IMAGE_DATA_PATH) # Image generation OUTPUT_DATA_IMAGE_PATH = 'augmented_set/' # Seeding SEED = 42 os.environ['PYTHONHASHSEED'] = str(SEED) random.seed = SEED tf.random.set_seed(SEED) # Checkpoints checkpoint_path = 'checkpoints/cp.ckpt' # TWEAKABLE # Image generation GENERATE_NEW_IMG = False USE_GENERATED_IMG = True IMG_TO_GEN_PER_IMG = 200 # Load existing model USE_SAVED_MODEL = True TRAIN_MODEL = True # Predictions RUN_PREDICTIONS_ON_TEST_IMAGES = False if GENERATE_NEW_IMG: # load the input image, convert it to a NumPy array, and then # reshape it to have an extra dimension for img in tqdm(IMAGES_FILENAMES): image = load_img(IMAGE_DATA_PATH + img) image = img_to_array(image) image = np.expand_dims(image, axis=0) truth = load_img(MASK_DATA_PATH + img) truth = img_to_array(truth) truth = np.expand_dims(truth, axis=0) # construct the image generator for data augmentation then # initialize the total number of images generated thus far aug = ImageDataGenerator(rotation_range=360, zoom_range=0.3, brightness_range=[0.7, 1], width_shift_range=0.1, height_shift_range=0.1, vertical_flip=True, shear_range=0.15, horizontal_flip=True, fill_mode="reflect") total = 0 # construct the actual Python generator imageGen = aug.flow(image, y=truth, batch_size=1, save_to_dir=OUTPUT_DATA_IMAGE_PATH + "images", save_prefix=img.split(".")[0], save_format="png", seed=SEED) truthGen = aug.flow(truth, y=truth, batch_size=1, save_to_dir=OUTPUT_DATA_IMAGE_PATH + "groundtruth", save_prefix=img.split(".")[0], save_format="png", seed=SEED) # loop over examples from our image data augmentation generator for image in imageGen: # increment our counter total += 1 # if we have reached the specified number of examples, break # from the loop if total == IMG_TO_GEN_PER_IMG: break total = 0 for image in truthGen: # increment our counter total += 1 # if we have reached the specified number of examples, break # from the loop if total == IMG_TO_GEN_PER_IMG: break if (USE_GENERATED_IMG): print("[INFO] Updating images_filename") IMAGE_DATA_PATH = OUTPUT_DATA_IMAGE_PATH + 'images/' MASK_DATA_PATH = OUTPUT_DATA_IMAGE_PATH + 'groundtruth/' print("[INFO] new MASK_DATA_PATH : " + MASK_DATA_PATH) print("[INFO] new IMAGE_DATA_PATH : " + IMAGE_DATA_PATH) IMAGES_FILENAMES = os.listdir(IMAGE_DATA_PATH) print("[INFO] There are " + str(len(IMAGES_FILENAMES)) + " found") np.random.seed = SEED print("[INFO] Loading images into RAM", flush=True) X = np.zeros((len(IMAGES_FILENAMES), IMG_HEIGHT, IMG_WIDTH, IMG_CHANNELS), dtype=np.uint8) Y = np.zeros((len(IMAGES_FILENAMES), IMG_HEIGHT, IMG_WIDTH, 1), dtype=np.bool) for n, filename in tqdm(enumerate(IMAGES_FILENAMES), total=len(IMAGES_FILENAMES)): img = imread(IMAGE_DATA_PATH + filename)[:, :, :IMG_CHANNELS] img = resize(img, (IMG_HEIGHT, IMG_WIDTH), mode='constant', preserve_range=True) X[n] = img mask = imread(MASK_DATA_PATH + filename) mask = np.expand_dims(resize(mask, (IMG_HEIGHT, IMG_WIDTH), mode='constant', preserve_range=True), axis=-1) if USE_GENERATED_IMG: Y[n] = mask[:, :, 0] else: Y[n] = mask # Build U-Net++ model inputs = tf.keras.layers.Input((IMG_HEIGHT, IMG_WIDTH, +IMG_CHANNELS)) s = tf.keras.layers.Lambda(lambda x: x / 255)(inputs) c1 = tf.keras.layers.Conv2D(16, (3, 3), activation=tf.keras.activations.relu, kernel_initializer='he_normal', padding='same')(s) c1 = tf.keras.layers.Dropout(0.1)(c1) c1 = tf.keras.layers.Conv2D(16, (3, 3), activation=tf.keras.activations.relu, kernel_initializer='he_normal', padding='same')(c1) p1 = tf.keras.layers.MaxPooling2D((2, 2))(c1) c2 = tf.keras.layers.Conv2D(32, (3, 3), activation=tf.keras.activations.relu, kernel_initializer='he_normal', padding='same')(p1) c2 = tf.keras.layers.Dropout(0.1)(c2) c2 = tf.keras.layers.Conv2D(32, (3, 3), activation=tf.keras.activations.relu, kernel_initializer='he_normal', padding='same')(c2) p2 = tf.keras.layers.MaxPooling2D((2, 2))(c2) c3 = tf.keras.layers.Conv2D(64, (3, 3), activation=tf.keras.activations.relu, kernel_initializer='he_normal', padding='same')(p2) c3 = tf.keras.layers.Dropout(0.2)(c3) c3 = tf.keras.layers.Conv2D(64, (3, 3), activation=tf.keras.activations.relu, kernel_initializer='he_normal', padding='same')(c3) p3 = tf.keras.layers.MaxPooling2D((2, 2))(c3) c4 = tf.keras.layers.Conv2D(128, (3, 3), activation=tf.keras.activations.relu, kernel_initializer='he_normal', padding='same')(p3) c4 = tf.keras.layers.Dropout(0.2)(c4) c4 = tf.keras.layers.Conv2D(128, (3, 3), activation=tf.keras.activations.relu, kernel_initializer='he_normal', padding='same')(c4) p4 = tf.keras.layers.MaxPooling2D(pool_size=(2, 2))(c4) c5 = tf.keras.layers.Conv2D(256, (3, 3), activation=tf.keras.activations.relu, kernel_initializer='he_normal', padding='same')(p4) c5 = tf.keras.layers.Dropout(0.3)(c5) c5 = tf.keras.layers.Conv2D(256, (3, 3), activation=tf.keras.activations.relu, kernel_initializer='he_normal', padding='same')(c5) u6 = tf.keras.layers.Conv2DTranspose(128, (2, 2), strides=(2, 2), padding='same')(c5) u6 = tf.keras.layers.concatenate([u6, c4]) c6 = tf.keras.layers.Conv2D(128, (3, 3), activation=tf.keras.activations.relu, kernel_initializer='he_normal', padding='same')(u6) c6 = tf.keras.layers.Dropout(0.2)(c6) c6 = tf.keras.layers.Conv2D(128, (3, 3), activation=tf.keras.activations.relu, kernel_initializer='he_normal', padding='same')(c6) u7 = tf.keras.layers.Conv2DTranspose(64, (2, 2), strides=(2, 2), padding='same')(c6) # One DenseNet Node d_u1 = tf.keras.layers.Conv2DTranspose(64, (2, 2), strides=(2, 2), padding='same')(c4) d1 = tf.keras.layers.concatenate([d_u1, c3]) d1 = tf.keras.layers.Dense(64, activation='relu')(d1) u7 = tf.keras.layers.concatenate([u7, d1]) c7 = tf.keras.layers.Conv2D(64, (3, 3), activation=tf.keras.activations.relu, kernel_initializer='he_normal', padding='same')(u7) c7 = tf.keras.layers.Dropout(0.2)(c7) c7 = tf.keras.layers.Conv2D(64, (3, 3), activation=tf.keras.activations.relu, kernel_initializer='he_normal', padding='same')(c7) d_u2 = tf.keras.layers.Conv2DTranspose(32, (2, 2), strides=(2, 2), padding='same')(c3) d2 = tf.keras.layers.concatenate([d_u2, c2]) d2 = tf.keras.layers.Dense(128, activation=tf.keras.activations.relu)(d2) d_u3 = tf.keras.layers.Conv2DTranspose(32, (2, 2), strides=(2, 2), padding='same')(d1) d3 = tf.keras.layers.concatenate([d_u3, d2, c2]) d3 = tf.keras.layers.Dense(128, activation=tf.keras.activations.relu)(d3) u8 = tf.keras.layers.Conv2DTranspose(32, (2, 2), strides=(2, 2), padding='same')(c7) u8 = tf.keras.layers.concatenate([u8, d3]) c8 = tf.keras.layers.Conv2D(32, (3, 3), activation=tf.keras.activations.relu, kernel_initializer='he_normal', padding='same')(u8) c8 = tf.keras.layers.Dropout(0.1)(c8) c8 = tf.keras.layers.Conv2D(32, (3, 3), activation=tf.keras.activations.relu, kernel_initializer='he_normal', padding='same')(c8) d_uc2 = tf.keras.layers.Conv2DTranspose(16, (2, 2), strides=(2, 2), padding='same')(c2) d4 = tf.keras.layers.concatenate([d_uc2, c1]) d4 = tf.keras.layers.Dense(256, activation=tf.keras.activations.relu)(d4) d_ud2 = tf.keras.layers.Conv2DTranspose(16, (2, 2), strides=(2, 2), padding='same')(d2) d5 = tf.keras.layers.concatenate([d_ud2, d4, c1]) d5 = tf.keras.layers.Dense(256, activation=tf.keras.activations.relu)(d5) d_ud3 = tf.keras.layers.Conv2DTranspose(16, (2, 2), strides=(2, 2), padding='same')(d3) d6 = tf.keras.layers.concatenate([d_ud3, d5, c1]) d6 = tf.keras.layers.Dense(256, activation=tf.keras.activations.relu)(d6) u9 = tf.keras.layers.Conv2DTranspose(16, (2, 2), strides=(2, 2), padding='same')(c8) u9 = tf.keras.layers.concatenate([u9, d6], axis=3) c9 = tf.keras.layers.Conv2D(16, (3, 3), activation=tf.keras.activations.relu, kernel_initializer='he_normal', padding='same')(u9) c9 = tf.keras.layers.Dropout(0.1)(c9) c9 = tf.keras.layers.Conv2D(16, (3, 3), activation=tf.keras.activations.relu, kernel_initializer='he_normal', padding='same')(c9) outputs = tf.keras.layers.Conv2D(1, (1, 1), activation='sigmoid')(c9) model = tf.keras.Model(inputs=[inputs], outputs=[outputs]) model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy']) model.summary() if USE_SAVED_MODEL: if not os.path.isfile(MODEL_SAVE_LOCATION): print( "[ERROR] Could not locate file for model weights. Proceding without loading weights." ) else: model.load_weights(MODEL_SAVE_LOCATION) print("[INFO] Loading saved model weights") log_dir = "logs/fit/" + datetime.datetime.now().strftime("%Y%m%d-%H%M%S") tensorboard_callback = tf.keras.callbacks.TensorBoard(log_dir=log_dir, histogram_freq=1) cp_callback = tf.keras.callbacks.ModelCheckpoint(checkpoint_path, save_weights_only=True, verbose=1) callbacks = [ #tf.keras.callbacks.EarlyStopping(patience=2, monitor='val_loss'), tensorboard_callback, cp_callback ] gc.collect() if TRAIN_MODEL: print("[INFO] Training model") #total_epochs = epochs #while epochs > 0: model.fit(X, Y, validation_split=0.1, batch_size=4, epochs=epochs, callbacks=callbacks, shuffle=True) model.save_weights(MODEL_SAVE_LOCATION, overwrite=True) # total_epochs += epochs # epochs = int(input(" -> How many more epochs? ")) #print(f"[INFO] Trained for {total_epochs} epochs.") gc.collect() def img_float_to_uint8(img): rimg = img - np.min(img) rimg = (rimg / np.max(rimg) * PIXEL_DEPTH).round().astype(np.uint8) return rimg predictions = [] if RUN_PREDICTIONS_ON_TEST_IMAGES: print("[INFO] Running prediction on submission set") if not os.path.isdir(PREDICTION_SUBMISSION_DIR): os.mkdir(PREDICTION_SUBMISSION_DIR) for i in range(1, 51): pimg = imread(SUBMISSION_DATA_DIR + f"test_{i}.png")[:, :, :IMG_CHANNELS] predictions.append( predict_img_with_smooth_windowing( pimg, window_size=IMG_WIDTH, subdivisions= 2, # Minimal amount of overlap for windowing. Must be an even number. nb_classes=1, pred_func=(lambda img_batch_subdiv: model.predict( img_batch_subdiv)))) else: print("[INFO] Skipping predicting test images") best_threshold = 0.51 if RUN_PREDICTIONS_ON_TEST_IMAGES: print("[INFO] Writing prediction to drive") pred = np.array(predictions.copy()) for i in range(1, 51): pimg = pred[i - 1] w = pimg.shape[0] h = pimg.shape[1] cimg = np.zeros((w, h, 3), dtype=np.uint8) pimg = (pimg > best_threshold).astype(np.uint8) pimg8 = np.squeeze(img_float_to_uint8(pimg)) cimg[:, :, 0] = pimg8 cimg[:, :, 1] = pimg8 cimg[:, :, 2] = pimg8 Image.fromarray(cimg).save(PREDICTION_SUBMISSION_DIR + f"gt_{i}.png") else: print("[INFO] Skipping write of predictions to disk") # Creating ouput for submission foreground_threshold = 0.25 # percentage of pixels > 1 required to assign a foreground label to a patch # assign a label to a patch def patch_to_label(patch): df = np.mean(patch) if df > foreground_threshold: return 1 else: return 0 def mask_to_submission_strings(image_filename): """Reads a single image and outputs the strings that should go into the submission file""" img_number = int(re.search(r"\d+", image_filename).group(0)) im = mpimg.imread(image_filename) patch_size = 16 for j in range(0, im.shape[1], patch_size): for i in range(0, im.shape[0], patch_size): patch = im[i:i + patch_size, j:j + patch_size] label = patch_to_label(patch) yield ("{:03d}_{}_{},{}".format(img_number, j, i, label)) def masks_to_submission(submission_filename, *image_filenames): """Converts images into a submission file""" with open(submission_filename, 'w') as f: f.write('id,prediction\n') for fn in image_filenames[0:]: f.writelines('{}\n'.format(s) for s in mask_to_submission_strings(fn)) if RUN_PREDICTIONS_ON_TEST_IMAGES: print("[INFO] Parsing prediction for AICrowd") time = strftime("%Y%m%dT%H%M%S") submission_filename = f'submission-{time}.csv' image_filenames = [] for i in range(1, 51): image_filename = f'{PREDICTION_SUBMISSION_DIR}gt_{i}.png' image_filenames.append(image_filename) masks_to_submission(submission_filename, *image_filenames) else: print("[INFO] Skipping prediction for AICrowd")
print("Calculate metrics (per image) . . .") iou_per_image = jaccard_index_numpy(Y_test, (preds_test > 0.5).astype(np.uint8)) ov_iou_per_image = voc_calculation(Y_test, (preds_test > 0.5).astype(np.uint8), iou_per_image) det_per_image = DET_calculation(Y_test, (preds_test > 0.5).astype(np.uint8), det_eval_ge_path, det_eval_path, det_bin, n_dig, args.job_id) print("~~~~ Blending (per image) ~~~~") Y_test_blending = np.zeros(X_test.shape, dtype=np.float32) for i in tqdm(range(X_test.shape[0])): predictions_blending = predict_img_with_smooth_windowing( X_test[i], window_size=crop_shape[0], subdivisions=2, nb_classes=1, pred_func=(lambda img_batch_subdiv: model.predict(img_batch_subdiv)), softmax=softmax_out) Y_test_blending[i] = predictions_blending print("Saving smooth predicted images . . .") save_img(Y=Y_test_blending, mask_dir=smo_no_bin_dir_per_image, prefix="test_out_smo_no_bin") save_img(Y=(Y_test_blending > 0.5).astype(np.uint8), mask_dir=smo_bin_dir_per_image, prefix="test_out_smo") print("Calculate metrics (smooth + per crop) . . .") smo_score_per_image = jaccard_index_numpy(
def predict(data_dir, output_dir, X, mode, pred): print("reading image...") proj, geotrans, input_img = read_img(data_dir) # input_img[:, :, [2, 0]] = input_img[:, :, [0, 2]] input_img = input_img[:, :, :3] print(input_img.shape) input_img = np.asarray(input_img, dtype='uint8') step = 32 height, width, _ = input_img.shape print(height // step) print(width // step) for i in range(height // step): if i == height // step and height // step != 0: continue for j in range(width // step + 1): if j == width // step and width // step != 0: continue last_height_value = ( i + 1) * step if i + 1 != height // step else height last_width_value = (j + 1) * step if j + 1 != width // step else width cv2.imwrite( '%s/tmp_%d_%d.jpg' % (tmp_dir, i, j), input_img[i * step:last_height_value, j * step:last_width_value, :]) print('%s/tmp_%d_%d.jpg write done' % (tmp_dir, i, j)) del input_img gc.collect() print("done1") label_pred = np.zeros((height, width), dtype=np.uint8) for i in range(height // step): if i == height // step and height // step != 0: continue for j in range(width // step + 1): if j == width // step and width // step != 0: continue last_height_value = ( i + 1) * step if i + 1 != height // step else height last_width_value = (j + 1) * step if j + 1 != width // step else width print(last_height_value, last_width_value) print('%s/tmp_%d_%d.jpg' % (tmp_dir, i, j)) img_tiny = cv2.imread('%s/tmp_%d_%d.jpg' % (tmp_dir, i, j)) print(img_tiny) label_pred_tiny = predict_img_with_smooth_windowing( img_tiny, window_size=32, subdivisions=2, batch_size=64, pred_func=( lambda img: sess.run(pred, feed_dict={ X: img, mode: False }))) label_pred_tiny = label_pred_tiny[:, :, 0] label_pred_tiny[np.where(label_pred_tiny >= 0.5)] = 1 label_pred_tiny[np.where(label_pred_tiny < 0.5)] = 0 label_pred_tiny = label_pred_tiny.astype(np.uint8) label_pred[i * step:last_height_value, j * step:last_width_value] = label_pred_tiny gc.collect() print("done2") # cv2.imwrite(output_dir, label_pred) write_img(output_dir, proj, geotrans, label_pred) print("done3")
if __name__ == '__main__': os.environ['CUDA_VISIBLE_DEVICES'] = '1' saver = tf.train.import_meta_graph("./models/model.ckpt.meta") sess = tf.InteractiveSession() saver.restore(sess, "models/model.ckpt") X = tf.get_collection("inputs") pred = tf.get_collection("outputs")[0] # input_img = cv2.imread('./test_data/test_n0013_im.png') # input_img = cv2.cvtColor(input_img, cv2.COLOR_BGR2RGB) input_img = tif.imread('../testing_data/changshou.tif') label_pred = predictions_smooth = predict_img_with_smooth_windowing( input_img, window_size=512, subdivisions=2, # Minimal amount of overlap for windowing. Must be an even number. nb_classes=2, pred_func=( lambda img: sess.run(pred, feed_dict={X: np.expand_dims(img, 0)}) ) ) label_pred = label_pred[:,:,1] label_pred[np.where(label_pred >= 0.5)] = 255 label_pred[np.where(label_pred < 0.5)] = 0 cv2.imwrite('./label.png', label_pred)
def predict(orthophoto_filename, model, smoothPatches=True, debug=False): print('Predicting ...') # Since model was trained by images with switched R and B channels here we need switch. # OpenCV switch it by default because it use BGR channels formation ximg = cv2.imread(orthophoto_filename)[:, :, :3] ximg = cv2.resize(ximg, (0, 0), fx=0.5, fy=0.5, interpolation=cv2.INTER_CUBIC) print('Source image shape: {0}, type: {1}'.format(ximg.shape, ximg.dtype)) if smoothPatches == True: # Use the algorithm. The `pred_func` is passed and will process all the image 8-fold by tiling small patches with overlap, called once with all those image as a batch outer dimension. # Note that model.predict(...) accepts a 4D tensor of shape (batch, x, y, nb_channels), such as a Keras model. prob_field = predict_img_with_smooth_windowing( ximg, window_size= 96, # Should be more than 96(training shape). But huge size will down your GPU and PC. Test shows 96(as wnd size) is the best subdivisions= 2, # Minimal amount of overlap for windowing. Must be an even number. nb_classes=1, pred_func=( lambda img_batch_subdiv: model.predict(img_batch_subdiv))) else: # Tile orthophoto images cropSize = 1024 # should be pow of 2, and greater than source image size used for training, sure - eq/less than img size overlapCropSize = cropSize // 4 * 3 w0, w1, h0, h1 = getTiledBoxx(ximg.shape, tile_size=(cropSize, cropSize), offset=(overlapCropSize, overlapCropSize)) print('Number of tiles: {0}'.format(len(w0))) ximg_tiled = [] for i in range(len(w0)): ximg_tiled.append(ximg[h0[i]:h1[i], w0[i]:w1[i]]) # Convert image tiles to required data format ximg_tiled = np.asarray(ximg_tiled, dtype=np.float32) print('Array prepared for prediction shape: {0}, type: {1}'.format( ximg_tiled.shape, ximg_tiled.dtype)) # To avoid memory overload, predict samples partialy tilesDoneNb = 0 tilesDoneSetp = 2 preds_train = np.empty(shape=(0, cropSize, cropSize, 1)) while tilesDoneNb < ximg_tiled.shape[0]: temp = model.predict( ximg_tiled[tilesDoneNb:min(tilesDoneNb + tilesDoneSetp, ximg_tiled.shape[0] )], verbose=0) preds_train = np.append(preds_train, temp, axis=0) tilesDoneNb = tilesDoneNb + tilesDoneSetp print('Predicted result shape: {0}, type: {1}'.format( preds_train.shape, preds_train.dtype)) # Accum tiled results to whole image ximg_accum_gray = np.zeros(shape=(ximg.shape[0], ximg.shape[1], 1), dtype=np.uint8) prob_field = np.zeros(shape=(ximg.shape[0], ximg.shape[1], 1), dtype=np.float32) for i in range(len(w0)): #prob_field[h0[i]:h1[i], w0[i]:w1[i]] = preds_train[i] prob_field[h0[i]:h1[i], w0[i]:w1[i]] = np.fmax( prob_field[h0[i]:h1[i], w0[i]:w1[i]], preds_train[i]) # result shape [h,w] return (prob_field[:, :, 0] * 255).astype(np.uint8)