14 Commits

Author SHA1 Message Date
Matias De lellis
d3b91453bb Dont install useless php extension 2020-04-24 11:57:07 -03:00
Matias De lellis
3e050a4772 Improve travis 2020-04-24 11:40:40 -03:00
Matias De lellis
16d19188c3 Improve travis 2020-04-24 11:10:33 -03:00
Matias De lellis
9d351afd07 Test on tavis. 2020-04-24 10:41:21 -03:00
Matias De lellis
ca007e400a Append more information to phpinfo()
If you think it works slow, make sure it is compiled with any of these instructions

> pdlib
>
> PDlib support => enabled
> Pdlib Version => 1.0.2
> DLIB_USE_CUDA => false
> DLIB_USE_BLAS => true
> DLIB_USE_LAPACK => true
> USE_AVX_INSTRUCTIONS => false
> USE_AVX2_INSTRUCTIONS => false
> USE_NEON_INSTRUCTIONS => false
> USE_SSE2_INSTRUCTIONS => true
> USE_SSE4_INSTRUCTIONS => false
2020-04-19 20:27:51 -03:00
Matias De lellis
2b06ea45c4 Improve messages when configure build. 2020-04-19 19:26:22 -03:00
matiasdelellis
c9e1015197 Merge pull request #2 from matiasdelellis/dlib_length
Dlib length
2020-04-14 20:05:40 -03:00
Matias De lellis
76da4d9b84 Multiply directly instead of using pow ($number, 2);
This small optimization allows us to improve from:

 OLD php: 0.012100038051605 Sec.
 New native: 0.0096198790073395 Sec.

(This is already 20 percent faster)

..to:
 OLD php: 0.012276937961578 Sec.
 New native: 0.0022540950775146 Sec.

What is 80 percent faster than our PHP class.
2020-04-14 10:45:13 -03:00
Matias De lellis
75adc6f801 Use references as an attempt to optimize. 2020-04-14 10:26:26 -03:00
Matias De lellis
4a2e4ff112 Implement dlib_vector_length to calculate the euclidean distance of the vectors
It not use the 'length' native versions of dlib, due I have to convert the
array to the vector, which will take the same time, and then I will use the
native method.
2020-04-14 09:45:16 -03:00
matiasdelellis
78819eb815 More description 2020-04-13 18:54:24 -03:00
matiasdelellis
e69df35435 Explain why the fork 2020-04-13 18:39:48 -03:00
matiasdelellis
a5e7cf3535 Move Instalation doc to wiki 2020-04-13 18:33:54 -03:00
matiasdelellis
80f8101e15 Merge pull request #1 from matiasdelellis/improve-hog
Improve hog
2020-04-13 18:23:59 -03:00
22 changed files with 179 additions and 225 deletions

View File

@@ -1,71 +1,15 @@
# PDlib - A PHP extension for Dlib
# PDlib - A PHP extension for [Dlib](https://github.com/davisking/dlib)
## Requirements
- Dlib 19.13+
- PHP 7.0+
- C++11
- libx11-dev (on Ubuntu: `sudo apt-get install libx11-dev`)
Dlib is a modern C++ toolkit containing machine learning algorithms and tools for creating complex software in C++ to solve real world problems. See http://dlib.net for the main project documentation and API reference.
## Recommended
- BLAS library
If no BLAS library found - dlib's built in BLAS will be used.
However, if you install an optimized BLAS such as OpenBLAS or the Intel MKL your code
will run faster. On Ubuntu you can install OpenBLAS by executing:
`sudo apt-get install libopenblas-dev liblapack-dev`
PDlib is a PHP extension that implements the PHP binging for the dlib library, that now is used in the Nextcloud [FaceRecognition](https://github.com/matiasdelellis/facerecognition) application.
## Dependencies
### Dlib
Install Dlib as shared library
```bash
git clone https://github.com/davisking/dlib.git
cd dlib/dlib
mkdir build
cd build
cmake -DBUILD_SHARED_LIBS=ON ..
make
sudo make install
```
## Note
This is a fork of the [original pdlib extension](https://github.com/goodspb/pdlib), which we will use temporarily for the Nextcloud [FaceRecognition](https://github.com/matiasdelellis/facerecognition) application while the original author is not responding.
## Installation
```bash
git clone https://github.com/goodspb/pdlib.git
cd pdlib
phpize
./configure --enable-debug
# you may need to indicate the dlib install location
# PKG_CONFIG_PATH=/usr/local/lib/pkgconfig ./configure --enable-debug
make
sudo make install
```
### Configure PHP installation
```bash
vim youpath/php.ini
```
Append the content below into `php.ini`
```
[pdlib]
extension="pdlib.so"
```
## Tests
For tests, you will need to have bz2 extension installed. On Ubuntu, it boils to:
```bash
sudo apt-get install php-bz2
```
After you successfully compiled everything, just run:
```bash
make test
```
Read [Installation](https://github.com/matiasdelellis/pdlib/wiki/Installation) documentation on the wiki for details.
## Usage

105
config.m4
View File

@@ -7,62 +7,65 @@ if test -z "$PHP_DEBUG"; then
fi
PHP_ARG_WITH(pdlib, for pdlib support,
dnl Make sure that the comment is aligned:
[ --with-pdlib Include pdlib support])
if test "$PHP_PDLIB" != "no"; then
PHP_REQUIRE_CXX()
PHP_ADD_LIBRARY(stdc++, 1, PDLIB_SHARED_LIBADD)
PHP_SUBST(PDLIB_SHARED_LIBADD)
dnl using C++11
CXXFLAGS="-std=c++11"
PHP_REQUIRE_CXX()
PHP_ADD_LIBRARY(stdc++, 1, PDLIB_SHARED_LIBADD)
PHP_SUBST(PDLIB_SHARED_LIBADD)
pdlib_src_files="pdlib.cc \
src/chinese_whispers.cc \
src/face_detection.cc \
src/face_landmark_detection.cc \
src/face_recognition.cc \
src/cnn_face_detection.cc
src/vector.cc"
PHP_PDLIB_SOURCES="\
pdlib.cc \
src/chinese_whispers.cc \
src/face_detection.cc \
src/face_landmark_detection.cc \
src/face_recognition.cc \
src/cnn_face_detection.cc \
src/vector.cc \
"
AC_MSG_CHECKING(for pkg-config)
AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
if test -x "$PKG_CONFIG"; then
AC_MSG_RESULT(found)
AC_MSG_CHECKING(for dlib-1)
if $PKG_CONFIG --exists dlib-1; then
if $PKG_CONFIG dlib-1 --atleast-version 19.00; then
LIBDLIB_CFLAGS=`$PKG_CONFIG dlib-1 --cflags`
LIBDLIB_LIBDIR=`$PKG_CONFIG dlib-1 --libs`
LIBDLIB_VERSON=`$PKG_CONFIG dlib-1 --modversion`
AC_MSG_RESULT(from pkgconfig: dlib version $LIBDLIB_VERSON)
else
AC_MSG_ERROR(system dlib is too old: version 19.00 required)
fi
else
AC_MSG_ERROR(dlib-1 not found)
fi
else
AC_MSG_ERROR(pkg-config not found)
fi
PHP_EVAL_LIBLINE($LIBDLIB_LIBDIR, PDLIB_SHARED_LIBADD)
PHP_EVAL_INCLINE($LIBDLIB_CFLAGS)
dnl using C++11
PHP_NEW_EXTENSION(pdlib, $pdlib_src_files, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1 -std=c++11, cxx)
AC_MSG_CHECKING(for pkg-config)
if test ! -f "$PKG_CONFIG"; then
PKG_CONFIG=`which pkg-config`
fi
if test -f "$PKG_CONFIG"; then
AC_MSG_RESULT(found)
AC_MSG_CHECKING(for dlib-1)
if $PKG_CONFIG --exists dlib-1; then
if $PKG_CONFIG dlib-1 --atleast-version 19.00; then
LIBDLIB_CFLAGS=`$PKG_CONFIG dlib-1 --cflags`
LIBDLIB_LIBDIR=`$PKG_CONFIG dlib-1 --libs`
LIBDLIB_VERSON=`$PKG_CONFIG dlib-1 --modversion`
AC_MSG_RESULT(from pkgconfig: dlib version $LIBDLIB_VERSON)
else
AC_MSG_ERROR(system dlib is too old: version 19.00 required)
fi
else
AC_MSG_ERROR(dlib-1 not found)
fi
else
AC_MSG_ERROR(pkg-config not found)
fi
PHP_EVAL_LIBLINE($LIBDLIB_LIBDIR, PDLIB_SHARED_LIBADD)
PHP_EVAL_INCLINE($LIBDLIB_CFLAGS)
PHP_NEW_EXTENSION(pdlib, $PHP_PDLIB_SOURCES, $ext_shared, , -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)
AC_CONFIG_COMMANDS_POST([
echo ""
echo "Build configuration for PDlib v1.0.2 done correctly."
echo ""
echo " dlib version: $LIBDLIB_VERSON"
echo ""
echo " CXXFLAGS : $CXXFLAGS"
echo " LDFLAGS : $LDFLAGS"
echo " LIBDIR: : $LIBDLIB_LIBDIR"
echo " LIBADD: : $PDLIB_SHARED_LIBADD"
echo ""
echo "Please submit bug reports at:"
echo " https://github.com/goodspb/pdlib/issues"
echo ""
echo ""
echo "Build configuration for PDlib v1.0.2 done correctly."
echo ""
echo " CFLAGS : $CFLAGS"
echo " LDFLAGS : $LDFLAGS"
echo " LIBDIR: : $LIBDLIB_LIBDIR"
echo " LIBADD: : $PDLIB_SHARED_LIBADD"
echo " CFLAGS: : $LIBDLIB_CFLAGS"
echo ""
echo "Please submit bug reports at:"
echo " https://github.com/matiasdelellis/pdlib/issues"
echo ""
])

View File

@@ -22,11 +22,13 @@ extern "C" {
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
}
#include <dlib/simd/simd_check.h>
#include "php_pdlib.h"
#include "src/chinese_whispers.h"
#include "src/face_detection.h"
@@ -35,12 +37,13 @@ extern "C" {
#include "src/face_landmark_detection.h"
#include "src/vector.h"
#include <dlib/revision.h>
/* If you declare any globals in php_pdlib.h uncomment this:
ZEND_DECLARE_MODULE_GLOBALS(pdlib)
*/
/* True global resources - no need for thread safety here */
static int le_pdlib;
static zend_class_entry *cnn_face_detection_ce = nullptr;
static zend_object_handlers cnn_face_detection_obj_handlers;
@@ -60,6 +63,13 @@ PHP_INI_END()
*/
/* }}} */
/* }}} */
/* The previous line is meant for vim and emacs, so it can correctly fold and
unfold functions in source code. See the corresponding marks just before
function definition, where the functions purpose is also documented. Please
follow this convention for the convenience of others editing your code.
*/
/* {{{ php_pdlib_init_globals
*/
@@ -78,10 +88,10 @@ const zend_function_entry cnn_face_detection_class_methods[] = {
PHP_FE_END
};
zend_object* php_cnn_face_detection_new(zend_class_entry *class_type)
zend_object* php_cnn_face_detection_new(zend_class_entry *class_type TSRMLS_DC)
{
cnn_face_detection *cfd = (cnn_face_detection*)ecalloc(1, sizeof(cnn_face_detection));
zend_object_std_init(&cfd->std, class_type);
zend_object_std_init(&cfd->std, class_type TSRMLS_CC);
object_properties_init(&cfd->std, class_type);
cfd->std.handlers = &cnn_face_detection_obj_handlers; //zend_get_std_object_handlers();
@@ -101,10 +111,10 @@ const zend_function_entry face_landmark_detection_class_methods[] = {
PHP_FE_END
};
zend_object* php_face_landmark_detection_new(zend_class_entry *class_type)
zend_object* php_face_landmark_detection_new(zend_class_entry *class_type TSRMLS_DC)
{
face_landmark_detection *fld = (face_landmark_detection*)ecalloc(1, sizeof(face_landmark_detection));
zend_object_std_init(&fld->std, class_type);
zend_object_std_init(&fld->std, class_type TSRMLS_CC);
object_properties_init(&fld->std, class_type);
fld->std.handlers = &face_landmark_detection_obj_handlers;
@@ -124,10 +134,10 @@ const zend_function_entry face_recognition_class_methods[] = {
PHP_FE_END
};
zend_object* php_face_recognition_new(zend_class_entry *class_type)
zend_object* php_face_recognition_new(zend_class_entry *class_type TSRMLS_DC)
{
face_recognition *fr = (face_recognition*)ecalloc(1, sizeof(face_recognition));
zend_object_std_init(&fr->std, class_type);
zend_object_std_init(&fr->std, class_type TSRMLS_CC);
object_properties_init(&fr->std, class_type);
fr->std.handlers = &face_recognition_obj_handlers;
@@ -149,7 +159,7 @@ PHP_MINIT_FUNCTION(pdlib)
// CnnFaceDetection class definition
//
INIT_CLASS_ENTRY(ce, "CnnFaceDetection", cnn_face_detection_class_methods);
cnn_face_detection_ce = zend_register_internal_class(&ce);
cnn_face_detection_ce = zend_register_internal_class(&ce TSRMLS_CC);
cnn_face_detection_ce->create_object = php_cnn_face_detection_new;
memcpy(&cnn_face_detection_obj_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
cnn_face_detection_obj_handlers.offset = XtOffsetOf(cnn_face_detection, std);
@@ -158,7 +168,7 @@ PHP_MINIT_FUNCTION(pdlib)
// FaceLandmarkDetection class definition
//
INIT_CLASS_ENTRY(ce, "FaceLandmarkDetection", face_landmark_detection_class_methods);
face_landmark_detection_ce = zend_register_internal_class(&ce);
face_landmark_detection_ce = zend_register_internal_class(&ce TSRMLS_CC);
face_landmark_detection_ce->create_object = php_face_landmark_detection_new;
memcpy(&face_landmark_detection_obj_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
face_landmark_detection_obj_handlers.offset = XtOffsetOf(face_landmark_detection, std);
@@ -167,7 +177,7 @@ PHP_MINIT_FUNCTION(pdlib)
// FaceRecognition class definition
//
INIT_CLASS_ENTRY(ce, "FaceRecognition", face_recognition_class_methods);
face_recognition_ce = zend_register_internal_class(&ce);
face_recognition_ce = zend_register_internal_class(&ce TSRMLS_CC);
face_recognition_ce->create_object = php_face_recognition_new;
memcpy(&face_recognition_obj_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
face_recognition_obj_handlers.offset = XtOffsetOf(face_recognition, std);
@@ -217,13 +227,10 @@ PHP_RSHUTDOWN_FUNCTION(pdlib)
*/
PHP_MINFO_FUNCTION(pdlib)
{
char buf[32];
php_info_print_table_start();
php_info_print_table_header(2, "pdlib support", "enabled");
php_info_print_table_row(2, "pdlib extension version", PHP_PDLIB_VERSION);
snprintf(buf, sizeof(buf), "%d.%d.%d", DLIB_MAJOR_VERSION, DLIB_MINOR_VERSION, DLIB_PATCH_VERSION);
php_info_print_table_row(2, "dlib library version", buf);
php_info_print_table_header(2, "PDlib support", "enabled");
php_info_print_table_header(2, "Pdlib Version", PHP_PDLIB_VERSION);
// php_info_print_table_header(2, "Dlib Version", DLIB_VERSION);
#ifdef DLIB_USE_CUDA
php_info_print_table_header(2, "DLIB_USE_CUDA", "true");
#else

View File

@@ -31,8 +31,8 @@ extern "C" {
extern zend_module_entry pdlib_module_entry;
#define phpext_pdlib_ptr &pdlib_module_entry
#define PHP_PDLIB_NAME "pdlib"
#define PHP_PDLIB_VERSION "1.0.2"
#define PHP_PDLIB_NAME "pdlib"
#ifdef PHP_WIN32
# define PHP_PDLIB_API __declspec(dllexport)
@@ -67,13 +67,13 @@ ZEND_TSRMLS_CACHE_EXTERN()
/* Tries to find given key in array */ \
data##key = zend_hash_str_find(hashtable, #key, sizeof(#key)-1); \
if (data##key == nullptr) { \
zend_throw_exception_ex(zend_ce_exception, 0, #error_key_missing); \
zend_throw_exception_ex(zend_ce_exception, 0 TSRMLS_CC, #error_key_missing); \
return; \
} \
\
/* We also need to check proper type of value in associative array */ \
if (Z_TYPE_P(data##key) != IS_LONG) { \
zend_throw_exception_ex(zend_ce_exception, 0, #error_key_not_long); \
zend_throw_exception_ex(zend_ce_exception, 0 TSRMLS_CC, #error_key_not_long); \
return; \
} \
zend_long key = Z_LVAL_P(data##key); \

View File

@@ -17,7 +17,11 @@ PHP_FUNCTION(dlib_chinese_whispers)
std::vector<sample_pair> edges;
std::vector<unsigned long> labels;
if(zend_parse_parameters_throw(ZEND_NUM_ARGS(), "a", &edges_arg) == FAILURE){
if(zend_parse_parameters(ZEND_NUM_ARGS(), "a", &edges_arg) == FAILURE){
zend_throw_exception_ex(
zend_ce_exception,
0 TSRMLS_CC,
"Unable to parse edges in dlib_chinese_whispers");
return;
}
@@ -39,7 +43,7 @@ PHP_FUNCTION(dlib_chinese_whispers)
if (Z_TYPE_P(edge) != IS_ARRAY) {
zend_throw_exception_ex(
zend_ce_exception,
0,
0 TSRMLS_CC,
"Each edge provided in array needs to be numeric array of 2 elements");
return;
}
@@ -51,7 +55,7 @@ PHP_FUNCTION(dlib_chinese_whispers)
if (zend_hash_num_elements(edge_hash) != 2) {
zend_throw_exception_ex(
zend_ce_exception,
0,
0 TSRMLS_CC,
"Edges need to contain exactly two elements");
return;
}
@@ -62,7 +66,7 @@ PHP_FUNCTION(dlib_chinese_whispers)
!zend_hash_index_exists(edge_hash, 1)) {
zend_throw_exception_ex(
zend_ce_exception,
0,
0 TSRMLS_CC,
"Edge should be numeric array with integer keys");
return;
}
@@ -74,7 +78,7 @@ PHP_FUNCTION(dlib_chinese_whispers)
if ((Z_TYPE_P(elem_i) != IS_LONG) || (Z_TYPE_P(elem_j) != IS_LONG)) {
zend_throw_exception_ex(
zend_ce_exception,
0,
0 TSRMLS_CC,
"Both elements in each edge must be of long type");
return;
}
@@ -93,7 +97,7 @@ PHP_FUNCTION(dlib_chinese_whispers)
}
} catch (exception& e)
{
zend_throw_exception_ex(zend_ce_exception, 0, "%s", e.what());
zend_throw_exception_ex(zend_ce_exception, 0 TSRMLS_CC, e.what());
return;
}
}

View File

@@ -6,7 +6,7 @@
#define PHP_DLIB_CHINESE_WHISPERS_H
ZEND_BEGIN_ARG_INFO_EX(dlib_chinese_whispers_arginfo, 0, 0, 1)
ZEND_ARG_ARRAY_INFO(0, edges, 0)
ZEND_ARG_INFO(0, edges)
ZEND_END_ARG_INFO()
PHP_FUNCTION(dlib_chinese_whispers);

View File

@@ -25,12 +25,13 @@ PHP_METHOD(CnnFaceDetection, __construct)
cnn_face_detection *cfd = Z_CNN_FACE_DETECTION_P(getThis());
if (NULL == cfd) {
php_error_docref(NULL, E_ERROR, "Unable to find obj in CnnFaceDetection::__construct()");
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Unable to find obj in CnnFaceDetection::__construct()");
return;
}
if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "p",
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
&sz_cnn_face_detection_model_path, &cnn_face_detection_model_path_len) == FAILURE){
zend_throw_exception_ex(zend_ce_exception, 0 TSRMLS_CC, "Unable to parse face_detection_model_path");
return;
}
@@ -41,7 +42,7 @@ PHP_METHOD(CnnFaceDetection, __construct)
deserialize(cnn_face_detection_model_path) >> *pnet;
cfd->net = pnet;
} catch (exception& e) {
zend_throw_exception_ex(zend_ce_exception, 0, "%s", e.what());
zend_throw_exception_ex(zend_ce_exception, 0 TSRMLS_CC, e.what());
return;
}
}
@@ -52,7 +53,8 @@ PHP_METHOD(CnnFaceDetection, detect)
size_t img_path_len;
long upsample_num = 0;
if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "p|l", &img_path, &img_path_len, &upsample_num) == FAILURE){
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &img_path, &img_path_len, &upsample_num) == FAILURE){
zend_throw_exception_ex(zend_ce_exception, 0 TSRMLS_CC, "Unable to parse detect arguments");
RETURN_FALSE;
}
@@ -75,6 +77,7 @@ PHP_METHOD(CnnFaceDetection, detect)
net_type *pnet = cfd->net;
auto dets = (*pnet)(img);
int rect_count = 0;
array_init(return_value);
// Scale the detection locations back to the original image size
@@ -98,7 +101,7 @@ PHP_METHOD(CnnFaceDetection, detect)
}
catch (exception& e)
{
zend_throw_exception_ex(zend_ce_exception, 0, "%s", e.what());
zend_throw_exception_ex(zend_ce_exception, 0 TSRMLS_CC, e.what());
return;
}
}

View File

@@ -23,17 +23,13 @@ typedef struct _cnn_face_detection {
} cnn_face_detection;
ZEND_BEGIN_ARG_INFO_EX(cnn_face_detection_ctor_arginfo, 0, 0, 1)
ZEND_ARG_TYPE_INFO(0, cnn_face_detection_model_path, IS_STRING, 0)
ZEND_ARG_INFO(0, cnn_face_detection_model_path)
ZEND_END_ARG_INFO()
PHP_METHOD(CnnFaceDetection, __construct);
ZEND_BEGIN_ARG_INFO_EX(cnn_face_detection_detect_arginfo, 0, 0, 1)
ZEND_ARG_TYPE_INFO(0, img_path, IS_STRING, 0)
#if PHP_VERSION_ID < 80000
ZEND_ARG_TYPE_INFO(0, upsample_num, IS_LONG, 0)
#else
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, upsample_num, IS_LONG, 0, "0")
#endif
ZEND_BEGIN_ARG_INFO_EX(cnn_face_detection_detect_arginfo, 0, 0, 2)
ZEND_ARG_INFO(0, img_path)
ZEND_ARG_INFO(0, upsample_num)
ZEND_END_ARG_INFO()
PHP_METHOD(CnnFaceDetection, detect);

View File

@@ -17,7 +17,8 @@ PHP_FUNCTION(dlib_face_detection)
size_t img_path_len;
long upsample_num = 0;
if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "p|l", &img_path, &img_path_len, &upsample_num) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &img_path, &img_path_len, &upsample_num) == FAILURE) {
zend_throw_exception_ex(zend_ce_exception, 0 TSRMLS_CC, "Unable to parse dlib_face_detection arguments");
RETURN_FALSE;
}
try {

View File

@@ -6,12 +6,8 @@
#define PHP_DLIB_FACE_DETECTION_H
ZEND_BEGIN_ARG_INFO_EX(dlib_face_detection_arginfo, 0, 0, 1)
ZEND_ARG_TYPE_INFO(0, img_path, IS_STRING, 0)
#if PHP_VERSION_ID < 80000
ZEND_ARG_TYPE_INFO(0, upsample_num, IS_LONG, 0)
#else
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, upsample_num, IS_LONG, 0, "0")
#endif
ZEND_ARG_INFO(0, img_path)
ZEND_ARG_INFO(0, upsample_num)
ZEND_END_ARG_INFO()
PHP_FUNCTION(dlib_face_detection);

View File

@@ -27,7 +27,7 @@ PHP_FUNCTION(dlib_face_landmark_detection)
char *img_path;
size_t shape_predictor_file_path_len, img_path_len;
if(zend_parse_parameters_throw(ZEND_NUM_ARGS(), "ss", &shape_predictor_file_path, &shape_predictor_file_path_len,
if(zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &shape_predictor_file_path, &shape_predictor_file_path_len,
&img_path, &img_path_len) == FAILURE){
RETURN_FALSE;
}
@@ -52,7 +52,7 @@ PHP_FUNCTION(dlib_face_landmark_detection)
zval ARRAY_NAME_WITH_INDEX(face, j);
array_init(&ARRAY_NAME_WITH_INDEX(face, j));
for (unsigned int k = 0; k < shape.num_parts(); k++) {
for (int k = 0; k < shape.num_parts(); k++) {
zval ARRAY_NAME_WITH_INDEX(part, k);
array_init(&ARRAY_NAME_WITH_INDEX(part, k));
dlib::point p = shape.part(k);
@@ -78,13 +78,14 @@ PHP_METHOD(FaceLandmarkDetection, __construct)
face_landmark_detection *fld = Z_FACE_LANDMARK_DETECTION_P(getThis());
if (nullptr == fld) {
php_error_docref(NULL, E_ERROR, "Unable to find obj in FaceLandmarkDetection::__construct()");
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Unable to find obj in FaceLandmarkDetection::__construct()");
return;
}
// Parse predictor model's path
if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "p",
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
&sz_shape_predictor_file_path, &shape_predictor_file_path_len) == FAILURE){
zend_throw_exception_ex(zend_ce_exception, 0 TSRMLS_CC, "Unable to parse shape_predictor_file_path");
return;
}
@@ -94,7 +95,7 @@ PHP_METHOD(FaceLandmarkDetection, __construct)
fld->sp = new shape_predictor;
deserialize(shape_predictor_file_path) >> *(fld->sp);
} catch (exception& e) {
zend_throw_exception_ex(zend_ce_exception, 0, "%s", e.what());
zend_throw_exception_ex(zend_ce_exception, 0 TSRMLS_CC, e.what());
return;
}
}
@@ -113,7 +114,8 @@ PHP_METHOD(FaceLandmarkDetection, detect)
// Parse path to image and bounding box. Bounding box is associative array of 4 elements - "top", "bottom", "left" and "right".
//
if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "pa", &img_path, &img_path_len, &bounding_box) == FAILURE){
if (zend_parse_parameters(ZEND_NUM_ARGS(), "sa", &img_path, &img_path_len, &bounding_box) == FAILURE){
zend_throw_exception_ex(zend_ce_exception, 0 TSRMLS_CC, "Unable to parse detect arguments");
return;
}
@@ -121,7 +123,7 @@ PHP_METHOD(FaceLandmarkDetection, detect)
HashTable *bounding_box_hash = Z_ARRVAL_P(bounding_box);
uint32_t bounding_box_num_elements = zend_hash_num_elements(bounding_box_hash);
if (bounding_box_num_elements < 4) {
zend_throw_exception_ex(zend_ce_exception, 0, "Bounding box (second argument) needs to have at least 4 elements");
zend_throw_exception_ex(zend_ce_exception, 0 TSRMLS_CC, "Bounding box (second argument) needs to have at least 4 elements");
return;
}
@@ -149,7 +151,7 @@ PHP_METHOD(FaceLandmarkDetection, detect)
array_init(&rect_arr);
array_init(&parts_arr);
for (unsigned int i = 0; i < shape.num_parts(); i++) {
for (int i = 0; i < shape.num_parts(); i++) {
zval part;
array_init(&part);
dlib::point p = shape.part(i);
@@ -167,7 +169,7 @@ PHP_METHOD(FaceLandmarkDetection, detect)
add_assoc_zval(return_value, "rect", &rect_arr);
add_assoc_zval(return_value, "parts", &parts_arr);
} catch (exception& e) {
zend_throw_exception_ex(zend_ce_exception, 0, "%s", e.what());
zend_throw_exception_ex(zend_ce_exception, 0 TSRMLS_CC, e.what());
return;
}
}

View File

@@ -9,9 +9,9 @@
using namespace dlib;
ZEND_BEGIN_ARG_INFO_EX(dlib_face_landmark_detection_arginfo, 0, 0, 2)
ZEND_ARG_TYPE_INFO(0, shape_predictor_file_path, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, img_path, IS_STRING, 0)
ZEND_BEGIN_ARG_INFO_EX(dlib_face_landmark_detection_arginfo, 0, 0, 1)
ZEND_ARG_INFO(0, shape_predictor_file_path)
ZEND_ARG_INFO(0, img_path)
ZEND_END_ARG_INFO()
PHP_FUNCTION(dlib_face_landmark_detection);
@@ -21,13 +21,13 @@ typedef struct _face_landmark_detection {
} face_landmark_detection;
ZEND_BEGIN_ARG_INFO_EX(face_landmark_detection_ctor_arginfo, 0, 0, 1)
ZEND_ARG_TYPE_INFO(0, shape_predictor_file_path, IS_STRING, 0)
ZEND_ARG_INFO(0, shape_predictor_file_path)
ZEND_END_ARG_INFO()
PHP_METHOD(FaceLandmarkDetection, __construct);
ZEND_BEGIN_ARG_INFO_EX(face_landmark_detection_detect_arginfo, 0, 0, 2)
ZEND_ARG_TYPE_INFO(0, img_path, IS_STRING, 0)
ZEND_ARG_ARRAY_INFO(0, bounding_box, 0)
ZEND_ARG_INFO(0, img_path)
ZEND_ARG_INFO(0, bounding_box)
ZEND_END_ARG_INFO()
PHP_METHOD(FaceLandmarkDetection, detect);

View File

@@ -22,12 +22,13 @@ PHP_METHOD(FaceRecognition, __construct)
face_recognition *fr = Z_FACE_RECOGNITION_P(getThis());
if (NULL == fr) {
php_error_docref(NULL, E_ERROR, "Unable to find obj in FaceRecognition::__construct()");
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Unable to find obj in FaceRecognition::__construct()");
return;
}
if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "p",
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
&sz_face_recognition_model_path, &face_recognition_model_path_len) == FAILURE){
zend_throw_exception_ex(zend_ce_exception, 0 TSRMLS_CC, "Unable to parse face_recognition_model_path");
return;
}
@@ -36,7 +37,7 @@ PHP_METHOD(FaceRecognition, __construct)
fr->net = new anet_type;
deserialize(face_recognition_model_path) >> *(fr->net);
} catch (exception& e) {
zend_throw_exception_ex(zend_ce_exception, 0, "%s", e.what());
zend_throw_exception_ex(zend_ce_exception, 0 TSRMLS_CC, e.what());
return;
}
}
@@ -72,24 +73,25 @@ PHP_METHOD(FaceRecognition, computeDescriptor)
zval *shape;
long num_jitters = 1;
if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "pa|l", &img_path, &img_path_len, &shape, &num_jitters) == FAILURE){
if (zend_parse_parameters(ZEND_NUM_ARGS(), "sa|l", &img_path, &img_path_len, &shape, &num_jitters) == FAILURE){
zend_throw_exception_ex(zend_ce_exception, 0 TSRMLS_CC, "Unable to parse computeDescriptor arguments");
return;
}
HashTable *shape_hash = Z_ARRVAL_P(shape);
uint32_t shape_hash_num_elements = zend_hash_num_elements(shape_hash);
if (shape_hash_num_elements != 2) {
zend_throw_exception_ex(zend_ce_exception, 0, "Shape (second argument) needs to have exactly 2 elements - keys \"rect\" and \"parts\"");
zend_throw_exception_ex(zend_ce_exception, 0 TSRMLS_CC, "Shape (second argument) needs to have exactly 2 elements - keys \"rect\" and \"parts\"");
return;
}
zval *rect_zval = zend_hash_str_find(shape_hash, "rect", sizeof("rect")-1);
if (rect_zval == nullptr) {
zend_throw_exception_ex(zend_ce_exception, 0, "Shape (second argument) array needs to have \"rect\" key"); \
zend_throw_exception_ex(zend_ce_exception, 0 TSRMLS_CC, "Shape (second argument) array needs to have \"rect\" key"); \
return;
}
if (Z_TYPE_P(rect_zval) != IS_ARRAY) {
zend_throw_exception_ex(zend_ce_exception, 0, "Value of shape's key \"rect\" must be array");
zend_throw_exception_ex(zend_ce_exception, 0 TSRMLS_CC, "Value of shape's key \"rect\" must be array");
return;
}
HashTable *rect_hash = Z_ARRVAL_P(rect_zval);
@@ -102,11 +104,11 @@ PHP_METHOD(FaceRecognition, computeDescriptor)
zval *parts_zval = zend_hash_str_find(shape_hash, "parts", sizeof("parts")-1);
if (parts_zval == nullptr) {
zend_throw_exception_ex(zend_ce_exception, 0, "Shape (second argument) array needs to have \"parts\" key"); \
zend_throw_exception_ex(zend_ce_exception, 0 TSRMLS_CC, "Shape (second argument) array needs to have \"parts\" key"); \
return;
}
if (Z_TYPE_P(parts_zval) != IS_ARRAY) {
zend_throw_exception_ex(zend_ce_exception, 0, "Value of shape's key \"parts\" must be array");
zend_throw_exception_ex(zend_ce_exception, 0 TSRMLS_CC, "Value of shape's key \"parts\" must be array");
return;
}
HashTable *parts_hash = Z_ARRVAL_P(parts_zval);
@@ -115,7 +117,7 @@ PHP_METHOD(FaceRecognition, computeDescriptor)
point parts_points[parts_count];
if ((parts_count != 5) && (parts_count != 68)) {
zend_throw_exception_ex(zend_ce_exception, 0,
zend_throw_exception_ex(zend_ce_exception, 0 TSRMLS_CC,
"The full_object_detection must use the iBUG 300W 68 point face landmark style or dlib's 5 point style");
return;
}
@@ -135,17 +137,17 @@ PHP_METHOD(FaceRecognition, computeDescriptor)
PARSE_POINT(x)
PARSE_POINT(y)
if (num_index > parts_count) {
zend_throw_exception_ex(zend_ce_exception, 0, "Internal error, bad parsing of parts array");
zend_throw_exception_ex(zend_ce_exception, 0 TSRMLS_CC, "Internal error, bad parsing of parts array");
return;
}
parts_points[num_index] = point(x, y);
} else {
zend_throw_exception_ex(zend_ce_exception, 0, "Values from parts array must be arrays with \"x\" and \"y\" keys");
zend_throw_exception_ex(zend_ce_exception, 0 TSRMLS_CC, "Values from parts array must be arrays with \"x\" and \"y\" keys");
return;
}
break;
case HASH_KEY_IS_STRING:
zend_throw_exception_ex(zend_ce_exception, 0, "Parts array must be indexed and it contains string keys");
zend_throw_exception_ex(zend_ce_exception, 0 TSRMLS_CC, "Parts array must be indexed and it contains string keys");
return;
break;
}
@@ -181,7 +183,7 @@ PHP_METHOD(FaceRecognition, computeDescriptor)
add_next_index_double(return_value, d);
}
} catch (exception& e) {
zend_throw_exception_ex(zend_ce_exception, 0, "%s", e.what());
zend_throw_exception_ex(zend_ce_exception, 0 TSRMLS_CC, e.what());
return;
}
}

View File

@@ -44,18 +44,14 @@ typedef struct _face_recognition {
} face_recognition;
ZEND_BEGIN_ARG_INFO_EX(face_recognition_ctor_arginfo, 0, 0, 1)
ZEND_ARG_TYPE_INFO(0, face_recognition_model_path, IS_STRING, 0)
ZEND_ARG_INFO(0, face_recognition_model_path)
ZEND_END_ARG_INFO()
PHP_METHOD(FaceRecognition, __construct);
ZEND_BEGIN_ARG_INFO_EX(face_recognition_compute_descriptor_arginfo, 0, 0, 2)
ZEND_ARG_TYPE_INFO(0, img_path, IS_STRING, 0)
ZEND_ARG_ARRAY_INFO(0, landmarks, 0)
#if PHP_VERSION_ID < 80000
ZEND_ARG_TYPE_INFO(0, num_jitters, IS_LONG, 0)
#else
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, num_jitters, IS_LONG, 0, "1")
#endif
ZEND_BEGIN_ARG_INFO_EX(face_recognition_compute_descriptor_arginfo, 0, 0, 3)
ZEND_ARG_INFO(0, img_path)
ZEND_ARG_INFO(0, landmarks)
ZEND_ARG_INFO(0, num_jitters)
ZEND_END_ARG_INFO()
PHP_METHOD(FaceRecognition, computeDescriptor);

View File

@@ -13,20 +13,24 @@ PHP_FUNCTION(dlib_vector_length)
{
zval *x_arg, *y_arg;
if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "aa", &x_arg, &y_arg) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS(), "aa", &x_arg, &y_arg) == FAILURE) {
zend_throw_exception_ex(
zend_ce_exception,
0 TSRMLS_CC,
"Unable to parse arrays in dlib_vector_length");
return;
}
zval *elem_x, *elem_y;
double sum = 0.0;
unsigned int i, len;
int i, len;
len = zend_hash_num_elements(Z_ARRVAL_P(x_arg));
if (len != zend_hash_num_elements(Z_ARRVAL_P(y_arg))) {
zend_throw_exception_ex(
zend_ce_exception,
0,
0 TSRMLS_CC,
"The arrays have different sizes");
return;
}

View File

@@ -2,8 +2,8 @@
#define PHP_DLIB_VECTOR_H
ZEND_BEGIN_ARG_INFO_EX(dlib_vector_length_arginfo, 0, 0, 2)
ZEND_ARG_ARRAY_INFO(0, x_arg, 0)
ZEND_ARG_ARRAY_INFO(0, y_arg, 0)
ZEND_ARG_INFO(1, x_arg)
ZEND_ARG_INFO(1, y_arg)
ZEND_END_ARG_INFO()
PHP_FUNCTION(dlib_vector_length);

View File

@@ -6,9 +6,10 @@ Args given to chinese_whispers functions is not correct
<?php
try {
dlib_chinese_whispers("foo");
} catch (Error $e) {
} catch (Exception $e) {
var_dump($e->getMessage());
}
?>
--EXPECTF--
string(%d) "%s type array, string given"
Warning: dlib_chinese_whispers() expects parameter 1 to be array, string given in %s on line 3
string(46) "Unable to parse edges in dlib_chinese_whispers"

View File

@@ -6,10 +6,10 @@ Testing CnnFaceDetection constructor without arguments
<?php
try {
new CnnFaceDetection();
} catch (Error $e) {
} catch (Exception $e) {
var_dump($e->getMessage());
}
?>
--EXPECTF--
string(%d) "CnnFaceDetection::__construct() expects exactly 1 %s, 0 given"
Warning: CnnFaceDetection::__construct() expects exactly 1 parameter, 0 given in %s on line 3
string(41) "Unable to parse face_detection_model_path"

View File

@@ -1,10 +1,7 @@
--TEST--
Frontal face detection.
--SKIPIF--
<?php
if (!extension_loaded("pdlib")) die('skip pdlib extension missing');
if (getenv("SKIP_SLOW_TESTS")) die('skip slow test');
?>
<?php if (!extension_loaded("pdlib") print "skip"; ?>
--FILE--
<?php
printf("Simple detection\n");
@@ -28,4 +25,4 @@ Faces found = 1
Face[0] in bounding box (left=214, top=194, right=393, bottom=373)
Detection with upsampling
Faces found = 1
Face[0] in bounding box (left=201, top=180, right=386, bottom=366)
Face[0] in bounding box (left=201, top=180, right=386, bottom=366)

View File

@@ -6,7 +6,7 @@ Testing FaceLandmarkDetection constructor without arguments
<?php
try {
new FaceLandmarkDetection();
} catch (Error $e) {
} catch (Exception $e) {
var_dump($e->getMessage());
}
try {
@@ -16,5 +16,6 @@ try {
}
?>
--EXPECTF--
string(%d) "FaceLandmarkDetection::__construct() expects exactly 1 %s, 0 given"
Warning: FaceLandmarkDetection::__construct() expects exactly 1 parameter, 0 given in %s on line 3
string(41) "Unable to parse shape_predictor_file_path"
string(45) "Unable to open non-existent file for reading."

View File

@@ -6,9 +6,10 @@ Testing FaceRecognition constructor without arguments
<?php
try {
new FaceRecognition();
} catch (Error $e) {
} catch (Exception $e) {
var_dump($e->getMessage());
}
?>
--EXPECTF--
string(%d) "FaceRecognition::__construct() expects exactly 1 %s, 0 given"
Warning: FaceRecognition::__construct() expects exactly 1 parameter, 0 given in %s on line 3
string(43) "Unable to parse face_recognition_model_path"

View File

@@ -1,11 +1,7 @@
--TEST--
Full test for face recognition - download models, detect faces, landmark detection and face recognition.
--SKIPIF--
<?php
if (!extension_loaded("pdlib")) die('skip pdlib extension missing');
if (!function_exists("bzopen")) die('skip bz2 extension missing');
if (getenv("SKIP_ONLINE_TESTS")) die('skip online test');
?>
<?php if (!extension_loaded("pdlib") || (function_exists("bzopen"))) print "skip"; ?>
--FILE--
<?php
$models = array(
@@ -59,6 +55,6 @@ Processing prediction model
Processing recognition model
Detection
Faces found = 1
Face[0] in bounding box (left=191, top=200, right=355, bottom=363)
Face[0] in bounding box (left=187, top=186, right=357, bottom=355)
Since we used model with 5 shape predictions, we found 5 landmark parts
Descriptor is vector of 128 dimensions
Descriptor is vector of 128 dimensions