29 Commits

Author SHA1 Message Date
goodspb
1153e3e2eb Merge pull request #32 from matiasdelellis/to-upstream
Thank you.
2020-08-01 17:21:59 +08:00
Matias De lellis
32f94d32b9 Fix test. Probably Remi changed some default option on php 8.0 update 2020-07-07 19:30:34 -03:00
Matias De lellis
526fb725ce Add native vector_lenght() function which calculates the euclidean distance 80%
faster. See https://github.com/matiasdelellis/pdlib/pull/2.

Increase the version to 1.0.2 since this is a required function for our
application and we must control it.

Add more compilation info in php-info(), and print a final message with the
build options when configure.

Fix that when dlib is not installed, the configuration returns that it cannot
find pkgconfig. See https://github.com/matiasdelellis/facerecognition/issues/261

Also implement the test on travis. See for example:
(https://travis-ci.com/github/matiasdelellis/pdlib/builds/161854044)
2020-07-07 19:11:56 -03:00
goodspb
c7d57a7a1b Merge pull request #29 from remicollet/issue-build
Fix build and PHP 8 compat.
2020-07-05 22:52:46 +08:00
goodspb
9a86f95849 Merge pull request #27 from remicollet/issue-ver
display extension and library version in phpinfo
2020-06-30 15:56:08 +08:00
Remi Collet
cf0ce5a01e Fix and improve reflection
- use "p" for path (security check for nul byte)
- fix number of args for some methods
- add type hinting
- throw standard exception (simplify)
- fix test suite for PHP 7.0 to 8.0
2020-06-22 16:22:37 +02:00
Remi Collet
d36a2de544 drop confirm_pdlib_compiled function
This is a generated function from example skeleton
only for documentation, no real value.

Adn it is broken on PHP 8 and arginfo is missing
2020-06-22 15:11:38 +02:00
Remi Collet
40a2bd60e4 cleanup TSRMLS_C macro
- only used on PHP 5 (not supported by this ext.)
- not needed on PHP 7
- removed from PHP 8
2020-06-22 15:01:30 +02:00
Remi Collet
912ab43641 fix [-Werror=format-security] 2020-06-22 12:54:12 +02:00
Remi Collet
8f424195e0 fix unused variables 2020-06-22 12:47:43 +02:00
Remi Collet
ba797b3c50 hounours system CXXFLAGS 2020-06-22 12:46:30 +02:00
Remi Collet
b70ff4eb17 display extension and library version in phpinfo 2020-06-22 11:20:55 +02:00
goodspb
45c0b7441a Merge pull request #26 from remicollet/issue-skip
fix tests skip condition
2020-06-20 20:28:51 +08:00
goodspb
7d60446891 Merge pull request #25 from remicollet/issue-css
fix linker command
2020-06-20 20:21:07 +08:00
Remi Collet
351bce6117 fix tests skip condition 2020-06-20 08:23:50 +02:00
Remi Collet
24d12358f2 fix linker command 2020-06-20 08:08:27 +02:00
goodspb
b4f152f860 Merge pull request #20 from matiasdelellis/improve-hog
HOG detector also must return the rectangles of the detections.
2020-05-01 11:19:17 +08:00
Matias De lellis
dfd6a952fb upsample_num as references 2020-03-07 12:55:39 -03:00
Matias De lellis
cd4e7bcbdf Dont upsamply by default in CNN, and optional argument on fhog for that. 2020-03-07 10:46:12 -03:00
Matias De lellis
afc9164127 HOG detector also must return the rectangles of the detections. 2020-02-29 14:04:41 -03:00
goodspb
1e492f2e12 Merge pull request #18 from stalker314314/fixing-tests-on-different-environments
Fixing tests on different environments
2020-01-31 11:25:09 +08:00
Branko Kokanovic
a83750a4ff Fixing tests, closes #14 2019-11-28 23:14:34 +01:00
goodspb
c08a7608a2 Merge pull request #13 from SlavikCA/patch-1
README: requirement of libx11-dev; recommendation of BLAS
2019-01-06 17:37:36 +08:00
Slavik
fcb54ace66 README: requirement of libx11-dev; recommendation of BLAS 2019-01-05 23:55:22 -08:00
goodspb
606a6717ea Merge pull request #11 from stalker314314/patch-1
Fix git -> https in README
2019-01-01 11:06:15 +08:00
Branko Kokanovic
0fd67af03e Fix git -> https in README
People usually don't have access to Github for DLib, so previous command will not work out-of-box. Better to suggest https:// alternative
2018-12-30 19:29:39 +00:00
Branko Kokanovic
54f3b75139 Merge pull request #9 from goodspb/master
refresh
2018-08-30 21:19:36 +02:00
Branko Kokanovic
ac67a9992d Merge pull request #6 from goodspb/master
refresh
2018-08-29 00:42:25 +02:00
Branko Kokanovic
9e429a772a Merge branch 'goodspb-master' 2018-08-29 00:40:55 +02:00
26 changed files with 365 additions and 161 deletions

13
.gitignore vendored
View File

@@ -28,12 +28,11 @@ missing
mkinstalldirs
modules
run-tests.php
tests/*/*.diff
tests/*/*.out
tests/*/*.php
tests/*/*.exp
tests/*/*.log
tests/*/*.sh
tests/*.diff
tests/*.out
tests/*.php
tests/*.exp
tests/*.log
tests/*.sh
.idea
cmake-build-debug

28
.travis.yml Normal file
View File

@@ -0,0 +1,28 @@
dist: bionic
sudo: false
language: php
php:
- 7.1
- 7.2
- 7.3
- 7.4
before_install:
- sudo sh -c 'echo "deb https://repo.delellis.com.ar bionic bionic" > /etc/apt/sources.list.d/20-pdlib.list'
- wget -qO - https://repo.delellis.com.ar/repo.gpg.key | sudo apt-key add -
- sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 762E3157
- sudo apt update
- sudo apt-get install libdlib-dev
- phpize
- ./configure --enable-debug
- make
- sudo make install
- echo "extension=pdlib.so" >> `php --ini | grep "Loaded Configuration" | sed -e "s|.*:\s*||"`
script:
- export TEST_PHP_EXECUTABLE=`which php`
- export NO_INTERACTION=1
- php run-tests.php -q --show-diff

View File

@@ -4,6 +4,14 @@
- Dlib 19.13+
- PHP 7.0+
- C++11
- libx11-dev (on Ubuntu: `sudo apt-get install libx11-dev`)
## 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`
## Dependencies
@@ -12,7 +20,7 @@
Install Dlib as shared library
```bash
git clone git@github.com:davisking/dlib.git
git clone https://github.com/davisking/dlib.git
cd dlib/dlib
mkdir build
cd build
@@ -92,9 +100,8 @@ If you want to use HOG based approach:
<?php
// face detection
$faceCount = dlib_face_detection("~/a.jpg");
// how mary face in the picture.
var_dump($faceCount);
detected_faces = dlib_face_detection("image.jpg");
// $detected_faces is indexed array, where values are assoc arrays with "top", "bottom", "left" and "right" values
```
If you want to use CNN approach (and CNN model):

View File

@@ -1,10 +1,3 @@
dnl $Id$
dnl config.m4 for extension pdlib
dnl Comments in this file start with the string 'dnl'.
dnl Remove where necessary. This file will not work
dnl without editing.
if test -z "$PHP_DEBUG"; then
AC_ARG_ENABLE(debug,
[ --enable-debug compile with debugging symbols],[
@@ -18,8 +11,6 @@ dnl Make sure that the comment is aligned:
[ --with-pdlib Include pdlib support])
if test "$PHP_PDLIB" != "no"; then
dnl using C++11
CXXFLAGS="-std=c++11"
PHP_REQUIRE_CXX()
PHP_ADD_LIBRARY(stdc++, 1, PDLIB_SHARED_LIBADD)
PHP_SUBST(PDLIB_SHARED_LIBADD)
@@ -29,27 +20,49 @@ if test "$PHP_PDLIB" != "no"; then
src/face_detection.cc \
src/face_landmark_detection.cc \
src/face_recognition.cc \
src/cnn_face_detection.cc "
src/cnn_face_detection.cc
src/vector.cc"
AC_MSG_CHECKING(for pkg-config)
if test ! -f "$PKG_CONFIG"; then
PKG_CONFIG=`which pkg-config`
fi
if test -x "$PKG_CONFIG" && $PKG_CONFIG --exists dlib-1; then
if $PKG_CONFIG dlib-1 --atleast-version 19.00; then
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
else
AC_MSG_ERROR(system dlib is too old: version 19.00 required)
fi
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, $pdlib_src_files, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)
dnl using C++11
PHP_NEW_EXTENSION(pdlib, $pdlib_src_files, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1 -std=c++11, cxx)
fi
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 ""
])

101
pdlib.cc
View File

@@ -33,14 +33,14 @@ extern "C" {
#include "src/face_recognition.h"
#include "src/cnn_face_detection.h"
#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,34 +60,6 @@ PHP_INI_END()
*/
/* }}} */
/* Remove the following function when you have successfully modified config.m4
so that your module can be compiled into PHP, it exists only for testing
purposes. */
/* Every user-visible function in PHP should document itself in the source */
/* {{{ proto string confirm_pdlib_compiled(string arg)
Return a string to confirm that the module is compiled in */
PHP_FUNCTION(confirm_pdlib_compiled)
{
char *arg = NULL;
size_t arg_len, len;
zend_string *strg;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &arg, &arg_len) == FAILURE) {
return;
}
strg = strpprintf(0, "Congratulations! You have successfully modified ext/%.78s/config.m4. Module %.78s is now compiled into PHP.", "pdlib", arg);
RETURN_STR(strg);
}
/* }}} */
/* 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
*/
@@ -106,10 +78,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 TSRMLS_DC)
zend_object* php_cnn_face_detection_new(zend_class_entry *class_type)
{
cnn_face_detection *cfd = (cnn_face_detection*)ecalloc(1, sizeof(cnn_face_detection));
zend_object_std_init(&cfd->std, class_type TSRMLS_CC);
zend_object_std_init(&cfd->std, class_type);
object_properties_init(&cfd->std, class_type);
cfd->std.handlers = &cnn_face_detection_obj_handlers; //zend_get_std_object_handlers();
@@ -129,10 +101,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 TSRMLS_DC)
zend_object* php_face_landmark_detection_new(zend_class_entry *class_type)
{
face_landmark_detection *fld = (face_landmark_detection*)ecalloc(1, sizeof(face_landmark_detection));
zend_object_std_init(&fld->std, class_type TSRMLS_CC);
zend_object_std_init(&fld->std, class_type);
object_properties_init(&fld->std, class_type);
fld->std.handlers = &face_landmark_detection_obj_handlers;
@@ -152,10 +124,10 @@ const zend_function_entry face_recognition_class_methods[] = {
PHP_FE_END
};
zend_object* php_face_recognition_new(zend_class_entry *class_type TSRMLS_DC)
zend_object* php_face_recognition_new(zend_class_entry *class_type)
{
face_recognition *fr = (face_recognition*)ecalloc(1, sizeof(face_recognition));
zend_object_std_init(&fr->std, class_type TSRMLS_CC);
zend_object_std_init(&fr->std, class_type);
object_properties_init(&fr->std, class_type);
fr->std.handlers = &face_recognition_obj_handlers;
@@ -177,7 +149,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 TSRMLS_CC);
cnn_face_detection_ce = zend_register_internal_class(&ce);
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);
@@ -186,7 +158,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 TSRMLS_CC);
face_landmark_detection_ce = zend_register_internal_class(&ce);
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);
@@ -195,7 +167,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 TSRMLS_CC);
face_recognition_ce = zend_register_internal_class(&ce);
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);
@@ -245,8 +217,53 @@ 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);
#ifdef DLIB_USE_CUDA
php_info_print_table_header(2, "DLIB_USE_CUDA", "true");
#else
php_info_print_table_header(2, "DLIB_USE_CUDA", "false");
#endif
#ifdef DLIB_USE_BLAS
php_info_print_table_header(2, "DLIB_USE_BLAS", "true");
#else
php_info_print_table_header(2, "DLIB_USE_BLAS", "false");
#endif
#ifdef DLIB_USE_LAPACK
php_info_print_table_header(2, "DLIB_USE_LAPACK", "true");
#else
php_info_print_table_header(2, "DLIB_USE_LAPACK", "false");
#endif
#ifdef DLIB_HAVE_AVX
php_info_print_table_header(2, "USE_AVX_INSTRUCTIONS", "true");
#else
php_info_print_table_header(2, "USE_AVX_INSTRUCTIONS", "false");
#endif
#ifdef DLIB_HAVE_AVX2
php_info_print_table_header(2, "USE_AVX2_INSTRUCTIONS", "true");
#else
php_info_print_table_header(2, "USE_AVX2_INSTRUCTIONS", "false");
#endif
#ifdef DLIB_HAVE_NEON
php_info_print_table_header(2, "USE_NEON_INSTRUCTIONS", "true");
#else
php_info_print_table_header(2, "USE_NEON_INSTRUCTIONS", "false");
#endif
#ifdef DLIB_HAVE_SSE2
php_info_print_table_header(2, "USE_SSE2_INSTRUCTIONS", "true");
#else
php_info_print_table_header(2, "USE_SSE2_INSTRUCTIONS", "false");
#endif
#ifdef DLIB_HAVE_SSE41
php_info_print_table_header(2, "USE_SSE4_INSTRUCTIONS", "true");
#else
php_info_print_table_header(2, "USE_SSE4_INSTRUCTIONS", "false");
#endif
php_info_print_table_end();
/* Remove comments if you have entries in php.ini
@@ -260,10 +277,10 @@ PHP_MINFO_FUNCTION(pdlib)
* Every user visible function must have an entry in pdlib_functions[].
*/
const zend_function_entry pdlib_functions[] = {
PHP_FE(confirm_pdlib_compiled, NULL)
PHP_FE(dlib_chinese_whispers, dlib_chinese_whispers_arginfo)
PHP_FE(dlib_face_detection, dlib_face_detection_arginfo)
PHP_FE(dlib_face_landmark_detection, dlib_face_landmark_detection_arginfo)
PHP_FE(dlib_vector_length, dlib_vector_length_arginfo)
PHP_FE_END /* Must be the last line in pdlib_functions[] */
};
/* }}} */
@@ -272,7 +289,7 @@ const zend_function_entry pdlib_functions[] = {
*/
zend_module_entry pdlib_module_entry = {
STANDARD_MODULE_HEADER,
"pdlib",
PHP_PDLIB_NAME,
pdlib_functions,
PHP_MINIT(pdlib),
PHP_MSHUTDOWN(pdlib),

View File

@@ -31,7 +31,8 @@ extern "C" {
extern zend_module_entry pdlib_module_entry;
#define phpext_pdlib_ptr &pdlib_module_entry
#define PHP_PDLIB_VERSION "0.1.0" /* Replace with version number for your extension */
#define PHP_PDLIB_VERSION "1.0.2"
#define PHP_PDLIB_NAME "pdlib"
#ifdef PHP_WIN32
# define PHP_PDLIB_API __declspec(dllexport)
@@ -66,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 TSRMLS_CC, #error_key_missing); \
zend_throw_exception_ex(zend_ce_exception, 0, #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 TSRMLS_CC, #error_key_not_long); \
zend_throw_exception_ex(zend_ce_exception, 0, #error_key_not_long); \
return; \
} \
zend_long key = Z_LVAL_P(data##key); \

View File

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

View File

@@ -25,13 +25,12 @@ PHP_METHOD(CnnFaceDetection, __construct)
cnn_face_detection *cfd = Z_CNN_FACE_DETECTION_P(getThis());
if (NULL == cfd) {
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Unable to find obj in CnnFaceDetection::__construct()");
php_error_docref(NULL, E_ERROR, "Unable to find obj in CnnFaceDetection::__construct()");
return;
}
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "p",
&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;
}
@@ -42,7 +41,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 TSRMLS_CC, e.what());
zend_throw_exception_ex(zend_ce_exception, 0, "%s", e.what());
return;
}
}
@@ -51,10 +50,9 @@ PHP_METHOD(CnnFaceDetection, detect)
{
char *img_path;
size_t img_path_len;
long upsample_num = 1;
long upsample_num = 0;
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");
if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "p|l", &img_path, &img_path_len, &upsample_num) == FAILURE){
RETURN_FALSE;
}
@@ -77,7 +75,6 @@ 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
@@ -101,7 +98,7 @@ PHP_METHOD(CnnFaceDetection, detect)
}
catch (exception& e)
{
zend_throw_exception_ex(zend_ce_exception, 0 TSRMLS_CC, e.what());
zend_throw_exception_ex(zend_ce_exception, 0, "%s", e.what());
return;
}
}

View File

@@ -23,13 +23,17 @@ typedef struct _cnn_face_detection {
} cnn_face_detection;
ZEND_BEGIN_ARG_INFO_EX(cnn_face_detection_ctor_arginfo, 0, 0, 1)
ZEND_ARG_INFO(0, cnn_face_detection_model_path)
ZEND_ARG_TYPE_INFO(0, cnn_face_detection_model_path, IS_STRING, 0)
ZEND_END_ARG_INFO()
PHP_METHOD(CnnFaceDetection, __construct);
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_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_END_ARG_INFO()
PHP_METHOD(CnnFaceDetection, detect);

View File

@@ -2,6 +2,7 @@
#include "../php_pdlib.h"
#include "face_detection.h"
#include <zend_exceptions.h>
#include <dlib/image_processing/frontal_face_detector.h>
#include <dlib/gui_widgets.h>
#include <dlib/image_io.h>
@@ -14,19 +15,40 @@ PHP_FUNCTION(dlib_face_detection)
{
char *img_path;
size_t img_path_len;
long upsample_num = 0;
if(zend_parse_parameters(ZEND_NUM_ARGS(), "s", &img_path, &img_path_len) == FAILURE){
if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "p|l", &img_path, &img_path_len, &upsample_num) == FAILURE) {
RETURN_FALSE;
}
try {
frontal_face_detector detector = get_frontal_face_detector();
pyramid_down<2> pyr;
array2d<unsigned char> img;
load_image(img, img_path);
pyramid_up(img);
unsigned int levels = upsample_num;
while (levels > 0) {
levels--;
pyramid_up(img, pyr);
}
array_init(return_value);
std::vector<rectangle> dets = detector(img);
RETURN_LONG(dets.size());
for (unsigned long i = 0; i < dets.size(); ++i) {
rectangle rect = pyr.rect_down(dets[i], upsample_num);
zval rect_arr;
array_init(&rect_arr);
add_assoc_long(&rect_arr, "left", rect.left());
add_assoc_long(&rect_arr, "top", rect.top());
add_assoc_long(&rect_arr, "right", rect.right());
add_assoc_long(&rect_arr, "bottom", rect.bottom());
// Add this assoc array to returned array
//
add_next_index_zval(return_value, &rect_arr);
}
}
catch (exception& e)
{

View File

@@ -6,7 +6,12 @@
#define PHP_DLIB_FACE_DETECTION_H
ZEND_BEGIN_ARG_INFO_EX(dlib_face_detection_arginfo, 0, 0, 1)
ZEND_ARG_INFO(0, img_path)
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_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(ZEND_NUM_ARGS(), "ss", &shape_predictor_file_path, &shape_predictor_file_path_len,
if(zend_parse_parameters_throw(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 (int k = 0; k < shape.num_parts(); k++) {
for (unsigned 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,14 +78,13 @@ PHP_METHOD(FaceLandmarkDetection, __construct)
face_landmark_detection *fld = Z_FACE_LANDMARK_DETECTION_P(getThis());
if (nullptr == fld) {
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Unable to find obj in FaceLandmarkDetection::__construct()");
php_error_docref(NULL, E_ERROR, "Unable to find obj in FaceLandmarkDetection::__construct()");
return;
}
// Parse predictor model's path
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "p",
&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;
}
@@ -95,7 +94,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 TSRMLS_CC, e.what());
zend_throw_exception_ex(zend_ce_exception, 0, "%s", e.what());
return;
}
}
@@ -114,8 +113,7 @@ 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(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");
if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "pa", &img_path, &img_path_len, &bounding_box) == FAILURE){
return;
}
@@ -123,7 +121,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 TSRMLS_CC, "Bounding box (second argument) needs to have at least 4 elements");
zend_throw_exception_ex(zend_ce_exception, 0, "Bounding box (second argument) needs to have at least 4 elements");
return;
}
@@ -151,7 +149,7 @@ PHP_METHOD(FaceLandmarkDetection, detect)
array_init(&rect_arr);
array_init(&parts_arr);
for (int i = 0; i < shape.num_parts(); i++) {
for (unsigned int i = 0; i < shape.num_parts(); i++) {
zval part;
array_init(&part);
dlib::point p = shape.part(i);
@@ -169,7 +167,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 TSRMLS_CC, e.what());
zend_throw_exception_ex(zend_ce_exception, 0, "%s", e.what());
return;
}
}

View File

@@ -9,9 +9,9 @@
using namespace dlib;
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_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_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_INFO(0, shape_predictor_file_path)
ZEND_ARG_TYPE_INFO(0, shape_predictor_file_path, IS_STRING, 0)
ZEND_END_ARG_INFO()
PHP_METHOD(FaceLandmarkDetection, __construct);
ZEND_BEGIN_ARG_INFO_EX(face_landmark_detection_detect_arginfo, 0, 0, 2)
ZEND_ARG_INFO(0, img_path)
ZEND_ARG_INFO(0, bounding_box)
ZEND_ARG_TYPE_INFO(0, img_path, IS_STRING, 0)
ZEND_ARG_ARRAY_INFO(0, bounding_box, 0)
ZEND_END_ARG_INFO()
PHP_METHOD(FaceLandmarkDetection, detect);

View File

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

View File

@@ -44,14 +44,18 @@ typedef struct _face_recognition {
} face_recognition;
ZEND_BEGIN_ARG_INFO_EX(face_recognition_ctor_arginfo, 0, 0, 1)
ZEND_ARG_INFO(0, face_recognition_model_path)
ZEND_ARG_TYPE_INFO(0, face_recognition_model_path, IS_STRING, 0)
ZEND_END_ARG_INFO()
PHP_METHOD(FaceRecognition, __construct);
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_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_END_ARG_INFO()
PHP_METHOD(FaceRecognition, computeDescriptor);

43
src/vector.cc Normal file
View File

@@ -0,0 +1,43 @@
#include "../php_pdlib.h"
#include "vector.h"
#include <cmath>
#include <zend_exceptions.h>
#include <iostream>
using namespace std;
PHP_FUNCTION(dlib_vector_length)
{
zval *x_arg, *y_arg;
if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "aa", &x_arg, &y_arg) == FAILURE) {
return;
}
zval *elem_x, *elem_y;
double sum = 0.0;
unsigned 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,
"The arrays have different sizes");
return;
}
for (i = 0 ; i < len ; i++) {
elem_x = zend_hash_index_find(Z_ARRVAL_P(x_arg), i);
elem_y = zend_hash_index_find(Z_ARRVAL_P(y_arg), i);
sum += (Z_DVAL_P(elem_x) - Z_DVAL_P(elem_y))*(Z_DVAL_P(elem_x) - Z_DVAL_P(elem_y));
}
RETURN_DOUBLE(sqrt(sum));
}

10
src/vector.h Normal file
View File

@@ -0,0 +1,10 @@
#ifndef PHP_DLIB_VECTOR_H
#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_END_ARG_INFO()
PHP_FUNCTION(dlib_vector_length);
#endif //PHP_DLIB_VECTOR_H

View File

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

View File

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

View File

@@ -0,0 +1,31 @@
--TEST--
Frontal face detection.
--SKIPIF--
<?php
if (!extension_loaded("pdlib")) die('skip pdlib extension missing');
if (getenv("SKIP_SLOW_TESTS")) die('skip slow test');
?>
--FILE--
<?php
printf("Simple detection\n");
$detected_faces = dlib_face_detection(__DIR__ . "/lenna.jpg");
printf("Faces found = %d\n", count($detected_faces));
foreach($detected_faces as $index => $detected_face) {
printf("Face[%d] in bounding box (left=%d, top=%d, right=%d, bottom=%d)\n", $index,
$detected_face["left"], $detected_face["top"], $detected_face["right"], $detected_face["bottom"]);
}
printf("Detection with upsampling\n");
$detected_faces = dlib_face_detection(__DIR__ . "/lenna.jpg", 1);
printf("Faces found = %d\n", count($detected_faces));
foreach($detected_faces as $index => $detected_face) {
printf("Face[%d] in bounding box (left=%d, top=%d, right=%d, bottom=%d)\n", $index,
$detected_face["left"], $detected_face["top"], $detected_face["right"], $detected_face["bottom"]);
}
?>
--EXPECT--
Simple detection
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)

View File

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

View File

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

View File

@@ -1,7 +1,11 @@
--TEST--
Full test for face recognition - download models, detect faces, landmark detection and face recognition.
--SKIPIF--
<?php if (!extension_loaded("pdlib") || (function_exists("bzopen"))) print "skip"; ?>
<?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');
?>
--FILE--
<?php
$models = array(
@@ -55,6 +59,6 @@ Processing prediction model
Processing recognition model
Detection
Faces found = 1
Face[0] in bounding box (left=187, top=186, right=357, bottom=355)
Face[0] in bounding box (left=191, top=200, right=355, bottom=363)
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

20
tests/vector_length.phpt Normal file
View File

@@ -0,0 +1,20 @@
--TEST--
Basic tests for dlib_vector_length
--SKIPIF--
<?php if (!extension_loaded("pdlib")) print "skip"; ?>
--FILE--
<?php
$vectorAL = [0.0, 0.0];
$vectorAR = [0.0, 1.0];
var_dump(dlib_vector_length($vectorAL, $vectorAR));
$vectorBL = [0.0, 0.0, -1.0];
$vectorBR = [0.0, 0.0, 1.0];
var_dump(dlib_vector_length($vectorBL, $vectorBR));
$vectorCL = [0.0, 2.5, 1.0];
$vectorCR = [0.0, 1.0, 1.0];
var_dump(dlib_vector_length($vectorCL, $vectorCR));
?>
--EXPECT--
float(1)
float(2)
float(1.5)

10
tests/version.phpt Normal file
View File

@@ -0,0 +1,10 @@
--TEST--
Just test php extension version
--SKIPIF--
<?php if (!extension_loaded("pdlib")) print "skip"; ?>
--FILE--
<?php
var_dump(phpversion('pdlib'));
?>
--EXPECT--
string(5) "1.0.2"