Commit 9f3d5bcc authored by Andre Araujo's avatar Andre Araujo
Browse files

Small polishing changes to DELF code.

PiperOrigin-RevId: 185469605
parent 0d7ce10e
...@@ -24,10 +24,11 @@ from __future__ import absolute_import ...@@ -24,10 +24,11 @@ from __future__ import absolute_import
from __future__ import division from __future__ import division
from __future__ import print_function from __future__ import print_function
from delf import datum_pb2
import numpy as np import numpy as np
import tensorflow as tf import tensorflow as tf
from delf import datum_pb2
def ArrayToDatum(arr): def ArrayToDatum(arr):
"""Converts numpy array to DatumProto. """Converts numpy array to DatumProto.
......
...@@ -12,19 +12,19 @@ ...@@ -12,19 +12,19 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
# ============================================================================== # ==============================================================================
"""Tests for datum_io, the python interface of DatumProto.""" """Tests for datum_io, the python interface of DatumProto."""
from __future__ import absolute_import from __future__ import absolute_import
from __future__ import division from __future__ import division
from __future__ import print_function from __future__ import print_function
from delf import datum_io
from delf import datum_pb2
import numpy as np
import os import os
import numpy as np
import tensorflow as tf import tensorflow as tf
from delf import datum_io
class DatumIoTest(tf.test.TestCase): class DatumIoTest(tf.test.TestCase):
......
...@@ -12,8 +12,7 @@ ...@@ -12,8 +12,7 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
# ============================================================================== # ==============================================================================
"""DELF model implementation based on the following paper.
"""DELF model implementation based on the following paper:
Large-Scale Image Retrieval with Attentive Deep Local Features Large-Scale Image Retrieval with Attentive Deep Local Features
https://arxiv.org/abs/1612.06321 https://arxiv.org/abs/1612.06321
...@@ -26,10 +25,10 @@ from __future__ import absolute_import ...@@ -26,10 +25,10 @@ from __future__ import absolute_import
from __future__ import division from __future__ import division
from __future__ import print_function from __future__ import print_function
from nets import resnet_v1
import tensorflow as tf import tensorflow as tf
from nets import resnet_v1
slim = tf.contrib.slim slim = tf.contrib.slim
_SUPPORTED_TARGET_LAYER = ['resnet_v1_50/block3', 'resnet_v1_50/block4'] _SUPPORTED_TARGET_LAYER = ['resnet_v1_50/block3', 'resnet_v1_50/block4']
......
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
# ============================================================================== # ==============================================================================
"""Extracts DELF features from a list of images, saving them to file. """Extracts DELF features from a list of images, saving them to file.
The images must be in JPG format. The program checks if descriptors already The images must be in JPG format. The program checks if descriptors already
...@@ -24,18 +23,17 @@ from __future__ import division ...@@ -24,18 +23,17 @@ from __future__ import division
from __future__ import print_function from __future__ import print_function
import argparse import argparse
from google.protobuf import text_format
import numpy as np
import os import os
import sys import sys
import tensorflow as tf
from tensorflow.python.platform import app
import time import time
import tensorflow as tf
from google.protobuf import text_format
from tensorflow.python.platform import app
from delf import delf_config_pb2 from delf import delf_config_pb2
from delf import feature_extractor from delf import feature_extractor
from delf import feature_io from delf import feature_io
from delf import feature_pb2
cmd_args = None cmd_args = None
...@@ -152,9 +150,9 @@ def main(unused_argv): ...@@ -152,9 +150,9 @@ def main(unused_argv):
config.delf_local_config.max_feature_num config.delf_local_config.max_feature_num
}) })
serialized_desc = feature_io.WriteToFile( feature_io.WriteToFile(out_desc_fullpath, locations_out,
out_desc_fullpath, locations_out, feature_scales_out, feature_scales_out, descriptors_out,
descriptors_out, attention_out) attention_out)
# Finalize enqueue threads. # Finalize enqueue threads.
coord.request_stop() coord.request_stop()
......
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
# ============================================================================== # ==============================================================================
"""Matches two images using their DELF features. """Matches two images using their DELF features.
The matching is done using feature-based nearest-neighbor search, followed by The matching is done using feature-based nearest-neighbor search, followed by
...@@ -26,7 +25,8 @@ from __future__ import division ...@@ -26,7 +25,8 @@ from __future__ import division
from __future__ import print_function from __future__ import print_function
import argparse import argparse
from delf import feature_io import sys
import matplotlib.image as mpimg import matplotlib.image as mpimg
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import numpy as np import numpy as np
...@@ -34,9 +34,10 @@ from scipy.spatial import cKDTree ...@@ -34,9 +34,10 @@ from scipy.spatial import cKDTree
from skimage.feature import plot_matches from skimage.feature import plot_matches
from skimage.measure import ransac from skimage.measure import ransac
from skimage.transform import AffineTransform from skimage.transform import AffineTransform
import sys
import tensorflow as tf import tensorflow as tf
from tensorflow.python.platform import app from tensorflow.python.platform import app
from delf import feature_io
cmd_args = None cmd_args = None
...@@ -58,21 +59,23 @@ def main(unused_argv): ...@@ -58,21 +59,23 @@ def main(unused_argv):
# Find nearest-neighbor matches using a KD tree. # Find nearest-neighbor matches using a KD tree.
d1_tree = cKDTree(descriptors_1) d1_tree = cKDTree(descriptors_1)
distances, indices = d1_tree.query( _, indices = d1_tree.query(
descriptors_2, distance_upper_bound=_DISTANCE_THRESHOLD) descriptors_2, distance_upper_bound=_DISTANCE_THRESHOLD)
# Select feature locations for putative matches. # Select feature locations for putative matches.
locations_2_to_use = np.array([ locations_2_to_use = np.array([
locations_2[i,] for i in range(num_features_2) locations_2[i,]
for i in range(num_features_2)
if indices[i] != num_features_1 if indices[i] != num_features_1
]) ])
locations_1_to_use = np.array([ locations_1_to_use = np.array([
locations_1[indices[i],] for i in range(num_features_2) locations_1[indices[i],]
for i in range(num_features_2)
if indices[i] != num_features_1 if indices[i] != num_features_1
]) ])
# Perform geometric verification using RANSAC. # Perform geometric verification using RANSAC.
model_robust, inliers = ransac( _, inliers = ransac(
(locations_1_to_use, locations_2_to_use), (locations_1_to_use, locations_2_to_use),
AffineTransform, AffineTransform,
min_samples=3, min_samples=3,
...@@ -82,7 +85,7 @@ def main(unused_argv): ...@@ -82,7 +85,7 @@ def main(unused_argv):
tf.logging.info('Found %d inliers' % sum(inliers)) tf.logging.info('Found %d inliers' % sum(inliers))
# Visualize correspondences, and save to file. # Visualize correspondences, and save to file.
fig, ax = plt.subplots() _, ax = plt.subplots()
img_1 = mpimg.imread(cmd_args.image_1_path) img_1 = mpimg.imread(cmd_args.image_1_path)
img_2 = mpimg.imread(cmd_args.image_2_path) img_2 = mpimg.imread(cmd_args.image_2_path)
inlier_idxs = np.nonzero(inliers)[0] inlier_idxs = np.nonzero(inliers)[0]
......
...@@ -18,12 +18,12 @@ from __future__ import absolute_import ...@@ -18,12 +18,12 @@ from __future__ import absolute_import
from __future__ import division from __future__ import division
from __future__ import print_function from __future__ import print_function
import tensorflow as tf
from delf import datum_io from delf import datum_io
from delf import delf_v1 from delf import delf_v1
from delf import delf_config_pb2
from object_detection.core import box_list from object_detection.core import box_list
from object_detection.core import box_list_ops from object_detection.core import box_list_ops
import tensorflow as tf
def NormalizePixelValues(image, def NormalizePixelValues(image,
...@@ -170,7 +170,8 @@ def ExtractKeypointDescriptor(image, layer_name, image_scales, iou, ...@@ -170,7 +170,8 @@ def ExtractKeypointDescriptor(image, layer_name, image_scales, iou,
resized_image, normalized_image=True, reuse=reuse) resized_image, normalized_image=True, reuse=reuse)
rf_boxes = CalculateReceptiveBoxes( rf_boxes = CalculateReceptiveBoxes(
tf.shape(feature_map)[1], tf.shape(feature_map)[2], rf, stride, padding) tf.shape(feature_map)[1],
tf.shape(feature_map)[2], rf, stride, padding)
# Re-project back to the original image space. # Re-project back to the original image space.
rf_boxes = tf.divide(rf_boxes, scale) rf_boxes = tf.divide(rf_boxes, scale)
attention = tf.reshape(attention, [-1]) attention = tf.reshape(attention, [-1])
...@@ -236,8 +237,8 @@ def ExtractKeypointDescriptor(image, layer_name, image_scales, iou, ...@@ -236,8 +237,8 @@ def ExtractKeypointDescriptor(image, layer_name, image_scales, iou,
nms_max_boxes) nms_max_boxes)
return (final_boxes.get(), final_boxes.get_field('scales'), return (final_boxes.get(), final_boxes.get_field('scales'),
final_boxes.get_field('features'), tf.expand_dims( final_boxes.get_field('features'),
final_boxes.get_field('scores'), 1)) tf.expand_dims(final_boxes.get_field('scores'), 1))
def BuildModel(layer_name, attention_nonlinear, attention_type, def BuildModel(layer_name, attention_nonlinear, attention_type,
......
...@@ -12,17 +12,17 @@ ...@@ -12,17 +12,17 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
# ============================================================================== # ==============================================================================
"""Tests for DELF feature extractor.""" """Tests for DELF feature extractor."""
from __future__ import absolute_import from __future__ import absolute_import
from __future__ import division from __future__ import division
from __future__ import print_function from __future__ import print_function
from delf import feature_extractor
import numpy as np import numpy as np
import tensorflow as tf import tensorflow as tf
from delf import feature_extractor
class FeatureExtractorTest(tf.test.TestCase): class FeatureExtractorTest(tf.test.TestCase):
...@@ -80,14 +80,15 @@ class FeatureExtractorTest(tf.test.TestCase): ...@@ -80,14 +80,15 @@ class FeatureExtractorTest(tf.test.TestCase):
axis=3) axis=3)
return attention, feature_map return attention, feature_map
boxes, feature_scales, features, scores = feature_extractor.ExtractKeypointDescriptor( boxes, feature_scales, features, scores = (
feature_extractor.ExtractKeypointDescriptor(
image, image,
layer_name='resnet_v1_50/block3', layer_name='resnet_v1_50/block3',
image_scales=tf.constant([1.0]), image_scales=tf.constant([1.0]),
iou=1.0, iou=1.0,
max_feature_num=10, max_feature_num=10,
abs_thres=1.5, abs_thres=1.5,
model_fn=_test_model_fn) model_fn=_test_model_fn))
exp_boxes = [[-145.0, -145.0, 145.0, 145.0], [-113.0, -145.0, 177.0, 145.0]] exp_boxes = [[-145.0, -145.0, 145.0, 145.0], [-113.0, -145.0, 177.0, 145.0]]
exp_feature_scales = [1.0, 1.0] exp_feature_scales = [1.0, 1.0]
......
...@@ -21,11 +21,12 @@ from __future__ import absolute_import ...@@ -21,11 +21,12 @@ from __future__ import absolute_import
from __future__ import division from __future__ import division
from __future__ import print_function from __future__ import print_function
from delf import feature_pb2
from delf import datum_io
import numpy as np import numpy as np
import tensorflow as tf import tensorflow as tf
from delf import feature_pb2
from delf import datum_io
def ArraysToDelfFeatures(locations, def ArraysToDelfFeatures(locations,
scales, scales,
...@@ -57,7 +58,7 @@ def ArraysToDelfFeatures(locations, ...@@ -57,7 +58,7 @@ def ArraysToDelfFeatures(locations,
assert num_features == len(orientations) assert num_features == len(orientations)
delf_features = feature_pb2.DelfFeatures() delf_features = feature_pb2.DelfFeatures()
for i in xrange(num_features): for i in range(num_features):
delf_feature = delf_features.feature.add() delf_feature = delf_features.feature.add()
delf_feature.y = locations[i, 0] delf_feature.y = locations[i, 0]
delf_feature.x = locations[i, 1] delf_feature.x = locations[i, 1]
...@@ -98,7 +99,7 @@ def DelfFeaturesToArrays(delf_features): ...@@ -98,7 +99,7 @@ def DelfFeaturesToArrays(delf_features):
attention = np.zeros([num_features]) attention = np.zeros([num_features])
orientations = np.zeros([num_features]) orientations = np.zeros([num_features])
for i in xrange(num_features): for i in range(num_features):
delf_feature = delf_features.feature[i] delf_feature = delf_features.feature[i]
locations[i, 0] = delf_feature.y locations[i, 0] = delf_feature.y
locations[i, 1] = delf_feature.x locations[i, 1] = delf_feature.x
......
...@@ -12,22 +12,23 @@ ...@@ -12,22 +12,23 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
# ============================================================================== # ==============================================================================
"""Tests for feature_io, the python interface of DelfFeatures.""" """Tests for feature_io, the python interface of DelfFeatures."""
from __future__ import absolute_import from __future__ import absolute_import
from __future__ import division from __future__ import division
from __future__ import print_function from __future__ import print_function
from delf import feature_io
from delf import datum_pb2
import numpy as np
import os import os
import numpy as np
import tensorflow as tf import tensorflow as tf
from delf import feature_io
def create_data(): def create_data():
"""Creates data to be used in tests. """Creates data to be used in tests.
Returns: Returns:
locations: [N, 2] float array which denotes the selected keypoint locations: [N, 2] float array which denotes the selected keypoint
locations. N is the number of features. locations. N is the number of features.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment