Skip to content

Commit

Permalink
updated baseline with improved performance, added initial reference t…
Browse files Browse the repository at this point in the history
…o arXiv paper
  • Loading branch information
mukhery committed Nov 17, 2017
1 parent e18ab9d commit 17d8604
Show file tree
Hide file tree
Showing 5 changed files with 258 additions and 158 deletions.
22 changes: 18 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
# fMoW: Functional Map of the World

This code was developed by [JHU/APL](http://www.jhuapl.edu).
This code was developed by [JHU/APL](https://jhuapl.edu).


## Dependencies

The following libraries were used for training/testing the deep learning models:

Keras 2.0.5
Keras 2.0.8

Tensorflow 1.2.1
Tensorflow 1.3.0

DenseNet from [titu1994/DenseNet](https://github.com/titu1994/DenseNet)

tqdm

## Dataset

Expand Down Expand Up @@ -89,6 +90,19 @@ Once this is complete, the following arguments can be passed in to run different

Our best performing model is the CNN-only approach, which sums predictions over each temporal view and then takes an argmax. However, we provide code for using an LSTM, which performs slightly worse, so that modifications can be made.

## References

If you would like to cite this baseline, please reference:
```
@article{fmow2017,
title={Functional Map of the World},
author={Christie, Gordon and Fendley, Neil and Wilson, James and Mukherjee, Ryan},
journal={arXiv:TBD},
year={2017}
}
```
**Note: This will be updated on Tuesday when published.**

## License

The license is Apache 2.0. See LICENSE.
110 changes: 82 additions & 28 deletions code/data_ml_functions/dataFunctions.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@
from tqdm import tqdm
import warnings

import code

def prepare_data(params):
"""
Saves sub images, converts metadata to feature vectors and saves in JSON files,
Expand Down Expand Up @@ -61,7 +59,7 @@ def prepare_data(params):
else:
outDir = params.directories['test_data']

print('Looping through sequences in: ' + currDir)
print('Queuing sequences in: ' + currDir)
for root, dirs, files in tqdm(os.walk(os.path.join(params.directories['dataset'], currDir))):
if len(files) > 0:
slashes = [i for i,ltr in enumerate(root) if ltr == '/']
Expand All @@ -71,7 +69,7 @@ def prepare_data(params):
task = partial(_process_file, file, slashes, root, isTrain, outDir, paramsDict)
futures.append(executor.submit(task))

print('Preprocessing all files...')
print('Wait for all preprocessing tasks to complete...')
results = []
[results.extend(future.result()) for future in tqdm(futures)]
allTrainFeatures = [np.array(r[0]) for r in results if r[0] is not None]
Expand All @@ -84,6 +82,9 @@ def prepare_data(params):
trainCount = len(trainingData)
testData = [r[2] for r in results if r[2] is not None]

# Shutdown the executor and free resources
executor.shutdown()

metadataMean = metadataTrainSum / trainCount
metadataMax = np.zeros(params.metadata_length)
for currFeat in allTrainFeatures:
Expand Down Expand Up @@ -161,13 +162,43 @@ def _process_file(file, slashes, root, isTrain, outDir, params):
continue

# train with context around box
widthBuffer = int((box[2] * 0.5) / 2.0)
heightBuffer = int((box[2] * 0.5) / 2.0)

contextMultWidth = 0.15
contextMultHeight = 0.15

wRatio = float(box[2]) / img.shape[0]
hRatio = float(box[3]) / img.shape[1]

if wRatio < 0.5 and wRatio >= 0.4:
contextMultWidth = 0.2
if wRatio < 0.4 and wRatio >= 0.3:
contextMultWidth = 0.3
if wRatio < 0.3 and wRatio >= 0.2:
contextMultWidth = 0.5
if wRatio < 0.2 and wRatio >= 0.1:
contextMultWidth = 1
if wRatio < 0.1:
contextMultWidth = 2

if hRatio < 0.5 and hRatio >= 0.4:
contextMultHeight = 0.2
if hRatio < 0.4 and hRatio >= 0.3:
contextMultHeight = 0.3
if hRatio < 0.3 and hRatio >= 0.2:
contextMultHeight = 0.5
if hRatio < 0.2 and hRatio >= 0.1:
contextMultHeight = 1
if hRatio < 0.1:
contextMultHeight = 2


widthBuffer = int((box[2] * contextMultWidth) / 2.0)
heightBuffer = int((box[3] * contextMultHeight) / 2.0)

r1 = box[1] - heightBuffer
r2 = r1 + box[3] + heightBuffer
r2 = box[1] + box[3] + heightBuffer
c1 = box[0] - widthBuffer
c2 = c1 + box[2] + widthBuffer
c2 = box[0] + box[2] + widthBuffer

if r1 < 0:
r1 = 0
Expand All @@ -186,10 +217,11 @@ def _process_file(file, slashes, root, isTrain, outDir, params):
subImg = subImg.resize(params['target_img_size'])
subImg.save(imgPath)

features = json_to_feature_vector(params['metadata_length'], jsonData)
features = json_to_feature_vector(params, jsonData, bb)
features = features.tolist()

json.dump(features, open(featuresPath, 'w'))


if isTrain:
allResults.append((features, {"features_path": featuresPath, "img_path": imgPath, "category": params['category_names'].index(category)}, None))
Expand All @@ -198,14 +230,9 @@ def _process_file(file, slashes, root, isTrain, outDir, params):

return allResults

def json_to_feature_vector(metadata_length, jsonData):
"""
Generates feature vector for CNN fusion from metadata
:param metadata_length: total number of metadata parameters being used
:param jsonData: metadata from a JSON file
:return features: numpy feature vector representation of the metadata
"""
features = np.zeros(metadata_length, dtype=float)

def json_to_feature_vector(params, jsonData, bb):
features = np.zeros(params['metadata_length'], dtype=float)
features[0] = float(jsonData['gsd'])
x,y = utm_to_xy(jsonData['utm'])
features[1] = x
Expand All @@ -222,17 +249,44 @@ def json_to_feature_vector(metadata_length, jsonData):
else:
features[8] = 1.0
features[9] = float(jsonData['pan_resolution_dbl'])
features[10] = float(jsonData['multi_resolution_dbl'])
features[11] = float(jsonData['target_azimuth_dbl']) / 360.0
features[12] = float(jsonData['sun_azimuth_dbl']) / 360.0
features[13] = float(jsonData['sun_elevation_dbl']) / 90.0
features[14] = float(jsonData['off_nadir_angle_dbl']) / 90.0
features[15] = float(jsonData['bounding_boxes'][0]['box'][2])
features[16] = float(jsonData['bounding_boxes'][0]['box'][3])
features[17] = float(jsonData['img_width'])
features[18] = float(jsonData['img_height'])
features[19] = float(len(jsonData['approximate_wavelengths']))
features[20] = float(date.weekday())
features[10] = float(jsonData['pan_resolution_start_dbl'])
features[11] = float(jsonData['pan_resolution_end_dbl'])
features[12] = float(jsonData['pan_resolution_min_dbl'])
features[13] = float(jsonData['pan_resolution_max_dbl'])
features[14] = float(jsonData['multi_resolution_dbl'])
features[15] = float(jsonData['multi_resolution_min_dbl'])
features[16] = float(jsonData['multi_resolution_max_dbl'])
features[17] = float(jsonData['multi_resolution_start_dbl'])
features[18] = float(jsonData['multi_resolution_end_dbl'])
features[19] = float(jsonData['target_azimuth_dbl']) / 360.0
features[20] = float(jsonData['target_azimuth_min_dbl']) / 360.0
features[21] = float(jsonData['target_azimuth_max_dbl']) / 360.0
features[22] = float(jsonData['target_azimuth_start_dbl']) / 360.0
features[23] = float(jsonData['target_azimuth_end_dbl']) / 360.0
features[24] = float(jsonData['sun_azimuth_dbl']) / 360.0
features[25] = float(jsonData['sun_azimuth_min_dbl']) / 360.0
features[26] = float(jsonData['sun_azimuth_max_dbl']) / 360.0
features[27] = float(jsonData['sun_elevation_min_dbl']) / 90.0
features[28] = float(jsonData['sun_elevation_dbl']) / 90.0
features[29] = float(jsonData['sun_elevation_max_dbl']) / 90.0
features[30] = float(jsonData['off_nadir_angle_dbl']) / 90.0
features[31] = float(jsonData['off_nadir_angle_min_dbl']) / 90.0
features[32] = float(jsonData['off_nadir_angle_max_dbl']) / 90.0
features[33] = float(jsonData['off_nadir_angle_start_dbl']) / 90.0
features[34] = float(jsonData['off_nadir_angle_end_dbl']) / 90.0
features[35] = float(bb['box'][2])
features[36] = float(bb['box'][3])
features[37] = float(jsonData['img_width'])
features[38] = float(jsonData['img_height'])
features[39] = float(date.weekday())
features[40] = min([features[35], features[36]]) / max([features[37], features[38]])
features[41] = features[35] / features[37]
features[42] = features[36] / features[38]
features[43] = date.second
if len(jsonData['bounding_boxes']) == 1:
features[44] = 1.0
else:
features[44] = 0.0

return features

Expand Down
Loading

0 comments on commit 17d8604

Please sign in to comment.