Commit 8d88e03c authored by Sushil BHATTACHARJEE's avatar Sushil BHATTACHARJEE

Merge branch 'optimizations' into 'master'

Optimizations See merge request !6
parents a55a13ca 7b263619
Pipeline #11313 canceled with stages
in 8 minutes 4 seconds
This diff is collapsed.
include README.rst bootstrap-buildout.py buildout.cfg develop.cfg requirements.txt version.txt
recursive-include doc *.py *.rst *.png *.ico
recursive-include bob/ip/qualitymeasure/data *.mp4 *.jpg *.h5 *.hdf5
recursive-include bob/ip/qualitymeasure/data *.mp4 *.jpg *.h5 *.hdf5 *.ppm
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
from ._library import remove_highlights
from .galbally_iqm_features import compute_quality_features
from .msu_iqa_features import compute_msu_iqa_features
def get_config():
"""
Returns a string containing the configuration information.
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
// include directly and indirectly dependent libraries
#ifdef NO_IMPORT_ARRAY
#undef NO_IMPORT_ARRAY
#endif
#include <bob.blitz/cppapi.h>
#include <bob.blitz/cleanup.h>
#include <bob.extension/documentation.h>
// declare C++ function
void remove_highlights( blitz::Array<float ,3> &img,
blitz::Array<float ,3> &diff,
blitz::Array<float ,3> &sfi,
blitz::Array<float ,3> &residue,
float epsilon,
bool skip_diffuse,
bool check_nan_inf);
// use the documentation classes to document the function
static bob::extension::FunctionDoc remove_highlights_doc = bob::extension::FunctionDoc(
"remove_highlights",
"This function implements a specular highlight removal algorithm.",
"This function implements a specular highlight removal algorithm which, by \
using an iterative process, separates the specular component from the \
diffuse component of the picture. It returns a color incorect specular free \
image, the diffuse component and the specular residue, respectively. It is \
based on the original code by Robby T. Tan \
reference: \
separating reflection components of textured surfaces using a single image \
by Robby T. Tan, Katsushi Ikeuchi, \
IEEE Transactions on Pattern Analysis and Machine Intelligence (PAMI), \
27(2), pp.179-193, February, 2005"
)
.add_prototype("image", "specular_free_image, diffuse_image, specular_residue, epsilon")
.add_parameter("image", "array_like (3D, float32)", "The image to process")
.add_return("specular_free_image", "array_like (3D, float32)", "Specular free image with altered colors.")
.add_return("diffuse_image", "array_like (3D, float32)", "Diffuse component image, free of specularity.")
.add_return("specular_residue", "array_like (3D, float32)", "Specular residue of the image.")
.add_return("epsilon", "float32", "Parameter that specifies the number of iterations.")
;
// declare the function
static PyObject* PyRemoveHighlights(PyObject*, PyObject* args, PyObject* kwargs) {
BOB_TRY
static const char* const_kwlist[] =
{"array", "startEps", "skip_diffuse", "check_nan_inf", 0};
static char** kwlist = const_cast<char**>(const_kwlist);
PyBlitzArrayObject* array;
double epsilon = 0.5f;
bool skip_diffuse = false;
bool check_nan_inf = false;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|dii", kwlist,
&PyBlitzArray_Converter, &array,
&epsilon, &skip_diffuse, &check_nan_inf))
return 0;
// check that the array has the expected properties
if (array->type_num != NPY_FLOAT32|| array->ndim != 3){
PyErr_Format(PyExc_TypeError,
"remove_highlights : Only 3D arrays of type float32 are allowed");
return 0;
}
// extract the actual blitz array from the Python type
blitz::Array<float ,3> img = *PyBlitzArrayCxx_AsBlitz<float , 3>(array);
// results
int dim_x = img.shape()[2];
int dim_y = img.shape()[1];
blitz::Array<float ,3> diffuse_img(3, dim_y, dim_x);
blitz::Array<float ,3> speckle_free_img(3, dim_y, dim_x);
blitz::Array<float ,3> speckle_img(3, dim_y, dim_x);
diffuse_img = 0;
speckle_free_img = 0;
speckle_img = 0;
// call the C++ function
remove_highlights(img, diffuse_img, speckle_free_img, speckle_img,
(float)epsilon, skip_diffuse, check_nan_inf);
// convert the blitz array back to numpy and return it
PyObject *ret_tuple = PyTuple_New(3);
PyTuple_SetItem(ret_tuple, 0, PyBlitzArrayCxx_AsNumpy(speckle_free_img));
PyTuple_SetItem(ret_tuple, 1, PyBlitzArrayCxx_AsNumpy(diffuse_img));
PyTuple_SetItem(ret_tuple, 2, PyBlitzArrayCxx_AsNumpy(speckle_img));
return ret_tuple;
// handle exceptions that occurred in this function
BOB_CATCH_FUNCTION("remove_highlights", 0)
}
//////////////////////////////////////////////////////////////////////////
/////// Python module declaration ////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// module-wide methods
static PyMethodDef module_methods[] = {
{
"remove_highlights",
(PyCFunction)PyRemoveHighlights,
METH_VARARGS|METH_KEYWORDS,
remove_highlights_doc.doc()
},
{NULL} // Sentinel
};
// module documentation
PyDoc_STRVAR(module_docstr, "Tan Specular Highlights");
// module definition
#if PY_VERSION_HEX >= 0x03000000
static PyModuleDef module_definition = {
PyModuleDef_HEAD_INIT,
BOB_EXT_MODULE_NAME,
module_docstr,
-1,
module_methods,
0, 0, 0, 0
};
#endif
// create the module
static PyObject* create_module (void) {
# if PY_VERSION_HEX >= 0x03000000
PyObject* module = PyModule_Create(&module_definition);
auto module_ = make_xsafe(module);
const char* ret = "O";
# else
PyObject* module = Py_InitModule3(BOB_EXT_MODULE_NAME, module_methods, module_docstr);
const char* ret = "N";
# endif
if (!module) return 0;
if (PyModule_AddStringConstant(module, "__version__", BOB_EXT_MODULE_VERSION) < 0) return 0;
/* imports bob.blitz C-API + dependencies */
if (import_bob_blitz() < 0) return 0;
return Py_BuildValue(ret, module);
}
PyMODINIT_FUNC BOB_EXT_ENTRY_NAME (void) {
# if PY_VERSION_HEX >= 0x03000000
return
# endif
create_module();
}
......@@ -9,10 +9,10 @@ import scipy.signal as ssg
import bob.ip.base
import bob.ip.color
from . import galbally_iqm_features as iqm
from . import tan_specular_highlights as tsh
''' Utility functions '''
from . import remove_highlights
''' Utility functions '''
def matlab_rgb2hsv(rgbImage):
# first normalize the range of values to 0-1
......@@ -26,7 +26,7 @@ def matlab_rgb2hsv(rgbImage):
h = hsv[0, :, :]
s = hsv[1, :, :]
v = hsv[2, :, :]
#
return (h, s, v)
......@@ -155,8 +155,18 @@ def compute_iqa_specularity_features(rgbImage, startEps=0.05):
"""
# separate the specular and diffuse components of input color image.
speckleFreeImg, diffuseImg, speckleImg = tsh.remove_highlights(
rgbImage.astype(float), startEps, verboseFlag=False)
# original python version
#speckleFreeImg, diffuseImg, speckleImg = tsh.remove_highlights(
# rgbImage.astype(float), startEps, verboseFlag=False)
speckleFreeImg, diffuseImg, speckleImg = remove_highlights(
rgbImage.astype(np.float32), startEps)
speckleImg[np.where(np.isinf(speckleImg))] = 0
speckleImg[np.where(np.isnan(speckleImg))] = 0
speckleImg[np.where(speckleImg < 0)] = 0
speckleImg[np.where(speckleImg > 255)] = 255
# speckleImg contains the specular-component
if len(speckleImg.shape) == 3:
......@@ -302,7 +312,6 @@ def marzilianoBlur(image):
return blurMetric
def calmoment(channel, regionMask=None):
""" returns the first 3 statistical moments (mean, standard-dev., skewness)
and 2 other first-order statistical measures of input image
......
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
import sys
import argparse
import time
import bob.io.base
import bob.io.image
import numpy as np
from bob.ip.qualitymeasure import remove_highlights
def main(command_line_parameters=None):
"""Remove the specular component of the input image and write result to
a file.
"""
argParser = argparse.ArgumentParser(
description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter)
argParser.add_argument(
'-i',
'--input',
dest='inpImg',
default=None,
help='filename of image to be processed (including complete path). ')
argParser.add_argument(
'-o',
'--output',
dest='outImg',
default=None,
help='filename of specular free image.')
argParser.add_argument(
'-r',
'--residue',
dest='resImg',
default=None,
help='filename of specular residue image.')
argParser.add_argument(
'-e',
'--epsilon',
dest='epsilon',
default=0.5,
help='value of epsilon parameter.')
args = argParser.parse_args(command_line_parameters)
if not args.inpImg:
argParser.error('Specify parameter --input')
if not args.outImg:
argParser.error('Specify parameter --output')
# 1. open input image
print("Opening file: %s" % args.inpImg)
img = bob.io.image.load(args.inpImg)
# 2. compute
print("Extracting diffuse component...")
sfi, diff, residue = remove_highlights(img.astype(np.float32), float(args.epsilon))
# 1. save output image
print("Saving output file: %s" % args.outImg)
bob.io.base.save(diff.astype('uint8'), args.outImg)
if args.resImg:
print("Saving residue file: %s" % args.resImg)
bob.io.base.save(residue.astype('uint8'), args.resImg)
print('Done')
if __name__ == '__main__':
main(sys.argv[1:])
This diff is collapsed.
This diff is collapsed.
......@@ -18,6 +18,9 @@ import bob.ip.color
from . import galbally_iqm_features as iqm
from . import msu_iqa_features as iqa
from bob.io import image
from . import remove_highlights
REF_VIDEO_FILE = 'real_client001_android_SD_scene01.mp4'
REF_FEATURE_FILE = 'real_client001_android_SD_scene01_ref_feats.h5'
......@@ -106,3 +109,25 @@ def test_msu_feat_extr():
# test: compare feature-values in bobfset[] with those loaded from hdf5 file
nose.tools.assert_true((msufset == msu_ref_features).all())
# test if the specular highlights algorithm (remove_highlights.cpp::remove_highlights)
# performs exactly like the original code from which it was mostly copied.
def test_remove_highlights_integrity():
# open pictures
img1 = image.load(F('old_man.ppm'))
img2 = image.load(F('toys.ppm'))
# compute
sfi1, diff1, residue1 = remove_highlights(img1.astype(np.float32), 0.5)
sfi2, diff2, residue2 = remove_highlights(img2.astype(np.float32), 0.5)
diff1_u8 = diff1.astype('uint8')
diff2_u8 = diff2.astype('uint8')
# reference files
ref1 = image.load(F('old_man_diffuse.ppm'))
ref2 = image.load(F('toys_diffuse.ppm'))
# test: compare results
assert (diff1_u8 == ref1).all()
assert (diff2_u8 == ref2).all()
/**
* @author Andre Anjos <andre.anjos@idiap.ch>
* @date Thu 7 Nov 13:50:16 2013
*
* @brief Binds configuration information available from bob
*/
#define BOB_IMPORT_VERSION
#include <bob.blitz/config.h>
#include <bob.blitz/cleanup.h>
// builds the dictionary of versions
static PyObject* build_version_dictionary() {
PyObject* retval = PyDict_New();
if (!retval) return 0;
auto retval_ = make_safe(retval);
if (!dict_steal(retval, "Blitz++", blitz_version())) return 0;
if (!dict_steal(retval, "Boost", boost_version())) return 0;
if (!dict_steal(retval, "Compiler", compiler_version())) return 0;
if (!dict_steal(retval, "Python", python_version())) return 0;
if (!dict_steal(retval, "NumPy", numpy_version())) return 0;
if (!dict_steal(retval, "bob.blitz", bob_blitz_version())) return 0;
return Py_BuildValue("O", retval);
}
static PyMethodDef module_methods[] = {
{0} /* Sentinel */
};
PyDoc_STRVAR(module_docstr,
"Information about software used to compile the C++ Bob API"
);
#if PY_VERSION_HEX >= 0x03000000
static PyModuleDef module_definition = {
PyModuleDef_HEAD_INIT,
BOB_EXT_MODULE_NAME,
module_docstr,
-1,
module_methods,
0, 0, 0, 0
};
#endif
static PyObject* create_module (void) {
# if PY_VERSION_HEX >= 0x03000000
PyObject* module = PyModule_Create(&module_definition);
auto module_ = make_xsafe(module);
const char* ret = "O";
# else
PyObject* module = Py_InitModule3(BOB_EXT_MODULE_NAME, module_methods, module_docstr);
const char* ret = "N";
# endif
if (!module) return 0;
/* register version numbers and constants */
if (PyModule_AddStringConstant(module, "module", BOB_EXT_MODULE_VERSION) < 0) return 0;
if (PyModule_AddObject(module, "externals", build_version_dictionary()) < 0) return 0;
return Py_BuildValue(ret, module);
}
PyMODINIT_FUNC BOB_EXT_ENTRY_NAME (void) {
# if PY_VERSION_HEX >= 0x03000000
return
# endif
create_module();
}
......@@ -3,11 +3,18 @@
# Sushil Bhattacharjee <sushil.bhattacharjee@idiap.ch>
# Tue 7 Mar 2017 11:26:26 CET
setup_packages = ['bob.extension', 'bob.blitz']
bob_packages = []
from setuptools import setup, find_packages, dist
dist.Distribution(dict(setup_requires=['bob.extension']))
dist.Distribution(dict(setup_requires = setup_packages + bob_packages))
# import the Extension class and the build_ext function from bob.blitz
from bob.blitz.extension import Extension, build_ext
# load the requirements.txt for additional requirements
from bob.extension.utils import load_requirements
requirements = load_requirements()
requirements = setup_packages + bob_packages + load_requirements()
version = open("version.txt").read().rstrip()
......@@ -17,12 +24,12 @@ setup(
version=version,
description='Image-quality feature-extractors for PAD applications',
url='http://gitlab.idiap.ch/bob/bob.ip.qualitymeasure',
license='BSD',
license='GPLv3',
author='Sushil Bhattacharjee',
author_email='sushil.bhattacharjee@idiap.ch',
keywords='bob, image-quality, face',
maintainer="Sushil Bhattacharjee",
maintainer_email="sbhatta@idiap.ch",
maintainer="David Geissbuhler",
maintainer_email="david.geissbuhler@idiap.ch",
long_description=open('README.rst').read(),
# This line is required for any distutils based packaging.
......@@ -31,10 +38,47 @@ setup(
install_requires = requirements,
# We are defining two extensions here. Each of them will be compiled
# independently into a separate .so file.
ext_modules = [
# The first extension defines the version of this package and all C++-dependencies.
Extension("bob.ip.qualitymeasure.version",
# list of files compiled into this extension
[
"bob/ip/qualitymeasure/version.cpp",
],
# additional parameters, see Extension documentation
version = version,
bob_packages = bob_packages,
),
# The second extension contains the actual C++ code and the Python bindings
Extension("bob.ip.qualitymeasure._library",
# list of files compiled into this extension
[
# the pure C++ code
"bob/ip/qualitymeasure/tan_specular_highlights.cpp",
# the Python bindings
"bob/ip/qualitymeasure/main.cpp",
],
# additional parameters, see Extension documentation
version = version,
bob_packages = bob_packages,
),
],
# Important! We need to tell setuptools that we want the extension to be
# compiled with our build_ext function!
cmdclass = {
'build_ext': build_ext,
},
entry_points={
# scripts should be declared using this entry:
'console_scripts': [
'compute_qualityfeatures.py = bob.ip.qualitymeasure.script.compute_qualitymeasures:main',
'remove_highlights.py = bob.ip.qualitymeasure.script.remove_highlights:main',
],
},
......@@ -45,7 +89,7 @@ setup(
'Framework :: Bob',
'Development Status :: 4 - Beta',
'Intended Audience :: Developers',
'License :: OSI Approved :: BSD License',
'License :: OSI Approved :: GPL General Public Licence (GPLv3)',
'Natural Language :: English',
'Programming Language :: Python',
'Programming Language :: Python :: 3',
......
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