Skip to content
This repository was archived by the owner on Sep 16, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 99 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
output
*.npy
*.ckpt
*.ipynb

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
.hypothesis/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# pyenv
.python-version

# celery beat schedule file
celerybeat-schedule

# SageMath parsed files
*.sage.py

# dotenv
.env

# virtualenv
.venv
venv/
ENV/

# Spyder project settings
.spyderproject

# Rope project settings
.ropeproject
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ virtualenv:
install:
- echo $TRAVIS_PYTHON_VERSION
- pip install -U -r ./requirements.txt
- pip install -U tensorflow==0.12.1
- pip install -U https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-1.0.0-cp27-none-linux_x86_64.whl
- wget https://www.dropbox.com/s/cd0drt6t9q1mwg0/deeplab_resnet.ckpt?dl=1 -O deeplab_resnet.ckpt

script:
- python inference.py ./misc/2007_000129.jpg ./deeplab_resnet.ckpt
- python train.py --batch-size 1 --data-dir ./ --data-list ./dataset/debug.txt --num-steps 1 --random-mirror --random-scale --restore-from ./deeplab_resnet.ckpt --save-num-images 1
Expand Down
98 changes: 60 additions & 38 deletions deeplab_resnet/image_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
import tensorflow as tf

IGNORE_LABEL = 255
IMG_MEAN = np.array((104.00698793,116.66876762,122.67891434), dtype=np.float32)
IMG_MEAN = np.array((104.00698793, 116.66876762,
122.67891434), dtype=np.float32)


def image_scaling(img, label):
"""
Expand All @@ -14,17 +16,20 @@ def image_scaling(img, label):
img: Training image to scale.
label: Segmentation mask to scale.
"""

scale = tf.random_uniform([1], minval=0.5, maxval=1.5, dtype=tf.float32, seed=None)
h_new = tf.to_int32(tf.mul(tf.to_float(tf.shape(img)[0]), scale))
w_new = tf.to_int32(tf.mul(tf.to_float(tf.shape(img)[1]), scale))
new_shape = tf.squeeze(tf.pack([h_new, w_new]), squeeze_dims=[1])

scale = tf.random_uniform(
[1], minval=0.5, maxval=1.5, dtype=tf.float32, seed=None)
h_new = tf.to_int32(tf.multiply(tf.to_float(tf.shape(img)[0]), scale))
w_new = tf.to_int32(tf.multiply(tf.to_float(tf.shape(img)[1]), scale))
new_shape = tf.squeeze(tf.stack([h_new, w_new]), squeeze_dims=[1])
img = tf.image.resize_images(img, new_shape)
label = tf.image.resize_nearest_neighbor(tf.expand_dims(label, 0), new_shape)
label = tf.image.resize_nearest_neighbor(
tf.expand_dims(label, 0), new_shape)
label = tf.squeeze(label, squeeze_dims=[0])

return img, label


def image_mirroring(img, label):
"""
Randomly mirrors the images.
Expand All @@ -33,13 +38,20 @@ def image_mirroring(img, label):
img: Training image to mirror.
label: Segmentation mask to mirror.
"""

distort_left_right_random = tf.random_uniform([1], 0, 1.0, dtype=tf.float32)[0]
mirror = tf.less(tf.pack([1.0, distort_left_right_random, 1.0]), 0.5)

distort_left_right_random = tf.random_uniform(
[1], 0, 1.0, dtype=tf.float32)[0]
mirror = tf.less(tf.stack([1.0, distort_left_right_random, 1.0]),
0.5)
# tf.reverse() now takes indices of axes to be reversed.
# so we should convert boolean_mask into indices
mirror = tf.boolean_mask([0, 1, 2], mirror)

img = tf.reverse(img, mirror)
label = tf.reverse(label, mirror)
return img, label


def random_crop_and_pad_image_and_labels(image, label, crop_h, crop_w, ignore_label=255):
"""
Randomly crop and pads the input images.
Expand All @@ -53,31 +65,34 @@ def random_crop_and_pad_image_and_labels(image, label, crop_h, crop_w, ignore_la
"""

label = tf.cast(label, dtype=tf.float32)
label = label - ignore_label # Needs to be subtracted and later added due to 0 padding.
combined = tf.concat(2, [image, label])
# Needs to be subtracted and later added due to 0 padding.
label = label - ignore_label
combined = tf.concat([image, label], axis=2)
image_shape = tf.shape(image)
combined_pad = tf.image.pad_to_bounding_box(combined, 0, 0, tf.maximum(crop_h, image_shape[0]), tf.maximum(crop_w, image_shape[1]))

combined_pad = tf.image.pad_to_bounding_box(combined, 0, 0, tf.maximum(
crop_h, image_shape[0]), tf.maximum(crop_w, image_shape[1]))

last_image_dim = tf.shape(image)[-1]
last_label_dim = tf.shape(label)[-1]
combined_crop = tf.random_crop(combined_pad, [crop_h,crop_w,4])
combined_crop = tf.random_crop(combined_pad, [crop_h, crop_w, 4])
img_crop = combined_crop[:, :, :last_image_dim]
label_crop = combined_crop[:, :, last_image_dim:]
label_crop = label_crop + ignore_label
label_crop = tf.cast(label_crop, dtype=tf.uint8)
# Set static shape so that tensorflow knows shape at compile time.

# Set static shape so that tensorflow knows shape at compile time.
img_crop.set_shape((crop_h, crop_w, 3))
label_crop.set_shape((crop_h,crop_w, 1))
return img_crop, label_crop
label_crop.set_shape((crop_h, crop_w, 1))
return img_crop, label_crop


def read_labeled_image_list(data_dir, data_list):
"""Reads txt file containing paths to images and ground truth masks.

Args:
data_dir: path to the directory with images and masks.
data_list: path to the file with lines of the form '/path/to/image /path/to/mask'.

Returns:
Two lists with all file names for images and masks, respectively.
"""
Expand All @@ -87,15 +102,17 @@ def read_labeled_image_list(data_dir, data_list):
for line in f:
try:
image, mask = line.strip("\n").split(' ')
except ValueError: # Adhoc for test.
except ValueError: # Adhoc for test.
image = mask = line.strip("\n")
images.append(data_dir + image)
masks.append(data_dir + mask)
return images, masks

def read_images_from_disk(input_queue, input_size, random_scale, random_mirror): # optional pre-processing arguments

# optional pre-processing arguments
def read_images_from_disk(input_queue, input_size, random_scale, random_mirror):
"""Read one image and its corresponding mask with optional pre-processing.

Args:
input_queue: tf queue with paths to the image and its mask.
input_size: a tuple with (height, width) values.
Expand All @@ -104,17 +121,17 @@ def read_images_from_disk(input_queue, input_size, random_scale, random_mirror):
to random crop.
random_mirror: whether to randomly mirror the images prior
to random crop.

Returns:
Two tensors: the decoded image and its mask.
"""

img_contents = tf.read_file(input_queue[0])
label_contents = tf.read_file(input_queue[1])

img = tf.image.decode_jpeg(img_contents, channels=3)
img_r, img_g, img_b = tf.split(split_dim=2, num_split=3, value=img)
img = tf.cast(tf.concat(2, [img_b, img_g, img_r]), dtype=tf.float32)
img_r, img_g, img_b = tf.split(value=img, num_or_size_splits=3, axis=2)
img = tf.cast(tf.concat([img_b, img_g, img_r], axis=2), dtype=tf.float32)
# Extract mean.
img -= IMG_MEAN

Expand All @@ -132,10 +149,12 @@ def read_images_from_disk(input_queue, input_size, random_scale, random_mirror):
img, label = image_mirroring(img, label)

# Randomly crops the images and labels.
img, label = random_crop_and_pad_image_and_labels(img, label, h, w, IGNORE_LABEL)
img, label = random_crop_and_pad_image_and_labels(
img, label, h, w, IGNORE_LABEL)

return img, label


class ImageReader(object):
'''Generic ImageReader which reads images and corresponding segmentation
masks from the disk, and enqueues them into a TensorFlow queue.
Expand All @@ -144,7 +163,7 @@ class ImageReader(object):
def __init__(self, data_dir, data_list, input_size, random_scale,
random_mirror, coord):
'''Initialise an ImageReader.

Args:
data_dir: path to the directory with images and masks.
data_list: path to the file with lines of the form '/path/to/image /path/to/mask'.
Expand All @@ -157,22 +176,25 @@ def __init__(self, data_dir, data_list, input_size, random_scale,
self.data_list = data_list
self.input_size = input_size
self.coord = coord

self.image_list, self.label_list = read_labeled_image_list(self.data_dir, self.data_list)

self.image_list, self.label_list = read_labeled_image_list(
self.data_dir, self.data_list)
self.images = tf.convert_to_tensor(self.image_list, dtype=tf.string)
self.labels = tf.convert_to_tensor(self.label_list, dtype=tf.string)
self.queue = tf.train.slice_input_producer([self.images, self.labels],
shuffle=input_size is not None) # not shuffling if it is val
self.image, self.label = read_images_from_disk(self.queue, self.input_size, random_scale, random_mirror)
shuffle=input_size is not None) # not shuffling if it is val
self.image, self.label = read_images_from_disk(
self.queue, self.input_size, random_scale, random_mirror)

def dequeue(self, num_elements):
'''Pack images and labels into a batch.

Args:
num_elements: the batch size.

Returns:
Two tensors of size (batch_size, h, w, {3, 1}) for images and masks.'''
Two tensors of size (batch_size, h, w, {3, 1}) for images and masks.
'''
image_batch, label_batch = tf.train.batch([self.image, self.label],
num_elements)
return image_batch, label_batch
Loading