Arquivos
2021-10-28 16:44:08 +02:00

242 linhas
6.2 KiB
C++

/*
+----------------------------------------------------------------------+
| PHP Version 7 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2018 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Robert Eisele (https://www.xarg.org/) |
+----------------------------------------------------------------------+
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
extern "C" {
#include "php.h"
}
#include "ext/standard/info.h"
#include "php_facedetect.h"
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/objdetect.hpp>
/* for PHP 8 */
#ifndef TSRMLS_CC
#define TSRMLS_CC
#endif
using namespace cv;
CascadeClassifier cascade;
static void php_facedetect(INTERNAL_FUNCTION_PARAMETERS, int return_type) {
#if PHP_VERSION_ID < 70000
int flen, clen;
zval *array;
#else
size_t flen, clen;
zval array;
#endif
zval *pArray;
char *file = NULL, *casc = NULL;
Mat img;
Mat gray;
std::vector<Rect> faces;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|p", &file, &flen, &casc, &clen) == FAILURE) {
RETURN_NULL();
}
if (access(file, R_OK) == -1) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Image file is missing or could not be read.\n");
RETURN_FALSE;
}
if (casc && access(casc, R_OK) == -1) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Haar-cascade file is missing or could not be read.\n");
RETURN_FALSE;
}
if (casc && !cascade.load(casc)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Haar-cascade file could not be loaded.\n");
RETURN_FALSE;
}
if (!casc && cascade.empty()) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "No Haar-cascade file loaded.\n");
RETURN_FALSE;
}
img = imread(file);
if (!img.data) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Image could not be loaded.\n");
RETURN_FALSE;
}
cvtColor(img, gray, COLOR_BGR2GRAY);
equalizeHist(gray, gray);
cascade.detectMultiScale(gray, faces, 1.1, 2, 0 | CASCADE_SCALE_IMAGE, Size(30, 30));
if (return_type) {
array_init(return_value);
for (size_t i = 0; i < faces.size(); i++) {
#if PHP_VERSION_ID >= 70000
array_init(&array);
pArray = &array;
#else
MAKE_STD_ZVAL(array);
pArray = array;
#endif
array_init(pArray);
add_assoc_long(pArray, "x", faces[i].x);
add_assoc_long(pArray, "y", faces[i].y);
add_assoc_long(pArray, "w", faces[i].width);
add_assoc_long(pArray, "h", faces[i].height);
add_next_index_zval(return_value, pArray);
}
} else {
RETVAL_LONG(faces.size());
}
}
PHP_INI_MH(on_cascade_change) {
#if PHP_VERSION_ID < 70000
if (new_value_length > 0 && cascade.load(new_value))
#else
if (ZSTR_LEN(new_value) > 0 && cascade.load(ZSTR_VAL(new_value)))
#endif
return SUCCESS;
else
return FAILURE;
}
PHP_INI_BEGIN()
PHP_INI_ENTRY("facedetect.cascade", "", PHP_INI_ALL, on_cascade_change)
PHP_INI_END()
#if PHP_VERSION_ID < 80000
ZEND_BEGIN_ARG_INFO_EX(arginfo_face_detect, 0, 0, 1)
ZEND_ARG_INFO(0, image_path)
ZEND_ARG_INFO(0, cascade_path)
ZEND_END_ARG_INFO()
#define arginfo_face_count arginfo_face_detect
#else
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_face_detect, 0, 1, MAY_BE_FALSE|MAY_BE_ARRAY)
ZEND_ARG_TYPE_INFO(0, image_path, IS_STRING, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, cascade_path, IS_STRING, 1, "null")
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_face_count, 0, 1, MAY_BE_FALSE|MAY_BE_LONG)
ZEND_ARG_TYPE_INFO(0, image_path, IS_STRING, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, cascade_path, IS_STRING, 1, "null")
ZEND_END_ARG_INFO()
#endif
PHP_FUNCTION(face_detect) {
php_facedetect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
}
PHP_FUNCTION(face_count) {
php_facedetect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
}
/* {{{ PHP_MINIT_FUNCTION
*/
PHP_MINIT_FUNCTION(facedetect) {
REGISTER_INI_ENTRIES();
return SUCCESS;
}
/* }}} */
/* {{{ PHP_MSHUTDOWN_FUNCTION
*/
PHP_MSHUTDOWN_FUNCTION(facedetect) {
UNREGISTER_INI_ENTRIES();
return SUCCESS;
}
/* }}} */
/* {{{ PHP_MINFO_FUNCTION
*/
PHP_MINFO_FUNCTION(facedetect) {
php_info_print_table_start();
php_info_print_table_row(2, "facedetect support", "enabled");
php_info_print_table_row(2, "facedetect version", PHP_FACEDETECT_VERSION);
php_info_print_table_row(2, "OpenCV version", CV_VERSION);
php_info_print_table_end();
}
/* }}} */
/* {{{ facedetect_functions[]
*
* Every user visible function must have an entry in facedetect_functions[].
*/
const zend_function_entry facedetect_functions[] = {
PHP_FE(face_detect, arginfo_face_detect)
PHP_FE(face_count, arginfo_face_count)
PHP_FE_END
};
/* }}} */
/* {{{ facedetect_module_entry
*/
zend_module_entry facedetect_module_entry = {
STANDARD_MODULE_HEADER,
"facedetect",
facedetect_functions,
PHP_MINIT(facedetect),
PHP_MSHUTDOWN(facedetect),
NULL,
NULL,
PHP_MINFO(facedetect),
PHP_FACEDETECT_VERSION,
STANDARD_MODULE_PROPERTIES
};
/* }}} */
#ifdef COMPILE_DL_FACEDETECT
#ifdef ZTS
ZEND_TSRMLS_CACHE_DEFINE()
#endif
extern "C" {
ZEND_GET_MODULE(facedetect)
}
#endif
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
*/