<filename>PSPNet/utils.py
"""
This module contains utility functions used in the conversion of the downloaded
data to TFrecords as well as functions used by the model/training script.

Semantic segmenation evaluations methods were taken from
https://github.com/martinkersner/py_img_seg_eval
"""

import os
import fnmatch
import logging

import cv2
import numpy as np
from PIL import Image
from tqdm import tqdm
import tensorflow as tf


def set_logging_verbosity(verbose_level=3):
    """Set the level of logging verbosity."""

    if not isinstance(verbose_level, int):
        raise TypeError("verbose_level must be an int")

    if not (0 <= verbose_level <= 4):
        raise ValueError("verbose_level must be between 0 and 4")

    verbosity = [logging.CRITICAL,
                 logging.ERROR,
                 logging.WARNING,
                 logging.INFO,
                 logging.DEBUG]

    logging.basicConfig(
        format='%(asctime)s:\t %(message)s',
        datefmt='%m/%d/%Y %I:%M:%S %p',
        level=verbosity[verbose_level])

def compute_batch_pixel_accuracy(predicted_masks, ground_truth_masks):
    """
    Compute the the average pixel accuracy across a batch of ground truth masks
    and their respective predicted masks given by the network.
    """

    return np.mean(
        [pixel_accuracy(np.squeeze(predicted_masks[i]), np.squeeze(ground_truth_masks[i]))
         for i in range(len(predicted_masks))])

def load_data_paths(data_root_directory, extra_ignore_regexes=None):
    """
    Provide a generic function to load paths of image data files.

    This function loads only the `string` paths, it does not load images into memory.
    """

    root_path = os.path.realpath(data_root_directory)

    # Load the image file extensions that the scanner uses
    extensions = ['.png', '.jpg']

    full_file_list = []
    for ext in extensions:
        # Using os.walk and fnmatch here instead of glob to remain compatible
        # with Python 2
        file_list = [os.path.join(dir_path, f)
                     for dir_path, dirnames, files in os.walk(root_path)
                     for f in fnmatch.filter(files, '*' + ext)]

        full_file_list.extend(file_list)

    for scan_path in full_file_list:
        yield scan_path

def _bytes_feature(value):
    """Convert a bytearray into a Feature."""
    return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))

def _int64_feature(value):
    """Convert a scalar int into a Feature."""
    return tf.train.Feature(int64_list=tf.train.Int64List(value=[value]))

def build_semseg_record(images_to_masks, tfrecords_filename, resize_dims):
    """Convert an iterable of paths to semseg images into a TFRecords object."""
    writer = tf.python_io.TFRecordWriter(tfrecords_filename)

    for image_path, mask_path in tqdm(images_to_masks.items()):

        image = cv2.imread(image_path)
        mask = cv2.imread(mask_path, 0)

        mask = cv2.resize(mask, resize_dims[::-1], interpolation=cv2.INTER_AREA)
        image = cv2.resize(image, resize_dims[::-1], interpolation=cv2.INTER_AREA)

        # Save original dimensions
        h, w, _ = image.shape

        # Add axis for QueueRunners
        mask = np.expand_dims(mask, axis=-1)

        # convert the image and mask to their raw bytes repr
        mask_raw = mask.tostring()
        image_raw = image.tostring()

        # Encode one example at a time
        example = tf.train.Example(features=tf.train.Features(feature={
            'original_height': _int64_feature(h),
            'original_width': _int64_feature(w),
            'resized_height': _int64_feature(resize_dims[0]),
            'resized_width': _int64_feature(resize_dims[1]),
            'image_raw': _bytes_feature(image_raw),
            'mask_raw': _bytes_feature(mask_raw)}))

        writer.write(example.SerializeToString())

    writer.close()

def symbolic_read_and_decode_semseg_tfrecord(
    filename_queue, resize_dims, batch_size, num_threads, min_after_dequeue):
    """
    Given a TFRecord file generated by `kml.utils.serialize.semseg_files_to_tfrecords`,
    construct symbolic (image, mask) batches from it, adding all
    relevant ops to the graph.
    """

    reader = tf.TFRecordReader()

    _, serialized_example = reader.read(filename_queue)

    features = tf.parse_single_example(
      serialized_example,
      features={
        'original_height': tf.FixedLenFeature([], tf.int64),
        'original_width': tf.FixedLenFeature([], tf.int64),
        'resized_height': tf.FixedLenFeature([], tf.int64),
        'resized_width': tf.FixedLenFeature([], tf.int64),
        'image_raw': tf.FixedLenFeature([], tf.string),
        'mask_raw': tf.FixedLenFeature([], tf.string)})

    # Decode the image/mask back from bytes to uint8
    image = tf.decode_raw(features['image_raw'], tf.uint8)
    mask = tf.decode_raw(features['mask_raw'], tf.uint8)

    # Reshape to the image's original shape
    image = tf.reshape(image, (*resize_dims, 3))
    mask = tf.reshape(mask, (*resize_dims, 1))

    # Use capacity formula recommended by tensorflow
    capacity = min_after_dequeue + (num_threads + 1) * batch_size

    # Add queue/shuffling related ops to the graph
    image_batch, mask_batch= tf.train.shuffle_batch(
        [image, mask], batch_size=batch_size, capacity=capacity,
        num_threads=num_threads, min_after_dequeue=min_after_dequeue)

    return image_batch, mask_batch

def build_tfrecords_batch(*paths_to_tfrecords, image_shape, batch_size, max_iterations, min_after_dequeue=100):
    """Build tensors for a batch of data given the path to tfrecord file"""
    filename_queue = tf.train.string_input_producer(
            [*paths_to_tfrecords], num_epochs=max_iterations)

    image_batch, label_batch = symbolic_read_and_decode_semseg_tfrecord(
            filename_queue, image_shape, batch_size=batch_size,
            num_threads=4, min_after_dequeue=min_after_dequeue)

    return image_batch, label_batch

def add_color(img, num_classes=32):
    """Given a 1-channel color map; convert it to a colored mask."""
    h, w = img.shape
    img_color = np.zeros((h, w, 3))
    for i in range(1, 151):
        img_color[img == i] = to_color(i)
    img_color[img == num_classes] = (1.0, 1.0, 1.0)
    return img_color

def to_color(category):
    """Map each category color a good distance away from each other on the HSV color space."""
    import colorsys
    v = (category - 1) * (137.5 / 360)
    return colorsys.hsv_to_rgb(v, 1, 1)

<filename>PSPNet/utils.py
"""
This module contains utility functions used in the conversion of the downloaded
data to TFrecords as well as functions used by the model/training script.

Semantic segmenation evaluations methods were taken from
https://github.com/martinkersner/py_img_seg_eval
"""

import os
import fnmatch
import logging

import cv2
import numpy as np
from PIL import Image
from tqdm import tqdm
import tensorflow as tf


def set_logging_verbosity(verbose_level=3):
    """Set the level of logging verbosity."""

    if not isinstance(verbose_level, int):
        raise TypeError("verbose_level must be an int")

    if not (0 <= verbose_level <= 4):
        raise ValueError("verbose_level must be between 0 and 4")

    verbosity = [logging.CRITICAL,
                 logging.ERROR,
                 logging.WARNING,
                 logging.INFO,
                 logging.DEBUG]

    logging.basicConfig(
        format='%(asctime)s:\t %(message)s',
        datefmt='%m/%d/%Y %I:%M:%S %p',
        level=verbosity[verbose_level])

def compute_batch_pixel_accuracy(predicted_masks, ground_truth_masks):
    """
    Compute the the average pixel accuracy across a batch of ground truth masks
    and their respective predicted masks given by the network.
    """

    return np.mean(
        [pixel_accuracy(np.squeeze(predicted_masks[i]), np.squeeze(ground_truth_masks[i]))
         for i in range(len(predicted_masks))])

def load_data_paths(data_root_directory, extra_ignore_regexes=None):
    """
    Provide a generic function to load paths of image data files.

    This function loads only the `string` paths, it does not load images into memory.
    """

    root_path = os.path.realpath(data_root_directory)

    # Load the image file extensions that the scanner uses
    extensions = ['.png', '.jpg']

    full_file_list = []
    for ext in extensions:
        # Using os.walk and fnmatch here instead of glob to remain compatible
        # with Python 2
        file_list = [os.path.join(dir_path, f)
                     for dir_path, dirnames, files in os.walk(root_path)
                     for f in fnmatch.filter(files, '*' + ext)]

        full_file_list.extend(file_list)

    for scan_path in full_file_list:
        yield scan_path

def _bytes_feature(value):
    """Convert a bytearray into a Feature."""
    return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))

def _int64_feature(value):
    """Convert a scalar int into a Feature."""
    return tf.train.Feature(int64_list=tf.train.Int64List(value=[value]))

def build_semseg_record(images_to_masks, tfrecords_filename, resize_dims):
    """Convert an iterable of paths to semseg images into a TFRecords object."""
    writer = tf.python_io.TFRecordWriter(tfrecords_filename)

    for image_path, mask_path in tqdm(images_to_masks.items()):

        image = cv2.imread(image_path)
        mask = cv2.imread(mask_path, 0)

        mask = cv2.resize(mask, resize_dims[::-1], interpolation=cv2.INTER_AREA)
        image = cv2.resize(image, resize_dims[::-1], interpolation=cv2.INTER_AREA)

        # Save original dimensions
        h, w, _ = image.shape

        # Add axis for QueueRunners
        mask = np.expand_dims(mask, axis=-1)

        # convert the image and mask to their raw bytes repr
        mask_raw = mask.tostring()
        image_raw = image.tostring()

        # Encode one example at a time
        example = tf.train.Example(features=tf.train.Features(feature={
            'original_height': _int64_feature(h),
            'original_width': _int64_feature(w),
            'resized_height': _int64_feature(resize_dims[0]),
            'resized_width': _int64_feature(resize_dims[1]),
            'image_raw': _bytes_feature(image_raw),
            'mask_raw': _bytes_feature(mask_raw)}))

        writer.write(example.SerializeToString())

    writer.close()

def symbolic_read_and_decode_semseg_tfrecord(
    filename_queue, resize_dims, batch_size, num_threads, min_after_dequeue):
    """
    Given a TFRecord file generated by `kml.utils.serialize.semseg_files_to_tfrecords`,
    construct symbolic (image, mask) batches from it, adding all
    relevant ops to the graph.
    """

    reader = tf.TFRecordReader()

    _, serialized_example = reader.read(filename_queue)

    features = tf.parse_single_example(
      serialized_example,
      features={
        'original_height': tf.FixedLenFeature([], tf.int64),
        'original_width': tf.FixedLenFeature([], tf.int64),
        'resized_height': tf.FixedLenFeature([], tf.int64),
        'resized_width': tf.FixedLenFeature([], tf.int64),
        'image_raw': tf.FixedLenFeature([], tf.string),
        'mask_raw': tf.FixedLenFeature([], tf.string)})

    # Decode the image/mask back from bytes to uint8
    image = tf.decode_raw(features['image_raw'], tf.uint8)
    mask = tf.decode_raw(features['mask_raw'], tf.uint8)

    # Reshape to the image's original shape
    image = tf.reshape(image, (*resize_dims, 3))
    mask = tf.reshape(mask, (*resize_dims, 1))

    # Use capacity formula recommended by tensorflow
    capacity = min_after_dequeue + (num_threads + 1) * batch_size

    # Add queue/shuffling related ops to the graph
    image_batch, mask_batch= tf.train.shuffle_batch(
        [image, mask], batch_size=batch_size, capacity=capacity,
        num_threads=num_threads, min_after_dequeue=min_after_dequeue)

    return image_batch, mask_batch

def build_tfrecords_batch(*paths_to_tfrecords, image_shape, batch_size, max_iterations, min_after_dequeue=100):
    """Build tensors for a batch of data given the path to tfrecord file"""
    filename_queue = tf.train.string_input_producer(
            [*paths_to_tfrecords], num_epochs=max_iterations)

    image_batch, label_batch = symbolic_read_and_decode_semseg_tfrecord(
            filename_queue, image_shape, batch_size=batch_size,
            num_threads=4, min_after_dequeue=min_after_dequeue)

    return image_batch, label_batch

def add_color(img, num_classes=32):
    """Given a 1-channel color map; convert it to a colored mask."""
    h, w = img.shape
    img_color = np.zeros((h, w, 3))
    for i in range(1, 151):
        img_color[img == i] = to_color(i)
    img_color[img == num_classes] = (1.0, 1.0, 1.0)
    return img_color

def to_color(category):
    """Map each category color a good distance away from each other on the HSV color space."""
    import colorsys
    v = (category - 1) * (137.5 / 360)
    return colorsys.hsv_to_rgb(v, 1, 1)

This module contains utility functions used in the conversion of the downloaded data to TFrecords as well as functions used by the model/training script.  Semantic segmenation evaluations methods were taken from https://github.com/martinkersner/py_img_seg_eval Set the level of logging verbosity. Compute the the average pixel accuracy across a batch of ground truth masks     and their respective predicted masks given by the network. Provide a generic function to load paths of image data files.      This function loads only the `string` paths, it does not load images into memory. # Load the image file extensions that the scanner uses # Using os.walk and fnmatch here instead of glob to remain compatible # with Python 2 Convert a bytearray into a Feature. Convert a scalar int into a Feature. Convert an iterable of paths to semseg images into a TFRecords object. # Save original dimensions # Add axis for QueueRunners # convert the image and mask to their raw bytes repr # Encode one example at a time Given a TFRecord file generated by `kml.utils.serialize.semseg_files_to_tfrecords`,     construct symbolic (image, mask) batches from it, adding all     relevant ops to the graph. # Decode the image/mask back from bytes to uint8 # Reshape to the image's original shape # Use capacity formula recommended by tensorflow # Add queue/shuffling related ops to the graph Build tensors for a batch of data given the path to tfrecord file Given a 1-channel color map; convert it to a colored mask. Map each category color a good distance away from each other on the HSV color space.