├── .gitignore ├── CREDITS ├── INSTALL ├── LICENSE ├── README.md ├── config.m4 ├── config.w32 ├── facedetect.cc └── php_facedetect.h /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.swp 3 | *.lo 4 | *.la 5 | .deps 6 | .libs 7 | Makefile 8 | Makefile.fragments 9 | Makefile.global 10 | Makefile.objects 11 | acinclude.m4 12 | aclocal.m4 13 | autom4te.cache 14 | build 15 | config.cache 16 | config.guess 17 | config.h 18 | config.h.in 19 | config.log 20 | config.nice 21 | config.status 22 | config.sub 23 | configure 24 | configure.in 25 | configure.ac 26 | conftest 27 | conftest.c 28 | include 29 | install-sh 30 | libtool 31 | ltmain.sh 32 | ltmain.sh.backup 33 | missing 34 | mkinstalldirs 35 | modules 36 | scan_makefile_in.awk 37 | *.dsw 38 | *.plg 39 | *.opt 40 | *.ncb 41 | Release 42 | Release_inline 43 | Debug 44 | Release_TS 45 | Release_TSDbg 46 | Release_TS_inline 47 | Debug_TS 48 | memcached*.tgz 49 | run-tests.php 50 | cscope.out 51 | php_memcached.loT 52 | tests/*.log 53 | tests/*.mem 54 | tests/*.out 55 | tests/*.diff 56 | tests/*.php 57 | tests/*.exp 58 | tests/*.sh 59 | tests/*/*.log 60 | tests/*/*.mem 61 | tests/*/*.out 62 | tests/*/*.diff 63 | tests/*/*.php 64 | tests/*/*.exp 65 | tests/*/*.sh 66 | tests/*/*/*.log 67 | tests/*/*/*.mem 68 | tests/*/*/*.out 69 | tests/*/*/*.diff 70 | tests/*/*/*.php 71 | tests/*/*/*.exp 72 | tests/*/*/*.sh 73 | tmp-php.ini 74 | -------------------------------------------------------------------------------- /CREDITS: -------------------------------------------------------------------------------- 1 | Facedetect 2 | Robert Eisele 3 | 4 | www.xarg.org -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | Installing with `pecl` command-line utility 2 | 3 | 1. Install OpenCV libraries (at least version 3.0.0) 4 | 2. Execute command "pecl install facedetect" 5 | 3. Make sure you have extension=facedetect.so in your php.ini 6 | 7 | 8 | Installing from sources 9 | 10 | 1. Install OpenCV libraries (at least version 3.0.0) 11 | 2. Unpack facedetect source package 12 | 3. Go to facedetect folder and type "phpize && ./configure && make && make install" 13 | 4. Make sure you have extension=facedetect.so in your php.ini 14 | 15 | 16 | Compiling Facedetect into PHP 17 | 18 | 1. Install OpenCV libraries (at least version 3.0.0) 19 | 2. Unpack facedetect source package to $PHP_SOURCE_DIR/ext/facedetect 20 | 3. In php source root directory run commands: "rm configure && ./buildconf --force" 21 | 4. Configure PHP with command "./configure --with-facedetect" 22 | 5. Run make && make install 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009, Robert Eisele 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | * Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | * Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | * Neither the name of the nor the 12 | names of its contributors may be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 19 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PHP-Facedetect 2 | A simple OpenCV wrapper for PHP to detect faces on images 3 | 4 | OpenCV 3 Support 5 | 6 | See [Details](http://www.xarg.org/project/php-facedetect/) 7 | -------------------------------------------------------------------------------- /config.m4: -------------------------------------------------------------------------------- 1 | PHP_ARG_WITH(facedetect, for facedetect support, [ --with-facedetect Enable facedetect support]) 2 | 3 | if test "$PHP_FACEDETECT" != "no"; then 4 | PHP_REQUIRE_CXX() 5 | AC_PATH_PROG(PKG_CONFIG, pkg-config, no) 6 | AC_MSG_CHECKING(for opencv) 7 | if test -x "$PKG_CONFIG" && $PKG_CONFIG --exists opencv; then 8 | CV_INCLUDE=`$PKG_CONFIG opencv --variable=includedir_new` 9 | CV_LIBRARY=`$PKG_CONFIG opencv --libs` 10 | CV_VERSION=`$PKG_CONFIG opencv --modversion` 11 | if $PKG_CONFIG opencv --atleast-version=3.0.0 ; then 12 | AC_MSG_RESULT($CV_VERSION) 13 | else 14 | AC_MSG_ERROR(opencv version is too old.) 15 | fi 16 | PHP_EVAL_LIBLINE($CV_LIBRARY, FACEDETECT_SHARED_LIBADD) 17 | PHP_ADD_INCLUDE($CV_INCLUDE) 18 | else 19 | if test -x "$PKG_CONFIG" && $PKG_CONFIG --exists opencv4; then 20 | CV_INCLUDE=`$PKG_CONFIG opencv4 --variable=includedir` 21 | CV_LIBRARY=`$PKG_CONFIG opencv4 --libs` 22 | CV_VERSION=`$PKG_CONFIG opencv4 --modversion` 23 | if $PKG_CONFIG opencv4 --atleast-version=3.0.0 ; then 24 | AC_MSG_RESULT($CV_VERSION) 25 | else 26 | AC_MSG_ERROR(opencv version is too old) 27 | fi 28 | PHP_EVAL_LIBLINE($CV_LIBRARY, FACEDETECT_SHARED_LIBADD) 29 | PHP_ADD_INCLUDE($CV_INCLUDE) 30 | else 31 | AC_MSG_ERROR(Please reinstall opencv) 32 | fi 33 | fi 34 | 35 | PHP_SUBST(FACEDETECT_SHARED_LIBADD) 36 | AC_DEFINE(HAVE_FACEDETECT, 1, [ ]) 37 | PHP_NEW_EXTENSION(facedetect, facedetect.cc, $ext_shared) 38 | fi 39 | -------------------------------------------------------------------------------- /config.w32: -------------------------------------------------------------------------------- 1 | // $Id$ 2 | // vim:ft=javascript 3 | 4 | ARG_WITH("facedetect", "for facedetect support", "no"); 5 | 6 | if (PHP_FACEDETECT == "yes") { 7 | if (CHECK_LIB("opencv_objdetect*.lib", "facedetect", PHP_FACEDETECT) && 8 | CHECK_LIB("opencv_core*.lib", "facedetect", PHP_FACEDETECT) && 9 | CHECK_LIB("opencv_imgproc*.lib", "facedetect", PHP_FACEDETECT) && 10 | CHECK_LIB("opencv_highgui*.lib", "facedetect", PHP_FACEDETECT) && 11 | CHECK_HEADER_ADD_INCLUDE("opencv2/core/core_c.h", "CFLAGS_FFACEDETECT")) { 12 | 13 | AC_DEFINE("HAVE_FACEDETECT", 1); 14 | 15 | EXTENSION("facedetect", "facedetect.c", true); 16 | } else { 17 | WARNING("facedetect not enabled, headers or libraries not found"); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /facedetect.cc: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | PHP Version 7 | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 1997-2018 The PHP Group | 6 | +----------------------------------------------------------------------+ 7 | | This source file is subject to version 3.01 of the PHP license, | 8 | | that is bundled with this package in the file LICENSE, and is | 9 | | available through the world-wide-web at the following url: | 10 | | http://www.php.net/license/3_01.txt | 11 | | If you did not receive a copy of the PHP license and are unable to | 12 | | obtain it through the world-wide-web, please send a note to | 13 | | license@php.net so we can mail you a copy immediately. | 14 | +----------------------------------------------------------------------+ 15 | | Author: Robert Eisele (https://www.xarg.org/) | 16 | +----------------------------------------------------------------------+ 17 | */ 18 | 19 | #ifdef HAVE_CONFIG_H 20 | #include "config.h" 21 | #endif 22 | 23 | extern "C" { 24 | #include "php.h" 25 | } 26 | #include "ext/standard/info.h" 27 | #include "php_facedetect.h" 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | /* for PHP 8 */ 35 | #ifndef TSRMLS_CC 36 | #define TSRMLS_CC 37 | #endif 38 | 39 | using namespace cv; 40 | 41 | CascadeClassifier cascade; 42 | 43 | static void php_facedetect(INTERNAL_FUNCTION_PARAMETERS, int return_type) { 44 | 45 | #if PHP_VERSION_ID < 70000 46 | int flen, clen; 47 | zval *array; 48 | #else 49 | size_t flen, clen; 50 | zval array; 51 | #endif 52 | zval *pArray; 53 | 54 | char *file = NULL, *casc = NULL; 55 | 56 | 57 | Mat img; 58 | Mat gray; 59 | std::vector faces; 60 | 61 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|p", &file, &flen, &casc, &clen) == FAILURE) { 62 | RETURN_NULL(); 63 | } 64 | 65 | if (access(file, R_OK) == -1) { 66 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Image file is missing or could not be read.\n"); 67 | RETURN_FALSE; 68 | } 69 | 70 | if (casc && access(casc, R_OK) == -1) { 71 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Haar-cascade file is missing or could not be read.\n"); 72 | RETURN_FALSE; 73 | } 74 | 75 | if (casc && !cascade.load(casc)) { 76 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Haar-cascade file could not be loaded.\n"); 77 | RETURN_FALSE; 78 | } 79 | 80 | if (!casc && cascade.empty()) { 81 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "No Haar-cascade file loaded.\n"); 82 | RETURN_FALSE; 83 | } 84 | 85 | img = imread(file); 86 | 87 | if (!img.data) { 88 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Image could not be loaded.\n"); 89 | RETURN_FALSE; 90 | } 91 | 92 | cvtColor(img, gray, COLOR_BGR2GRAY); 93 | equalizeHist(gray, gray); 94 | 95 | cascade.detectMultiScale(gray, faces, 1.1, 2, 0 | CASCADE_SCALE_IMAGE, Size(30, 30)); 96 | 97 | 98 | if (return_type) { 99 | 100 | array_init(return_value); 101 | 102 | for (size_t i = 0; i < faces.size(); i++) { 103 | #if PHP_VERSION_ID >= 70000 104 | array_init(&array); 105 | pArray = &array; 106 | #else 107 | MAKE_STD_ZVAL(array); 108 | pArray = array; 109 | #endif 110 | array_init(pArray); 111 | 112 | add_assoc_long(pArray, "x", faces[i].x); 113 | add_assoc_long(pArray, "y", faces[i].y); 114 | add_assoc_long(pArray, "w", faces[i].width); 115 | add_assoc_long(pArray, "h", faces[i].height); 116 | 117 | add_next_index_zval(return_value, pArray); 118 | } 119 | 120 | } else { 121 | RETVAL_LONG(faces.size()); 122 | } 123 | } 124 | 125 | PHP_INI_MH(on_cascade_change) { 126 | 127 | #if PHP_VERSION_ID < 70000 128 | if (new_value_length > 0 && cascade.load(new_value)) 129 | #else 130 | if (ZSTR_LEN(new_value) > 0 && cascade.load(ZSTR_VAL(new_value))) 131 | #endif 132 | return SUCCESS; 133 | else 134 | return FAILURE; 135 | } 136 | 137 | PHP_INI_BEGIN() 138 | PHP_INI_ENTRY("facedetect.cascade", "", PHP_INI_ALL, on_cascade_change) 139 | PHP_INI_END() 140 | 141 | 142 | #if PHP_VERSION_ID < 80000 143 | ZEND_BEGIN_ARG_INFO_EX(arginfo_face_detect, 0, 0, 1) 144 | ZEND_ARG_INFO(0, image_path) 145 | ZEND_ARG_INFO(0, cascade_path) 146 | ZEND_END_ARG_INFO() 147 | 148 | #define arginfo_face_count arginfo_face_detect 149 | 150 | #else 151 | ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_face_detect, 0, 1, MAY_BE_FALSE|MAY_BE_ARRAY) 152 | ZEND_ARG_TYPE_INFO(0, image_path, IS_STRING, 0) 153 | ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, cascade_path, IS_STRING, 1, "null") 154 | ZEND_END_ARG_INFO() 155 | 156 | ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_face_count, 0, 1, MAY_BE_FALSE|MAY_BE_LONG) 157 | ZEND_ARG_TYPE_INFO(0, image_path, IS_STRING, 0) 158 | ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, cascade_path, IS_STRING, 1, "null") 159 | ZEND_END_ARG_INFO() 160 | #endif 161 | 162 | 163 | PHP_FUNCTION(face_detect) { 164 | php_facedetect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); 165 | } 166 | 167 | PHP_FUNCTION(face_count) { 168 | php_facedetect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); 169 | } 170 | 171 | /* {{{ PHP_MINIT_FUNCTION 172 | */ 173 | PHP_MINIT_FUNCTION(facedetect) { 174 | REGISTER_INI_ENTRIES(); 175 | return SUCCESS; 176 | } 177 | /* }}} */ 178 | 179 | /* {{{ PHP_MSHUTDOWN_FUNCTION 180 | */ 181 | PHP_MSHUTDOWN_FUNCTION(facedetect) { 182 | UNREGISTER_INI_ENTRIES(); 183 | return SUCCESS; 184 | } 185 | /* }}} */ 186 | 187 | /* {{{ PHP_MINFO_FUNCTION 188 | */ 189 | PHP_MINFO_FUNCTION(facedetect) { 190 | php_info_print_table_start(); 191 | php_info_print_table_row(2, "facedetect support", "enabled"); 192 | php_info_print_table_row(2, "facedetect version", PHP_FACEDETECT_VERSION); 193 | php_info_print_table_row(2, "OpenCV version", CV_VERSION); 194 | php_info_print_table_end(); 195 | } 196 | /* }}} */ 197 | 198 | /* {{{ facedetect_functions[] 199 | * 200 | * Every user visible function must have an entry in facedetect_functions[]. 201 | */ 202 | const zend_function_entry facedetect_functions[] = { 203 | PHP_FE(face_detect, arginfo_face_detect) 204 | PHP_FE(face_count, arginfo_face_count) 205 | PHP_FE_END 206 | }; 207 | /* }}} */ 208 | 209 | /* {{{ facedetect_module_entry 210 | */ 211 | zend_module_entry facedetect_module_entry = { 212 | STANDARD_MODULE_HEADER, 213 | "facedetect", 214 | facedetect_functions, 215 | PHP_MINIT(facedetect), 216 | PHP_MSHUTDOWN(facedetect), 217 | NULL, 218 | NULL, 219 | PHP_MINFO(facedetect), 220 | PHP_FACEDETECT_VERSION, 221 | STANDARD_MODULE_PROPERTIES 222 | }; 223 | /* }}} */ 224 | 225 | #ifdef COMPILE_DL_FACEDETECT 226 | #ifdef ZTS 227 | ZEND_TSRMLS_CACHE_DEFINE() 228 | #endif 229 | extern "C" { 230 | ZEND_GET_MODULE(facedetect) 231 | } 232 | #endif 233 | 234 | /* 235 | * Local variables: 236 | * tab-width: 4 237 | * c-basic-offset: 4 238 | * End: 239 | * vim600: noet sw=4 ts=4 fdm=marker 240 | * vim<600: noet sw=4 ts=4 241 | */ 242 | -------------------------------------------------------------------------------- /php_facedetect.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | PHP Version 7 | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 1997-2018 The PHP Group | 6 | +----------------------------------------------------------------------+ 7 | | This source file is subject to version 3.01 of the PHP license, | 8 | | that is bundled with this package in the file LICENSE, and is | 9 | | available through the world-wide-web at the following url: | 10 | | http://www.php.net/license/3_01.txt | 11 | | If you did not receive a copy of the PHP license and are unable to | 12 | | obtain it through the world-wide-web, please send a note to | 13 | | license@php.net so we can mail you a copy immediately. | 14 | +----------------------------------------------------------------------+ 15 | | Author: | 16 | +----------------------------------------------------------------------+ 17 | */ 18 | 19 | #ifndef PHP_FACEDETECT_H 20 | #define PHP_FACEDETECT_H 21 | 22 | extern zend_module_entry facedetect_module_entry; 23 | #define phpext_facedetect_ptr &facedetect_module_entry 24 | 25 | #define PHP_FACEDETECT_VERSION "0.1.0" 26 | 27 | #ifdef PHP_WIN32 28 | # define PHP_FACEDETECT_API __declspec(dllexport) 29 | #elif defined(__GNUC__) && __GNUC__ >= 4 30 | # define PHP_FACEDETECT_API __attribute__ ((visibility("default"))) 31 | #else 32 | # define PHP_FACEDETECT_API 33 | #endif 34 | 35 | #ifdef ZTS 36 | #include "TSRM.h" 37 | #endif 38 | 39 | #define FACEDETECT_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(facedetect, v) 40 | 41 | #if defined(ZTS) && defined(COMPILE_DL_FACEDETECT) 42 | ZEND_TSRMLS_CACHE_EXTERN() 43 | #endif 44 | 45 | #endif /* PHP_FACEDETECT_H */ 46 | 47 | 48 | /* 49 | * Local variables: 50 | * tab-width: 4 51 | * c-basic-offset: 4 52 | * End: 53 | * vim600: noet sw=4 ts=4 fdm=marker 54 | * vim<600: noet sw=4 ts=4 55 | */ 56 | --------------------------------------------------------------------------------