Support for raw chinese_whispers
This commit introduces chinese_whispers method without any "helpers" on PHP side. Users needs to take care of everything (building edges from 128D face chip vector, for example), but this is exposed for people that need low-level call and want to calculate distances and build edges in PHP directly.
This commit is contained in:
104
src/chinese_whispers.cc
Normal file
104
src/chinese_whispers.cc
Normal file
@@ -0,0 +1,104 @@
|
||||
|
||||
#include "../php_pdlib.h"
|
||||
#include "chinese_whispers.h"
|
||||
|
||||
#include <zend_exceptions.h>
|
||||
#include <dlib/clustering.h>
|
||||
#include <iostream>
|
||||
|
||||
using namespace dlib;
|
||||
using namespace std;
|
||||
|
||||
PHP_FUNCTION(dlib_chinese_whispers)
|
||||
{
|
||||
zval *edges_arg;
|
||||
HashTable *edges_arg_hash;
|
||||
|
||||
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");
|
||||
return;
|
||||
}
|
||||
|
||||
edges_arg_hash = Z_ARRVAL_P(edges_arg);
|
||||
|
||||
try {
|
||||
HashPosition pos;
|
||||
zval *edge;
|
||||
HashTable *edge_hash;
|
||||
|
||||
// Iterate for all given edges, check if they are valid and put them to edges
|
||||
//
|
||||
for (
|
||||
zend_hash_internal_pointer_reset_ex(edges_arg_hash, &pos);
|
||||
(edge = zend_hash_get_current_data_ex(edges_arg_hash, &pos)) != nullptr;
|
||||
zend_hash_move_forward_ex(edges_arg_hash, &pos)) {
|
||||
// Check that each given edge is actually array
|
||||
//
|
||||
if (Z_TYPE_P(edge) != IS_ARRAY) {
|
||||
zend_throw_exception_ex(
|
||||
zend_ce_exception,
|
||||
0 TSRMLS_CC,
|
||||
"Each edge provided in array needs to be numeric array of 2 elements");
|
||||
return;
|
||||
}
|
||||
|
||||
edge_hash = Z_ARRVAL_P(edge);
|
||||
|
||||
// Check that there are two elements in this edge
|
||||
//
|
||||
if (zend_hash_num_elements(edge_hash) != 2) {
|
||||
zend_throw_exception_ex(
|
||||
zend_ce_exception,
|
||||
0 TSRMLS_CC,
|
||||
"Edges need to contain exactly two elements");
|
||||
return;
|
||||
}
|
||||
|
||||
// Check that this is regular array with integer keys
|
||||
//
|
||||
if (!zend_hash_index_exists(edge_hash, 0) ||
|
||||
!zend_hash_index_exists(edge_hash, 1)) {
|
||||
zend_throw_exception_ex(
|
||||
zend_ce_exception,
|
||||
0 TSRMLS_CC,
|
||||
"Edge should be numeric array with integer keys");
|
||||
return;
|
||||
}
|
||||
|
||||
zval *elem_i = zend_hash_index_find(edge_hash, 0);
|
||||
zval *elem_j = zend_hash_index_find(edge_hash, 1);
|
||||
|
||||
// Check that both elements in array are longs
|
||||
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,
|
||||
"Both elements in each edge must be of long type");
|
||||
return;
|
||||
}
|
||||
|
||||
// Finally, put extracted elements to edges
|
||||
edges.push_back(sample_pair(Z_LVAL_P(elem_i), Z_LVAL_P(elem_j)));
|
||||
}
|
||||
|
||||
chinese_whispers(edges, labels);
|
||||
|
||||
// Preparing and generating response array containing labels
|
||||
//
|
||||
array_init(return_value);
|
||||
for (auto label = labels.begin(); label != labels.end(); label++) {
|
||||
add_next_index_long(return_value, *label);
|
||||
}
|
||||
} catch (exception& e)
|
||||
{
|
||||
zend_throw_exception_ex(zend_ce_exception, 0 TSRMLS_CC, e.what());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
13
src/chinese_whispers.h
Normal file
13
src/chinese_whispers.h
Normal file
@@ -0,0 +1,13 @@
|
||||
//
|
||||
// Created by branko at kokanovic dot org on 2018/7/19.
|
||||
//
|
||||
|
||||
#ifndef PHP_DLIB_CHINESE_WHISPERS_H
|
||||
#define PHP_DLIB_CHINESE_WHISPERS_H
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(dlib_chinese_whispers_arginfo, 0, 0, 1)
|
||||
ZEND_ARG_INFO(0, edges)
|
||||
ZEND_END_ARG_INFO()
|
||||
PHP_FUNCTION(dlib_chinese_whispers);
|
||||
|
||||
#endif //PHP_DLIB_CHINESE_WHISPERS_H
|
||||
Reference in New Issue
Block a user