Skip to content

Commit ec543fa

Browse files
committed
get a more flexible FeatureDescriptor cell that can load Feature/Descriptor from another package
1 parent 8010c8f commit ec543fa

File tree

8 files changed

+147
-67
lines changed

8 files changed

+147
-67
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/opencv_candidate
3838
)
3939

4040
add_subdirectory(cells)
41+
add_subdirectory(python)
4142
add_subdirectory(src)
4243

4344
option(BUILD_TEST "Build tests" ON)

cells/opencv/features2d/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
ectomodule(features2d DESTINATION ecto_opencv
1+
ectomodule(features2d DESTINATION ecto_opencv/ecto_cells
22
INSTALL
33
module.cpp
44
DescriptorExtractor.cpp

python/CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
configure_file(__init__.py.plain.in
2+
${ECTO_PYTHON_BUILD_PATH}/${PROJECT_NAME}/ecto_cells/__init__.py
3+
@ONLY
4+
)
5+
6+
install(FILES ${ECTO_PYTHON_BUILD_PATH}/${PROJECT_NAME}/ecto_cells/__init__.py
7+
DESTINATION ${ECTO_PYTHON_INSTALL_PATH}/${PROJECT_NAME}/ecto_cells
8+
)

python/__init__.py.plain.in

Whitespace-only changes.

python/ecto_opencv/feature_descriptor.py

Lines changed: 0 additions & 65 deletions
This file was deleted.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
from feature_descriptor import *
2+
from ecto_opencv.ecto_cells.features2d import *
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
#!/usr/bin/env python
2+
"""
3+
Module defining a function that returns the appropriate ecto cells for Feature and Descriptor finding
4+
"""
5+
6+
import ecto_opencv.ecto_cells.features2d as features2d
7+
import ecto
8+
import inspect
9+
import pkgutil
10+
11+
def find_cell(modules, cell_name):
12+
'''
13+
Given a list of python packages, or modules, find an object of the given name.
14+
:param module: The module to look the cell into
15+
:param cell_name: the name of cell to find
16+
:returns: the object class itself
17+
'''
18+
ms = []
19+
for module in modules:
20+
if module == '':
21+
continue
22+
23+
m = __import__(module)
24+
ms += [m]
25+
for loader, module_name, is_pkg in pkgutil.walk_packages(m.__path__):
26+
if is_pkg:
27+
module = loader.find_module(module_name).load_module(module_name)
28+
ms.append(module)
29+
30+
for pymodule in ms:
31+
for name, potential_cell in inspect.getmembers(pymodule):
32+
if name==cell_name:
33+
return potential_cell
34+
35+
return None
36+
37+
class FeatureDescriptor(ecto.BlackBox):
38+
"""
39+
Function that takes JSON parameters for Feature/Descriptor extraction and that returns the appropriate blackbox
40+
combining the two (or just using one cell in the background).
41+
Both the Feature and the Descriptor will be computed
42+
"""
43+
ORB_combination = features2d.ORB
44+
SIFT_combination = features2d.SIFT
45+
_image_passthrough = ecto.Passthrough
46+
_mask_passthrough = ecto.Passthrough
47+
48+
# def __init__(self, **kwargs):
49+
# ecto.BlackBox.__init__(self, **kwargs)
50+
# self._feature_cell = None
51+
# self._descriptor_cell = None
52+
# self._feature_descriptor_cell = None
53+
54+
def declare_params(self, p):
55+
p.declare('json_feature_params', 'Parameters for the feature as a JSON string. '
56+
'It should have the format: "{"type":"ORB/SIFT whatever", "opencv_param_1":val1, ....}',
57+
'{"type": "ORB", "package": "ecto_opencv"}')
58+
p.declare('json_descriptor_params', 'Parameters for the descriptor as a JSON string. '
59+
'It should have the format: "{"type":"ORB/SIFT whatever", "opencv_param_1":val1, ....}',
60+
'{"type": "ORB", "package": "ecto_opencv"}')
61+
62+
def declare_io(self, p, i, o):
63+
# Make sure the parameters are valid
64+
for dict_key, p_val, desc in [ ('_feature_params', p.json_feature_params, 'feature'),
65+
('_descriptor_params', p.json_descriptor_params, 'descriptor') ]:
66+
try:
67+
self.__dict__[dict_key] = eval(p_val)
68+
except:
69+
raise RuntimeError('Invalid JSON for the ' + desc + ': ' + p.json_feature_params)
70+
for key in ['type', 'package']:
71+
if key not in self.__dict__[dict_key]:
72+
raise RuntimeError('No "%s" given for the %s; params: %s' % (key, desc, str(self.__dict__[dict_key])))
73+
self.__dict__['_%s_type' % desc] = self.__dict__[dict_key].pop('type')
74+
self.__dict__['_%s_package' % desc] = self.__dict__[dict_key].pop('package')
75+
76+
# Deal with the combinations first
77+
self._feature_cell = None
78+
self._descriptor_cell = None
79+
self._feature_descriptor_cell = None
80+
if self._feature_type == self._descriptor_type and \
81+
self._feature_package == self._descriptor_package == 'ecto_opencv':
82+
# deal with the combo case
83+
try:
84+
if self._feature_type == 'ORB':
85+
self._feature_descriptor_cell = self.ORB_combination(**self._feature_params)
86+
elif self._feature_type == 'SIFT':
87+
self._feature_descriptor_cell = self.SIFT_combination(**self._feature_params)
88+
except:
89+
raise RuntimeError('Parameters not supported for FeatureDescriptor: feature %s; descriptor: %s' %
90+
(self._feature_params, self._descriptor_params))
91+
if self._feature_type not in ['ORB', 'SIFT']:
92+
raise RuntimeError('Parameters not supported for FeatureDescriptor: feature %s; descriptor: %s' %
93+
(self._feature_params, self._descriptor_params))
94+
else:
95+
# if we are not computing everything at once, define the feature and the descriptor separately
96+
feature_class = find_cell([self._feature_package], self._feature_type)
97+
if feature_class is None:
98+
raise RuntimeError('Feature class not found: (type, package) = (%s, %s)' % (self._feature_type, self._feature_package))
99+
self._feature_cell = feature_class(**self._feature_params)
100+
101+
descriptor_class = find_cell([self._descriptor_package], self._descriptor_type)
102+
if descriptor_class is None:
103+
raise RuntimeError('Descriptor class not found: (type, package) = (%s, %s)' % (self._descriptor_type, self._descriptor_package))
104+
self._descriptor_cell = descriptor_class(**self._descriptor_params)
105+
106+
# everybody needs an image
107+
self._image_passthrough = ecto.Passthrough()
108+
if self._feature_descriptor_cell is None:
109+
i.forward('image', cell_name = '_image_passthrough', cell_key = 'in')
110+
i.forward('mask', cell_name = '_mask_passthrough', cell_key = 'in')
111+
if 'depth' in self._feature_cell.inputs.keys():
112+
i.forward('depth', cell_name = '_feature_cell', cell_key = 'input')
113+
o.forward('keypoints', cell_name = '_feature_cell', cell_key = 'keypoints')
114+
o.forward('descriptors', cell_name = '_descriptor_cell', cell_key = 'descriptors')
115+
else:
116+
# deal with the combo case
117+
i.forward_all('_feature_descriptor_cell')
118+
o.forward_all('_feature_descriptor_cell')
119+
120+
def configure(self, p, i, o):
121+
pass
122+
123+
def connections(self):
124+
connections = []
125+
if self._feature_descriptor_cell is None:
126+
connections += [ self._image_passthrough[:] >> self._feature_cell['image'],
127+
self._image_passthrough[:] >> self._descriptor_cell['image'] ]
128+
connections += [ self._mask_passthrough[:] >> self._feature_cell['mask'],
129+
self._mask_passthrough[:] >> self._descriptor_cell['mask'] ]
130+
connections += [ self._feature_cell['keypoints'] >> self._descriptor_cell['keypoints'] ]
131+
else:
132+
connections = [ ]
133+
134+
return connections

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@
44
setup(name='Ecto OpenCV',
55
version='1.0.0',
66
description='Ecto bindings for OpenCV',
7-
packages=['ecto_opencv'],
7+
packages=['ecto_opencv', 'ecto_opencv.features2d'],
88
package_dir={'':'python'}
99
)

0 commit comments

Comments
 (0)