From fe505614d44f3f26c8752f38f4786d348878954c Mon Sep 17 00:00:00 2001 From: tgupta6 <tgupta6@illinois.edu> Date: Sat, 4 Jun 2016 19:23:17 -0500 Subject: [PATCH] Visual Genome Data Manager --- __init__.py | 0 constants.py | 39 +++ data/__init__.py | 0 data/compute_mean_region_image.py | 31 +++ data/cropped_regions.py | 264 +++++++++++++++++++++ data/regions.py | 264 +++++++++++++++++++++ image_io.py | 78 ++++++ tftools/__init__.py | 0 tftools/data.py | 96 ++++++++ visual_genome_parser.py | 378 ++++++++++++++++++++++++++++++ 10 files changed, 1150 insertions(+) create mode 100644 __init__.py create mode 100644 constants.py create mode 100644 data/__init__.py create mode 100644 data/compute_mean_region_image.py create mode 100644 data/cropped_regions.py create mode 100644 data/regions.py create mode 100644 image_io.py create mode 100644 tftools/__init__.py create mode 100644 tftools/data.py create mode 100644 visual_genome_parser.py diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/constants.py b/constants.py new file mode 100644 index 0000000..b292f0f --- /dev/null +++ b/constants.py @@ -0,0 +1,39 @@ +import os + +#height and width to which images are resized before feeding into networks +image_size = (224, 224) + +# Token to be used if object or attribute variable is unknown +unknown_token = 'UNK' + +# Data paths +data_absolute_path = '/home/tanmay/Data/VisualGenome' +image_dir = os.path.join(data_absolute_path, 'images') +object_labels_json = os.path.join( + data_absolute_path, + 'restructured/object_labels.json') +attribute_labels_json = os.path.join( + data_absolute_path, + 'restructured/attribute_labels.json') +regions_json = os.path.join( + data_absolute_path, + 'restructured/region_with_labels.json') +mean_image_filename = os.path.join( + data_absolute_path, + 'restructured/mean_image.jpg') +# Regions data partition +# First 70% meant to be used for training +# Next 10% is set aside for validation +# Last 20% is to be used for testing +num_total_regions = 1951768 +num_train_regions = 1366238 # First 70% +num_val_regions = 195176 # Next 10% +num_test_regions = num_total_regions \ + - num_train_regions \ + - num_val_regions + + + + + + diff --git a/data/__init__.py b/data/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/data/compute_mean_region_image.py b/data/compute_mean_region_image.py new file mode 100644 index 0000000..75806ca --- /dev/null +++ b/data/compute_mean_region_image.py @@ -0,0 +1,31 @@ +import numpy as np +from data.regions import data +import constants +import image_io +import pdb + + +_image_size = constants.image_size +_num_train_regions = constants.num_train_regions +_mean_image_filename = constants.mean_image_filename + + +if __name__=='__main__': + data_mgr = data(constants.image_dir, + constants.object_labels_json, + constants.attribute_labels_json, + constants.regions_json, + constants.image_size, + channels=3, + mean_image_filename=None) + + h, w = _image_size + mean_image = np.zeros([h, w, 3], dtype=np.float32) + num_images_for_mean = min(10000, _num_train_regions) + for i in xrange(num_images_for_mean): + mean_image += data_mgr.get_region_image(i) + mean_image = mean_image/num_images_for_mean + image_io.imwrite(np.uint8(mean_image*255), + _mean_image_filename) + + diff --git a/data/cropped_regions.py b/data/cropped_regions.py new file mode 100644 index 0000000..b99e6c0 --- /dev/null +++ b/data/cropped_regions.py @@ -0,0 +1,264 @@ +import numpy as np +import json +import os +import pdb +import time + +from multiprocessing import Pool + +import tftools.data +import image_io +import constants + +import tensorflow as tf + +_unknown_token = constants.unknown_token + +class data(): + def __init__(self, + image_dir, + object_labels_json, + attribute_labels_json, + regions_json, + image_size, + channels=3, + mean_image_filename=None): + self.image_dir = image_dir + self.h = image_size[0] + self.w = image_size[1] + self.c = channels + self.mean_image = self.get_mean_image(mean_image_filename) + self.object_labels_dict = self.read_json_file(object_labels_json) + self.attribute_labels_dict = self.read_json_file(attribute_labels_json) + self.inv_object_labels_dict = self.invert_label_dict( + self.object_labels_dict) + self.inv_attribute_labels_dict = self.invert_label_dict( + self.attribute_labels_dict) + self.num_object_labels = len(self.object_labels_dict) + self.num_attribute_labels = len(self.attribute_labels_dict) + self.regions = self.read_json_file(regions_json) + self.num_regions = len(self.regions) + self.create_sample_to_region_dict() + + def create_sample_to_region_dict(self): + self.sample_to_region_dict = \ + {k: v for k, v in zip(xrange(self.num_regions), + self.regions.keys())} + + def invert_label_dict(self, label_dict): + return {v: k for k, v in label_dict.items()} + + def read_json_file(self, filename): + print 'Reading {} ...'.format(filename) + with open(filename, 'r') as file: + return json.load(file) + + def get(self, samples): + batch_size = len(samples) + batch = dict() + batch['region_ids'] = dict() + batch['images'] = np.zeros( + [batch_size, self.h, self.w, self.c], np.float32) + batch['object_labels'] = np.zeros( + [batch_size, len(self.object_labels_dict)], np.float32) + batch['attribute_labels'] = np.zeros( + [batch_size, len(self.attribute_labels_dict)], np.float32) + + for index, sample in enumerate(samples): + batch['region_ids'][index] = self.sample_to_region_dict[sample] + batch['images'][index, :, :, :] = self.get_region_image(sample) + batch['object_labels'][index, :] = self.get_object_label(sample) + batch['attribute_labels'][index,:] = \ + self.get_attribute_label(sample) + + return batch + + def get_single(self, sample): + print sample + batch = dict() + batch['region_ids'] = dict() + batch['images'] = np.zeros( + [self.h, self.w, self.c], np.float32) + batch['object_labels'] = np.zeros( + [len(self.object_labels_dict)], np.float32) + batch['attribute_labels'] = np.zeros( + [len(self.attribute_labels_dict)], np.float32) + + batch['region_ids'] = self.sample_to_region_dict[sample] + batch['images'] = self.get_region_image(sample) + batch['object_labels'] = self.get_object_label(sample) + batch['attribute_labels'] = self.get_attribute_label(sample) + + return batch + + def get_parallel(self, samples): + batch_list = self.pool.map(self.get_single, samples) + batch_size = len(samples) + batch = dict() + batch['region_ids'] = dict() + batch['images'] = np.zeros( + [batch_size, self.h, self.w, self.c], np.float32) + batch['object_labels'] = np.zeros( + [batch_size, len(self.object_labels_dict)], np.float32) + batch['attribute_labels'] = np.zeros( + [batch_size, len(self.attribute_labels_dict)], np.float32) + + for index, single_batch in enumerate(batch_list): + batch['region_ids'][index] = single_batch['region_ids'] + batch['images'][index, :, :, :] = single_batch['images'] + batch['object_labels'][index, :] = single_batch['object_labels'] + batch['attribute_labels'][index,:] = single_batch['attribute_labels'] + + + return batch + + def get_region_image(self, sample): + region_id = self.sample_to_region_dict[sample] + region = self.regions[region_id] + filename = os.path.join(self.image_dir, + str(region['image_id']) + '.jpg') + image = image_io.imread(filename) + image = self.single_to_three_channel(image) + x, y, w, h = self.get_clipped_region_coords(region, image.shape[0:2]) + region_image = image[y:y + h, x:x + w, :] + + region_image = image_io.imresize( + region_image, + output_size=(self.h, self.w)).astype(np.float32) + + return region_image / 255 - self.mean_image + + def single_to_three_channel(self, image): + if len(image.shape)==3: + return image + elif len(image.shape)==2: + im_h, im_w =image.shape + image_tmp = np.zeros([im_h, im_w, 3], dtype=image.dtype) + for c in xrange(3): + image_tmp[:,:,c] = image + return image_tmp + + def get_clipped_region_coords(self, region, image_size): + im_h, im_w = image_size + x = min(im_w - 1, max(0, region["x"])) + y = min(im_h - 1, max(0, region["y"])) + h = min(im_h - y, max(region["h"], 1)) + w = min(im_w - x, max(region["w"], 1)) + return x, y, w, h + + def get_mean_image(self, mean_image_filename): + if mean_image_filename: + return image_io.imread(mean_image_filename).astype( + np.float32) / 255 + else: + return np.zeros([self.h, self.w, self.c], np.float32) + + def get_object_label(self, sample): + # Returns a multihot vector encoding of object labels + # If an object label is not found in the labels list, + # _unknown_token is produced in that case. + region_id = self.sample_to_region_dict[sample] + region = self.regions[region_id] + object_labels = region['object_names'] + object_label_encoding = np.zeros([1, self.num_object_labels], + dtype = np.float32) + if object_labels: + for object in object_labels: + if object not in self.object_labels_dict: + label_id = self.object_labels_dict[_unknown_token] + else: + label_id = self.object_labels_dict[object] + object_label_encoding[0,label_id] = 1.0 + else: + label_id = self.object_labels_dict[_unknown_token] + object_label_encoding[0,label_id] = 1.0 + + return object_label_encoding/np.sum(object_label_encoding) + + def get_attribute_label(self, sample): + # Attribute is turned on if it is present + region_id = self.sample_to_region_dict[sample] + region = self.regions[region_id] + attribute_labels = region['attributes'] + attribute_label_encoding = np.zeros([1, self.num_attribute_labels], + dtype = np.float32) + for attribute in attribute_labels: + if attribute in self.attribute_labels_dict: + label_id = self.attribute_labels_dict[attribute] + attribute_label_encoding[0,label_id] = 1.0 + + return attribute_label_encoding + +if __name__=='__main__': + data_mgr = data(constants.image_dir, + constants.object_labels_json, + constants.attribute_labels_json, + constants.regions_json, + constants.image_size, + channels=3, + mean_image_filename=None) + print 'Number of object labels: {}'.format(data_mgr.num_object_labels) + print 'Number of attribute labels: {}'.format(data_mgr.num_attribute_labels) + print 'Number of regions: {}'.format(data_mgr.num_regions) + + #Test sample + samples = [1, 2] + sample = samples[0] + region_id = data_mgr.sample_to_region_dict[sample] + region = data_mgr.regions[region_id] + attribute_encoding = data_mgr.get_attribute_label(sample) + object_encoding = data_mgr.get_object_label(sample) + region_image = data_mgr.get_region_image(sample) + + attributes = [] + for i in xrange(attribute_encoding.shape[1]): + if attribute_encoding[0,i] > 0 : + attributes.append(data_mgr.inv_attribute_labels_dict[i]) + + objects = [] + for i in xrange(object_encoding.shape[1]): + if object_encoding[0,i] > 0 : + objects.append(data_mgr.inv_object_labels_dict[i]) + + print "Region: {}".format(region) + print "Attributes: {}".format(", ".join(attributes)) + print "Objects: {}".format(", ".join(objects)) + +# image_io.imshow(region_image) + + batch_size = 200 + num_samples = 1000 + num_epochs = 1 + offset = 0 + + index_generator = tftools.data.random( + batch_size, + num_samples, + num_epochs, + offset) + + # start = time.time() + # count = 0 + # for samples in index_generator: + # batch = data_mgr.get(samples) + # print 'Batch Count: {}'.format(count) + # count += 1 + # stop = time.time() + # print 'Time per batch: {}'.format((stop-start)/5.0) + + batch_generator = tftools.data.async_batch_generator( + data_mgr, + index_generator, + 1000) + + count = 0 + start = time.time() + for batch in batch_generator: + print 'Batch Number: {}'.format(count) +# print batch['region_ids'] + count += 1 + stop = time.time() + print 'Time per batch: {}'.format((stop-start)/50.0) + print "Count: {}".format(count) + + pool.close() diff --git a/data/regions.py b/data/regions.py new file mode 100644 index 0000000..b99e6c0 --- /dev/null +++ b/data/regions.py @@ -0,0 +1,264 @@ +import numpy as np +import json +import os +import pdb +import time + +from multiprocessing import Pool + +import tftools.data +import image_io +import constants + +import tensorflow as tf + +_unknown_token = constants.unknown_token + +class data(): + def __init__(self, + image_dir, + object_labels_json, + attribute_labels_json, + regions_json, + image_size, + channels=3, + mean_image_filename=None): + self.image_dir = image_dir + self.h = image_size[0] + self.w = image_size[1] + self.c = channels + self.mean_image = self.get_mean_image(mean_image_filename) + self.object_labels_dict = self.read_json_file(object_labels_json) + self.attribute_labels_dict = self.read_json_file(attribute_labels_json) + self.inv_object_labels_dict = self.invert_label_dict( + self.object_labels_dict) + self.inv_attribute_labels_dict = self.invert_label_dict( + self.attribute_labels_dict) + self.num_object_labels = len(self.object_labels_dict) + self.num_attribute_labels = len(self.attribute_labels_dict) + self.regions = self.read_json_file(regions_json) + self.num_regions = len(self.regions) + self.create_sample_to_region_dict() + + def create_sample_to_region_dict(self): + self.sample_to_region_dict = \ + {k: v for k, v in zip(xrange(self.num_regions), + self.regions.keys())} + + def invert_label_dict(self, label_dict): + return {v: k for k, v in label_dict.items()} + + def read_json_file(self, filename): + print 'Reading {} ...'.format(filename) + with open(filename, 'r') as file: + return json.load(file) + + def get(self, samples): + batch_size = len(samples) + batch = dict() + batch['region_ids'] = dict() + batch['images'] = np.zeros( + [batch_size, self.h, self.w, self.c], np.float32) + batch['object_labels'] = np.zeros( + [batch_size, len(self.object_labels_dict)], np.float32) + batch['attribute_labels'] = np.zeros( + [batch_size, len(self.attribute_labels_dict)], np.float32) + + for index, sample in enumerate(samples): + batch['region_ids'][index] = self.sample_to_region_dict[sample] + batch['images'][index, :, :, :] = self.get_region_image(sample) + batch['object_labels'][index, :] = self.get_object_label(sample) + batch['attribute_labels'][index,:] = \ + self.get_attribute_label(sample) + + return batch + + def get_single(self, sample): + print sample + batch = dict() + batch['region_ids'] = dict() + batch['images'] = np.zeros( + [self.h, self.w, self.c], np.float32) + batch['object_labels'] = np.zeros( + [len(self.object_labels_dict)], np.float32) + batch['attribute_labels'] = np.zeros( + [len(self.attribute_labels_dict)], np.float32) + + batch['region_ids'] = self.sample_to_region_dict[sample] + batch['images'] = self.get_region_image(sample) + batch['object_labels'] = self.get_object_label(sample) + batch['attribute_labels'] = self.get_attribute_label(sample) + + return batch + + def get_parallel(self, samples): + batch_list = self.pool.map(self.get_single, samples) + batch_size = len(samples) + batch = dict() + batch['region_ids'] = dict() + batch['images'] = np.zeros( + [batch_size, self.h, self.w, self.c], np.float32) + batch['object_labels'] = np.zeros( + [batch_size, len(self.object_labels_dict)], np.float32) + batch['attribute_labels'] = np.zeros( + [batch_size, len(self.attribute_labels_dict)], np.float32) + + for index, single_batch in enumerate(batch_list): + batch['region_ids'][index] = single_batch['region_ids'] + batch['images'][index, :, :, :] = single_batch['images'] + batch['object_labels'][index, :] = single_batch['object_labels'] + batch['attribute_labels'][index,:] = single_batch['attribute_labels'] + + + return batch + + def get_region_image(self, sample): + region_id = self.sample_to_region_dict[sample] + region = self.regions[region_id] + filename = os.path.join(self.image_dir, + str(region['image_id']) + '.jpg') + image = image_io.imread(filename) + image = self.single_to_three_channel(image) + x, y, w, h = self.get_clipped_region_coords(region, image.shape[0:2]) + region_image = image[y:y + h, x:x + w, :] + + region_image = image_io.imresize( + region_image, + output_size=(self.h, self.w)).astype(np.float32) + + return region_image / 255 - self.mean_image + + def single_to_three_channel(self, image): + if len(image.shape)==3: + return image + elif len(image.shape)==2: + im_h, im_w =image.shape + image_tmp = np.zeros([im_h, im_w, 3], dtype=image.dtype) + for c in xrange(3): + image_tmp[:,:,c] = image + return image_tmp + + def get_clipped_region_coords(self, region, image_size): + im_h, im_w = image_size + x = min(im_w - 1, max(0, region["x"])) + y = min(im_h - 1, max(0, region["y"])) + h = min(im_h - y, max(region["h"], 1)) + w = min(im_w - x, max(region["w"], 1)) + return x, y, w, h + + def get_mean_image(self, mean_image_filename): + if mean_image_filename: + return image_io.imread(mean_image_filename).astype( + np.float32) / 255 + else: + return np.zeros([self.h, self.w, self.c], np.float32) + + def get_object_label(self, sample): + # Returns a multihot vector encoding of object labels + # If an object label is not found in the labels list, + # _unknown_token is produced in that case. + region_id = self.sample_to_region_dict[sample] + region = self.regions[region_id] + object_labels = region['object_names'] + object_label_encoding = np.zeros([1, self.num_object_labels], + dtype = np.float32) + if object_labels: + for object in object_labels: + if object not in self.object_labels_dict: + label_id = self.object_labels_dict[_unknown_token] + else: + label_id = self.object_labels_dict[object] + object_label_encoding[0,label_id] = 1.0 + else: + label_id = self.object_labels_dict[_unknown_token] + object_label_encoding[0,label_id] = 1.0 + + return object_label_encoding/np.sum(object_label_encoding) + + def get_attribute_label(self, sample): + # Attribute is turned on if it is present + region_id = self.sample_to_region_dict[sample] + region = self.regions[region_id] + attribute_labels = region['attributes'] + attribute_label_encoding = np.zeros([1, self.num_attribute_labels], + dtype = np.float32) + for attribute in attribute_labels: + if attribute in self.attribute_labels_dict: + label_id = self.attribute_labels_dict[attribute] + attribute_label_encoding[0,label_id] = 1.0 + + return attribute_label_encoding + +if __name__=='__main__': + data_mgr = data(constants.image_dir, + constants.object_labels_json, + constants.attribute_labels_json, + constants.regions_json, + constants.image_size, + channels=3, + mean_image_filename=None) + print 'Number of object labels: {}'.format(data_mgr.num_object_labels) + print 'Number of attribute labels: {}'.format(data_mgr.num_attribute_labels) + print 'Number of regions: {}'.format(data_mgr.num_regions) + + #Test sample + samples = [1, 2] + sample = samples[0] + region_id = data_mgr.sample_to_region_dict[sample] + region = data_mgr.regions[region_id] + attribute_encoding = data_mgr.get_attribute_label(sample) + object_encoding = data_mgr.get_object_label(sample) + region_image = data_mgr.get_region_image(sample) + + attributes = [] + for i in xrange(attribute_encoding.shape[1]): + if attribute_encoding[0,i] > 0 : + attributes.append(data_mgr.inv_attribute_labels_dict[i]) + + objects = [] + for i in xrange(object_encoding.shape[1]): + if object_encoding[0,i] > 0 : + objects.append(data_mgr.inv_object_labels_dict[i]) + + print "Region: {}".format(region) + print "Attributes: {}".format(", ".join(attributes)) + print "Objects: {}".format(", ".join(objects)) + +# image_io.imshow(region_image) + + batch_size = 200 + num_samples = 1000 + num_epochs = 1 + offset = 0 + + index_generator = tftools.data.random( + batch_size, + num_samples, + num_epochs, + offset) + + # start = time.time() + # count = 0 + # for samples in index_generator: + # batch = data_mgr.get(samples) + # print 'Batch Count: {}'.format(count) + # count += 1 + # stop = time.time() + # print 'Time per batch: {}'.format((stop-start)/5.0) + + batch_generator = tftools.data.async_batch_generator( + data_mgr, + index_generator, + 1000) + + count = 0 + start = time.time() + for batch in batch_generator: + print 'Batch Number: {}'.format(count) +# print batch['region_ids'] + count += 1 + stop = time.time() + print 'Time per batch: {}'.format((stop-start)/50.0) + print "Count: {}".format(count) + + pool.close() diff --git a/image_io.py b/image_io.py new file mode 100644 index 0000000..578b8d9 --- /dev/null +++ b/image_io.py @@ -0,0 +1,78 @@ +from PIL import Image +import numpy as np +import math +import pdb + + +def imread(filename): + """ + Matlab like function for reading an image file. + Returns: + im_array (numpy.ndarray): h x w x 3 ndarray for color images and + h x w for grayscale images + """ + im = Image.open(filename) + + err_str = \ + "imread only supports 'RGB' and 'L' modes, found '{}'".format(im.mode) + assert (im.mode == 'RGB' or im.mode == 'L'), err_str + + im_array = np.array(im) + + return im_array + + +def imshow(np_im): + """ + Matlab like function for displaying a numpy ndarray as an image + Args: + np_im (numpy.ndarray): h x w x 3 ndarray for color images and + h x w for grayscale images with pixels stored in uint8 format + """ + err_str = 'imshow expects ndarray of dimension h x w x c (RGB) or h x w (L)' + assert (len(np_im.shape) == 3 or len(np_im.shape) == 2), err_str + + if len(np_im.shape) == 3: + assert (np_im.shape[2] == 3), 'imshow expected 3 channels' + im = Image.fromarray(np_im, 'RGB') + else: + im = Image.fromarray(np_im, 'L') + + im.show() + + +def imwrite(np_im, filename): + """ + Matlab like function to save numpy image. + Args: + np_im (numpy.ndarray): h x w x 3 ndarray for color images and + h x w for grayscale images with pixels stored in uint8 format + """ + err_str = 'imshow expects ndarray of dimension h x w x c (RGB) or h x w (L)' + assert (len(np_im.shape) == 3 or len(np_im.shape) == 2), err_str + + im = Image.fromarray(np_im) + im.save(filename) + + +def imresize(np_im, method=Image.BILINEAR, **kwargs): + assert_str = "Only 1 keyword argument expected with key either" + \ + "'output_size' or 'scale'" + assert (len(kwargs)==1), assert_str + im_h = np_im.shape[0] + im_w = np_im.shape[1] + if 'output_size' in kwargs: + h, w = kwargs['output_size'] + elif 'scale' in kwargs: + h = scale*im_h + w = scale*im_w + else: + assert_str = "Variable argument must be one of {'output_size','scale'}" + assert (False), assert_str + h = int(math.ceil(h)) + w = int(math.ceil(w)) + im = Image.fromarray(np_im) + return np.array(im.resize((w,h))) + + + diff --git a/tftools/__init__.py b/tftools/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tftools/data.py b/tftools/data.py new file mode 100644 index 0000000..9fe60c1 --- /dev/null +++ b/tftools/data.py @@ -0,0 +1,96 @@ +"""Utility functions for making batch generation easier.""" +import numpy as np +from multiprocessing import Process, Queue +import time + +def sequential(batch_size, num_samples, num_epochs=1, offset=0): + """Generate sequence indices. + """ + for epoch in range(num_epochs): + indices = range(num_samples) + for i in range(0, num_samples - batch_size + 1, batch_size): + yield indices[i:i+batch_size] + + +def random(batch_size, num_samples, num_epochs, offset=0): + """Generate random indices. + """ + for epoch in range(num_epochs): + indices = np.random.permutation(num_samples) + offset + indices = indices.tolist() + for i in range(0, num_samples - batch_size + 1, batch_size): + yield indices[i:i+batch_size] + + +def batch_generator(data, index_generator, batch_function=None): + """Generate batches of data. + """ + for samples in index_generator: + batch = data.get(samples) + if batch_function: + output = batch_function(batch) + else: + output = batch + yield output + + +def async_batch_generator(data, index_generator, queue_maxsize, batch_function=None): + """Create an asynchronous batch generator. + """ + batcher = batch_generator(data, index_generator, batch_function) + + queue = Queue(maxsize=queue_maxsize) + fetcher = BatchFetcher(queue, batcher) + fetcher.start() + + time.sleep(10) + + queue_batcher = queue_generator(queue) + return queue_batcher + + +def queue_generator(queue, sentinel=None): + """Create a generator from a queue. + """ + while True: + value = queue.get() + if value is not sentinel: + yield value + else: + return + + +class BatchFetcher(Process): + def __init__(self, queue, batch_generator): + super(BatchFetcher, self).__init__() + self.queue = queue + self.batch_generator = batch_generator + + def run(self): + + for batch in self.batch_generator: + self.queue.put(batch) + + # Signal that fetcher is done. + self.queue.put(None) + + +class NumpyData(object): + def __init__(self, array): + self.array = array + + def get(self, indices): + if not isinstance(indices, np.ndarray): + indices = np.array(indices) + return self.array[indices] + + +if __name__=='__main__': + batch_size = 10 + num_samples = 20 + num_epochs = 3 + offset = 0 + index_generator = random(batch_size, num_samples, num_epochs, offset) + for samples in index_generator: + print samples + diff --git a/visual_genome_parser.py b/visual_genome_parser.py new file mode 100644 index 0000000..d104401 --- /dev/null +++ b/visual_genome_parser.py @@ -0,0 +1,378 @@ +import json +import os +import operator +import nltk +import numpy as np +import pdb +from multiprocessing import Pool +import image_io + + +# Filenames +_datadir = '/home/tanmay/Data/VisualGenome/' +_outdir = os.path.join(_datadir,'restructured') +_cropped_regions_dir = os.path.join(_datadir, 'cropped_regions') +_objects = 'objects.json' +_attributes = 'attributes.json' +_objects_in_image = 'objects_in_image.json' +_regions_in_image = 'regions_in_image.json' +_regions_with_attributes = 'regions_with_attributes.json' +_regions = 'regions.json' +_raw_object_labels = 'raw_object_labels.json' +_raw_attribute_labels = 'raw_attribute_labels.json' +_object_labels = 'object_labels.json' +_attribute_labels = 'attribute_labels.json' +_regions_with_labels = 'region_with_labels.json' +_unknown_token = 'UNK' +_im_w = 224 +_im_h = 224 + +if not os.path.exists(_outdir): + os.mkdir(_outdir) + +def parse_objects(): + filename = os.path.join(_datadir, _objects) + with open(filename,'r') as file: + data = json.load(file) + + objects_in_image = dict() + for item in data: + objects_in_image[item['id']] = item['objects'] + + regions_in_image = dict() + for item in data: + region_ids = [object['id'] for object in item['objects']] + regions_in_image[item['id']] = region_ids + + objects_in_image_out_filename = os.path.join(_outdir, + _objects_in_image) + with open(objects_in_image_out_filename, 'w') as outfile: + json.dump(objects_in_image, outfile, sort_keys=True, indent=4) + + regions_in_image_out_filename = os.path.join(_outdir, + _regions_in_image) + with open(regions_in_image_out_filename, 'w') as outfile: + json.dump(regions_in_image, outfile, sort_keys=True, indent=4) + + +def parse_attributes(): + filename = os.path.join(_datadir, _attributes) + with open(filename,'r') as file: + data = json.load(file) + + regions = dict() + for image_data in data: + for region_data in image_data['attributes']: + region_data_without_id = dict() + region_data_without_id['image_id'] = image_data['id'] + for key, value in region_data.items(): + if key != 'id': + region_data_without_id[key] = value + regions[region_data['id']] = region_data_without_id + + regions_out_filename = os.path.join(_outdir, + _regions_with_attributes) + with open(regions_out_filename, 'w') as outfile: + json.dump(regions, outfile, sort_keys=True, indent=4) + + +def add_regions_without_attributes(): + regions_with_attributes_filename = os.path.join(_outdir, + _regions_with_attributes) + with open(regions_with_attributes_filename) as file: + regions_with_attributes_data = json.load(file) + + objects_in_image_filename = os.path.join(_outdir, + _objects_in_image) + with open(objects_in_image_filename) as file: + objects_in_image_data = json.load(file) + + regions = regions_with_attributes_data + for image_id, object_regions in objects_in_image_data.items(): + for object_region in object_regions: + if str(object_region['id']) not in regions_with_attributes_data: + region_data_without_id = dict() + region_data_without_id['image_id'] = int(image_id) + region_data_without_id['attributes'] = [] + for key, value in object_region.items(): + if key != 'id': + region_data_without_id[key] = value + regions[object_region['id']] = region_data_without_id + + regions_out_filename = os.path.join(_outdir, + _regions) + with open(regions_out_filename, 'w') as outfile: + json.dump(regions, outfile, sort_keys=True, indent=4) + + +def stats(): + regions_filename = os.path.join(_outdir, _regions) + with open(regions_filename) as file: + regions = json.load(file) + + num_regions = len(regions) + num_regions_with_attributes = 0 + for region in regions.values(): + if region['attributes']: + num_regions_with_attributes += 1 + + print 'Number of regions: {}'.format(num_regions) + print 'Number of regions with attributes: {}'.format( + num_regions_with_attributes) + + +def normalize_object_label(label, lemmatizer): + words = nltk.tokenize.word_tokenize(label) + nouns = [] + for word, pos_tag in nltk.pos_tag(words): + if pos_tag=='NN' or pos_tag=='NNS': + nouns.append(lemmatizer.lemmatize(word)) + return " ".join(nouns).lower() + + +def normalize_attribute_label(label, tokenizer): + words = tokenizer.tokenize(label) + attributes = [] + for word in words: + attributes.append("".join(word)) + return " ".join(attributes).lower() + + +def normalized_labels(): + regions_with_attributes_filename = os.path.join(_outdir, + _regions_with_attributes) + with open(regions_with_attributes_filename) as file: + regions = json.load(file) + + object_labels = dict() + attribute_labels = dict() + object_count = 0 + attribute_count = 0 + lemmatizer = nltk.stem.WordNetLemmatizer() + tokenizer = nltk.tokenize.RegexpTokenizer("([^\W\d]+'[^\W\d]+)|([^\W\d]+)") + for region_id, region_data in regions.items(): + for object in region_data['object_names']: + object = normalize_object_label(object, lemmatizer) + if object not in object_labels: + object_labels[object] = 1 + object_count += 1 + else: + object_labels[object] += 1 + + for attribute in region_data['attributes']: + attribute = normalize_attribute_label(attribute, tokenizer) + if attribute not in attribute_labels: + attribute_labels[attribute] = 1 + attribute_count += 1 + else: + attribute_labels[attribute] += 1 + + print 'Objects: {} Attributes: {}'.format(object_count, + attribute_count) + object_labels_out_filename = os.path.join(_outdir, + _raw_object_labels) + with open(object_labels_out_filename, 'w') as outfile: + json.dump(object_labels, outfile, sort_keys=True, indent=4) + + attribute_labels_out_filename = os.path.join(_outdir, + _raw_attribute_labels) + with open(attribute_labels_out_filename, 'w') as outfile: + json.dump(attribute_labels, outfile, sort_keys=True, indent=4) + + print 'Number of object labels: {}'.format(object_count) + print 'Number of attribute labels: {}'.format(attribute_count) + + +def normalize_region_object_attribute_labels(): + regions_with_attributes_filename = os.path.join(_outdir, + _regions_with_attributes) + with open(regions_with_attributes_filename) as file: + regions = json.load(file) + + lemmatizer = nltk.stem.WordNetLemmatizer() + tokenizer = nltk.tokenize.RegexpTokenizer("([^\W\d]+'[^\W\d]+)|([^\W\d]+)") + count = 0 + for region_id, region_data in regions.items(): + object_names = [] + for object in region_data['object_names']: + if object_names == "": + continue + object_names.append(normalize_object_label(object, lemmatizer)) + region_data['object_names'] = object_names + + attributes = [] + for attribute in region_data['attributes']: + if attributes == "": + continue + attributes.append(normalize_attribute_label(attribute, tokenizer)) + region_data['attributes'] = attributes + count += 1 + print '{}/{}'.format(count, len(regions)) + regions_with_labels_out_filename = os.path.join(_outdir, + _regions_with_labels) + with open(regions_with_labels_out_filename, 'w') as outfile: + json.dump(regions, outfile, sort_keys=True, indent=4) + + +def top_k_object_labels(k): + raw_object_labels_filename = os.path.join(_outdir, + _raw_object_labels) + with open(raw_object_labels_filename, 'r') as file: + raw_object_labels = json.load(file) + + sorted_raw_object_labels = \ + [key for key, value in sorted(raw_object_labels.items(), + key = operator.itemgetter(1), + reverse = True)] + + object_labels = dict() + for i in xrange(min(k,len(sorted_raw_object_labels))): + object_labels[sorted_raw_object_labels[i]] = i + + if "" in object_labels: + object_labels[_unknown_token] = object_labels[""] + del object_labels[""] + + object_labels_filename = os.path.join(_outdir, + _object_labels) + with open(object_labels_filename, 'w') as outfile: + json.dump(object_labels, outfile, sort_keys=True, indent=4) + + +def top_k_attribute_labels(k): + raw_attribute_labels_filename = os.path.join(_outdir, + _raw_attribute_labels) + with open(raw_attribute_labels_filename, 'r') as file: + raw_attribute_labels = json.load(file) + + sorted_raw_attribute_labels = \ + [key for key, value in sorted(raw_attribute_labels.items(), + key = operator.itemgetter(1), + reverse = True)] + + attribute_labels = dict() + for i in xrange(min(k,len(sorted_raw_attribute_labels))): + attribute_labels[sorted_raw_attribute_labels[i]] = i + + if "" in attribute_labels: + attribute_labels[_unknown_token] = attribute_labels[""] + del attribute_labels[""] + + attribute_labels_filename = os.path.join(_outdir, + _attribute_labels) + with open(attribute_labels_filename, 'w') as outfile: + json.dump(attribute_labels, outfile, sort_keys=True, indent=4) + + +def crop_region(region_info): + region_id, region_data = region_info + image_filename = os.path.join(_datadir, + 'images/' + + str(region_data['image_id']) + '.jpg') + image = image_io.imread(image_filename) + + if len(image.shape)==3: + im_h, im_w, im_c =image.shape + elif len(image.shape)==2: + im_h, im_w =image.shape + image_tmp = np.zeros([im_h, im_w, 3], dtype=image.dtype) + for c in xrange(3): + image_tmp[:,:,c] = image + image = image_tmp + + x = min(im_w-1,max(0,region_data["x"])) + y = min(im_h-1,max(0,region_data["y"])) + h = min(im_h-y,max(region_data["h"],1)) + w = min(im_w-x,max(region_data["w"],1)) + + cropped_region = image_io.imresize(image[y:y+h,x:x+w,:], + output_size=(_im_h, _im_w)) + image_subdir = os.path.join(_cropped_regions_dir, + str(region_data['image_id'])) + if not os.path.exists(image_subdir): + os.mkdir(image_subdir) + + image_out_filename = os.path.join(image_subdir, + str(region_id) + '.jpg') + + image_io.imwrite(cropped_region, image_out_filename) + + +def crop_regions_parallel(): + regions_filename = os.path.join(_outdir, + _regions_with_labels) + with open(regions_filename) as file: + regions = json.load(file) + + if not os.path.exists(_cropped_regions_dir): + os.mkdir(_cropped_regions_dir) + + pool = Pool(24) + try: + pool.map(crop_region, regions.items()) + except: + pool.close() + pool.close() + + +def crop_regions(): + regions_filename = os.path.join(_outdir, + _regions_with_labels) + with open(regions_filename) as file: + regions = json.load(file) + + if not os.path.exists(_cropped_regions_dir): + os.mkdir(_cropped_regions_dir) + + count = 0 + for region_id, region_data in regions.items(): + try: + image_filename = os.path.join(_datadir, + 'images/' + + str(region_data['image_id']) + '.jpg') + image = image_io.imread(image_filename) + + if len(image.shape)==3: + im_h, im_w, im_c =image.shape + elif len(image.shape)==2: + im_h, im_w =image.shape + image_tmp = np.zeros([im_h, im_w, 3], dtype=image.dtype) + for c in xrange(3): + image_tmp[:,:,c] = image + image = image_tmp + + x = min(im_w-1,max(0,region_data["x"])) + y = min(im_h-1,max(0,region_data["y"])) + h = min(im_h-y,max(region_data["h"],1)) + w = min(im_w-x,max(region_data["w"],1)) + + cropped_region = image_io.imresize(image[y:y+h,x:x+w,:], + output_size=(_im_h, _im_w)) + image_subdir = os.path.join(_cropped_regions_dir, + str(region_data['image_id'])) + if not os.path.exists(image_subdir): + os.mkdir(image_subdir) + + image_out_filename = os.path.join(image_subdir, + str(region_id) + '.jpg') + + image_io.imwrite(cropped_region, image_out_filename) + + count += 1 + + print '{}/{}'.format(count, len(regions)) + except: + print region_id, region_data + raise + + +if __name__=='__main__': + # parse_objects() + # parse_attributes() + # add_regions_without_attributes() + # stats() + # normalized_labels() + # normalize_region_object_attribute_labels() + # top_k_object_labels(1000) + # top_k_attribute_labels(1000) + crop_regions_parallel() -- GitLab