diff --git a/README.rst b/README.rst index c553949d36757a338d4a10febc35185df15a21bd..02b0f6a89e497d67c54bace3e38ffee0fd195562 100644 --- a/README.rst +++ b/README.rst @@ -16,8 +16,6 @@ It includes examples with three different complexities: To use this example, you will require Bob and the AT&T database. If you do not have a Bob version yet, you can get it from http://www.idiap.ch/software/bob. -If you already have installed Bob, please make sure that you have the version 1.0.5, otherwise the example won't work. - The AT&T image database is quite small, but sufficient to show how the face verification methods work. Still, the results may not be meaningful. One good thing about the AT&T database is that it is freely available. diff --git a/bootstrap.py b/bootstrap.py index 7647cbbe10e7638d71079fd8f6ca295e89941a51..ec3757a965c4a28ffd6cd900f4f5260239a30bcc 100644 --- a/bootstrap.py +++ b/bootstrap.py @@ -18,75 +18,10 @@ The script accepts buildout command-line options, so you can use the -c option to specify an alternate configuration file. """ -import os, shutil, sys, tempfile, urllib, urllib2, subprocess +import os, shutil, sys, tempfile from optparse import OptionParser -if sys.platform == 'win32': - def quote(c): - if ' ' in c: - return '"%s"' % c # work around spawn lamosity on windows - else: - return c -else: - quote = str - -# See zc.buildout.easy_install._has_broken_dash_S for motivation and comments. -stdout, stderr = subprocess.Popen( - [sys.executable, '-Sc', - 'try:\n' - ' import ConfigParser\n' - 'except ImportError:\n' - ' print 1\n' - 'else:\n' - ' print 0\n'], - stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() -has_broken_dash_S = bool(int(stdout.strip())) - -# In order to be more robust in the face of system Pythons, we want to -# run without site-packages loaded. This is somewhat tricky, in -# particular because Python 2.6's distutils imports site, so starting -# with the -S flag is not sufficient. However, we'll start with that: -if not has_broken_dash_S and 'site' in sys.modules: - # We will restart with python -S. - args = sys.argv[:] - args[0:0] = [sys.executable, '-S'] - args = map(quote, args) - os.execv(sys.executable, args) -# Now we are running with -S. We'll get the clean sys.path, import site -# because distutils will do it later, and then reset the path and clean -# out any namespace packages from site-packages that might have been -# loaded by .pth files. -clean_path = sys.path[:] -import site # imported because of its side effects -sys.path[:] = clean_path -for k, v in sys.modules.items(): - if k in ('setuptools', 'pkg_resources') or ( - hasattr(v, '__path__') and - len(v.__path__) == 1 and - not os.path.exists(os.path.join(v.__path__[0], '__init__.py'))): - # This is a namespace package. Remove it. - sys.modules.pop(k) - -is_jython = sys.platform.startswith('java') - -setuptools_source = 'http://peak.telecommunity.com/dist/ez_setup.py' -distribute_source = 'http://python-distribute.org/distribute_setup.py' - - -# parsing arguments -def normalize_to_url(option, opt_str, value, parser): - if value: - if '://' not in value: # It doesn't smell like a URL. - value = 'file://%s' % ( - urllib.pathname2url( - os.path.abspath(os.path.expanduser(value))),) - if opt_str == '--download-base' and not value.endswith('/'): - # Download base needs a trailing slash to make the world happy. - value += '/' - else: - value = None - name = opt_str[2:].replace('-', '_') - setattr(parser.values, name, value) +tmpeggs = tempfile.mkdtemp() usage = '''\ [DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options] @@ -101,26 +36,8 @@ local resources, you can keep this script from going over the network. ''' parser = OptionParser(usage=usage) -parser.add_option("-v", "--version", dest="version", - help="use a specific zc.buildout version") -parser.add_option("-d", "--distribute", - action="store_true", dest="use_distribute", default=False, - help="Use Distribute rather than Setuptools.") -parser.add_option("--setup-source", action="callback", dest="setup_source", - callback=normalize_to_url, nargs=1, type="string", - help=("Specify a URL or file location for the setup file. " - "If you use Setuptools, this will default to " + - setuptools_source + "; if you use Distribute, this " - "will default to " + distribute_source + ".")) -parser.add_option("--download-base", action="callback", dest="download_base", - callback=normalize_to_url, nargs=1, type="string", - help=("Specify a URL or directory for downloading " - "zc.buildout and either Setuptools or Distribute. " - "Defaults to PyPI.")) -parser.add_option("--eggs", - help=("Specify a directory for storing eggs. Defaults to " - "a temporary directory that is deleted when the " - "bootstrap script completes.")) +parser.add_option("-v", "--version", help="use a specific zc.buildout version") + parser.add_option("-t", "--accept-buildout-test-releases", dest='accept_buildout_test_releases', action="store_true", default=False, @@ -130,49 +47,38 @@ parser.add_option("-t", "--accept-buildout-test-releases", "extensions for you. If you use this flag, " "bootstrap and buildout will get the newest releases " "even if they are alphas or betas.")) -parser.add_option("-c", None, action="store", dest="config_file", +parser.add_option("-c", "--config-file", help=("Specify the path to the buildout configuration " "file to be used.")) +parser.add_option("-f", "--find-links", + help=("Specify a URL to search for buildout releases")) -options, args = parser.parse_args() - -# if -c was provided, we push it back into args for buildout's main function -if options.config_file is not None: - args += ['-c', options.config_file] - -if options.eggs: - eggs_dir = os.path.abspath(os.path.expanduser(options.eggs)) -else: - eggs_dir = tempfile.mkdtemp() -if options.setup_source is None: - if options.use_distribute: - options.setup_source = distribute_source - else: - options.setup_source = setuptools_source +options, args = parser.parse_args() -if options.accept_buildout_test_releases: - args.append('buildout:accept-buildout-test-releases=true') -args.append('bootstrap') +###################################################################### +# load/install distribute +to_reload = False try: - import pkg_resources - import setuptools # A flag. Sometimes pkg_resources is installed alone. + import pkg_resources, setuptools if not hasattr(pkg_resources, '_distribute'): + to_reload = True raise ImportError except ImportError: - ez_code = urllib2.urlopen( - options.setup_source).read().replace('\r\n', '\n') ez = {} - exec ez_code in ez - setup_args = dict(to_dir=eggs_dir, download_delay=0) - if options.download_base: - setup_args['download_base'] = options.download_base - if options.use_distribute: - setup_args['no_fake'] = True + + try: + from urllib.request import urlopen + except ImportError: + from urllib2 import urlopen + + exec(urlopen('http://python-distribute.org/distribute_setup.py').read(), ez) + setup_args = dict(to_dir=tmpeggs, download_delay=0, no_fake=True) ez['use_setuptools'](**setup_args) - if 'pkg_resources' in sys.modules: - reload(sys.modules['pkg_resources']) + + if to_reload: + reload(pkg_resources) import pkg_resources # This does not (always?) update the default working set. We will # do it. @@ -180,31 +86,26 @@ except ImportError: if path not in pkg_resources.working_set.entries: pkg_resources.working_set.add_entry(path) -cmd = [quote(sys.executable), - '-c', - quote('from setuptools.command.easy_install import main; main()'), - '-mqNxd', - quote(eggs_dir)] +###################################################################### +# Install buildout + +ws = pkg_resources.working_set -if not has_broken_dash_S: - cmd.insert(1, '-S') +cmd = [sys.executable, '-c', + 'from setuptools.command.easy_install import main; main()', + '-mZqNxd', tmpeggs] -find_links = options.download_base -if not find_links: - find_links = os.environ.get('bootstrap-testing-find-links') +find_links = os.environ.get( + 'bootstrap-testing-find-links', + options.find_links or + ('http://downloads.buildout.org/' + if options.accept_buildout_test_releases else None) + ) if find_links: - cmd.extend(['-f', quote(find_links)]) + cmd.extend(['-f', find_links]) -if options.use_distribute: - setup_requirement = 'distribute' -else: - setup_requirement = 'setuptools' -ws = pkg_resources.working_set -setup_requirement_path = ws.find( - pkg_resources.Requirement.parse(setup_requirement)).location -env = dict( - os.environ, - PYTHONPATH=setup_requirement_path) +distribute_path = ws.find( + pkg_resources.Requirement.parse('distribute')).location requirement = 'zc.buildout' version = options.version @@ -212,14 +113,13 @@ if version is None and not options.accept_buildout_test_releases: # Figure out the most recent final version of zc.buildout. import setuptools.package_index _final_parts = '*final-', '*final' - def _final_version(parsed_version): for part in parsed_version: if (part[:1] == '*') and (part not in _final_parts): return False return True index = setuptools.package_index.PackageIndex( - search_path=[setup_requirement_path]) + search_path=[distribute_path]) if find_links: index.add_find_links((find_links,)) req = pkg_resources.Requirement.parse(requirement) @@ -241,22 +141,25 @@ if version: requirement = '=='.join((requirement, version)) cmd.append(requirement) -if is_jython: - import subprocess - exitcode = subprocess.Popen(cmd, env=env).wait() -else: # Windows prefers this, apparently; otherwise we would prefer subprocess - exitcode = os.spawnle(*([os.P_WAIT, sys.executable] + cmd + [env])) -if exitcode != 0: - sys.stdout.flush() - sys.stderr.flush() - print ("An error occurred when trying to install zc.buildout. " - "Look above this message for any errors that " - "were output by easy_install.") - sys.exit(exitcode) +import subprocess +if subprocess.call(cmd, env=dict(os.environ, PYTHONPATH=distribute_path)) != 0: + raise Exception( + "Failed to execute command:\n%s", + repr(cmd)[1:-1]) -ws.add_entry(eggs_dir) +###################################################################### +# Import and run buildout + +ws.add_entry(tmpeggs) ws.require(requirement) import zc.buildout.buildout + +if not [a for a in args if '=' not in a]: + args.append('bootstrap') + +# if -c was provided, we push it back into args for buildout' main function +if options.config_file is not None: + args[0:0] = ['-c', options.config_file] + zc.buildout.buildout.main(args) -if not options.eggs: # clean up temporary egg directory - shutil.rmtree(eggs_dir) +shutil.rmtree(tmpeggs) diff --git a/buildout.cfg b/buildout.cfg index e1ad958be5bd5d680d6cdca9966a384a07e54018..481ab7f5b15a43c13c42013779780c1d23275180 100644 --- a/buildout.cfg +++ b/buildout.cfg @@ -5,30 +5,19 @@ ; This is the configuration file for buildout. [buildout] -parts = external python +parts = scripts newest = false develop = . ; required packages: sphinx (to generate the documentation), bob, and our package. -eggs = sphinx - bob - bob.example.faceverify +eggs = bob.example.faceverify ; This points to the bob databases that are installed locally at Idiap ; TODO: remove this as soon as the databases are published at pypi find-links = http://www.idiap.ch/software/bob/packages/xbob/nightlies/last -; This defines the installation directory of Bob. -; The current setup should work fine for use at Idiap. -; If you are not at Idiap, and bob is not installed in the default location, -; please modify the egg-directories accordingly. -; TODO: Change this directory back to the stable version of bob, when appropriate -[external] -recipe = xbob.buildout:external -egg-directories = /idiap/group/torch5spro/nightlies/last/install/linux-x86_64-release/lib +[bob.example.faceverify] +recipe = xbob.buildout:develop - -[python] -recipe = zc.recipe.egg -interpreter = python -eggs = ${buildout:eggs} +[scripts] +recipe = xbob.buildout:scripts diff --git a/faceverify/dct_ubm.py b/faceverify/dct_ubm.py index 823b9a50b81311f0b5baf17f81e64c96702a2710..48a2ed037dde74e44dac777f857e0ab1dc821b4c 100644 --- a/faceverify/dct_ubm.py +++ b/faceverify/dct_ubm.py @@ -16,12 +16,12 @@ ATNT_IMAGE_EXTENSION = ".pgm" def load_images(db, group = None, purpose = None, client_id = None): """Reads the images for the given group and the given client id from the given database""" # get the file names from the database - file_names = db.files(groups = group, purposes = purpose, model_ids = client_id, directory = ATNT_IMAGE_DIRECTORY, extension = ATNT_IMAGE_EXTENSION) + files = db.objects(groups = group, purposes = purpose) # iterate through the list of file names images = {} - for key, image_name in file_names.iteritems(): + for k in files: # load image and linearize it into a vector - images[key] = bob.io.load(image_name).astype(numpy.float64) + images[k.id] = bob.io.load(k.make_path(ATNT_IMAGE_DIRECTORY, ATNT_IMAGE_EXTENSION)).astype(numpy.float64) return images diff --git a/faceverify/eigenface.py b/faceverify/eigenface.py index c42a5d0aa0d15be93bc0211bf224b9428d3e5ffa..61633bf7efe39266784f9ce1f80b2663f2611cf2 100644 --- a/faceverify/eigenface.py +++ b/faceverify/eigenface.py @@ -16,12 +16,12 @@ ATNT_IMAGE_EXTENSION = ".pgm" def load_images(db, group = None, purpose = None): """Reads the images for the given group and the given purpose from the given database""" # get the file names from the database - file_names = db.files(groups = group, purposes = purpose, directory = ATNT_IMAGE_DIRECTORY, extension = ATNT_IMAGE_EXTENSION) + files = db.objects(groups = group, purposes = purpose) # iterate through the list of file names images = {} - for key, image_name in file_names.iteritems(): + for k in files: # load image and linearize it into a vector - images[key] = bob.io.load(image_name).astype(numpy.float64) + images[k.id] = bob.io.load(k.make_path(ATNT_IMAGE_DIRECTORY, ATNT_IMAGE_EXTENSION)).astype(numpy.float64) return images diff --git a/faceverify/gabor_phase.py b/faceverify/gabor_phase.py index 3609709fbedb3d41dce20d91edd219922e7c8f80..732d5991ae5ab10e3f46db8981c83a5a55a1fbf2 100644 --- a/faceverify/gabor_phase.py +++ b/faceverify/gabor_phase.py @@ -16,12 +16,12 @@ ATNT_IMAGE_EXTENSION = ".pgm" def load_images(db, group = None, purpose = None): """Reads the images for the given group and the given purpose from the given database""" # get the file names from the database - file_names = db.files(groups = group, purposes = purpose, directory = ATNT_IMAGE_DIRECTORY, extension = ATNT_IMAGE_EXTENSION) + files = db.objects(groups = group, purposes = purpose) # iterate through the list of file names images = {} - for key, image_name in file_names.iteritems(): + for k in files: # load image and linearize it into a vector - images[key] = bob.io.load(image_name).astype(numpy.float64) + images[k.id] = bob.io.load(k.make_path(ATNT_IMAGE_DIRECTORY, ATNT_IMAGE_EXTENSION)).astype(numpy.float64) return images diff --git a/setup.py b/setup.py index f85c72079038ca3ad26ec9c81926eb49dc32ac66..069825452653a1666e0d68de346cafce92e89426 100644 --- a/setup.py +++ b/setup.py @@ -28,7 +28,7 @@ setup( # This is the basic information about your project. Modify all this # information before releasing code publicly. name='bob.example.faceverify', - version='0.1.3', + version='0.1.4', description='Example for using Bob to create face verification systems', url='http://pypi.python.org/pypi/bob.example.faceverify', license='GPLv3', @@ -49,7 +49,7 @@ setup( # TODO: Add a version number requirement to bob, when ready install_requires=[ "sphinx", # to generate the documentation - "bob >= 1.1.0a0", # base signal proc./machine learning library + "bob >= 1.1.0", # base signal proc./machine learning library "xbob.db.atnt", # the AT&T (ORL) database of images ],