/usr/include/gamera/knnmodule.hpp is in python-gamera-dev 1:3.4.2+git20160808.1725654-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | /*
*
* Copyright (C) 2001-2005 Ichiro Fujinaga, Michael Droettboom, and Karl MacMillan
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
This holds various functions for using k-NN and Python together.
*/
#ifndef KWM12172002_knnmodule
#define KWM12172002_knnmodule
#include <Python.h>
#include "knn.hpp"
using namespace Gamera;
using namespace Gamera::kNN;
/*
This enum is for selecting between the various methods of
computing the distance between two floating-point feature
vectors.
*/
enum DistanceType {
CITY_BLOCK,
EUCLIDEAN,
FAST_EUCLIDEAN
};
/*
get the feature vector from an image. image argument _must_ an image - no
type checking is performed.
*/
inline int image_get_fv(PyObject* image, double** buf, Py_ssize_t* len) {
ImageObject* x = (ImageObject*)image;
if (PyObject_CheckReadBuffer(x->m_features) < 0) {
return -1;
}
if (PyObject_AsReadBuffer(x->m_features, (const void**)buf, len) < 0) {
PyErr_SetString(PyExc_TypeError, "knn: Could not use image as read buffer.");
return -1;
}
if (*len == 0) {
return -1;
}
*len = *len / sizeof(double);
return 0;
}
/*
get the id_name from an image. The image argument _must_ be an image -
no type checking is performed.
*/
inline int image_get_id_name(PyObject* image, char** id_name, int* len) {
ImageObject* x = (ImageObject*)image;
// PyList_Size shoule type check the argument
if (PyList_Size(x->m_id_name) < 1) {
PyErr_SetString(PyExc_TypeError, "knn: id_name not a list or list is empty.");
return -1;
}
PyObject* id_tuple = PyList_GET_ITEM(x->m_id_name, 0);
if (PyTuple_Size(id_tuple) != 2) {
PyErr_SetString(PyExc_TypeError, "knn: id_name is not a tuple or is the wrong size.");
return -1;
}
PyObject* id = PyTuple_GET_ITEM(id_tuple, 1);
*id_name = PyString_AsString(id);
if (*id_name == 0) {
PyErr_SetString(PyExc_TypeError, "knn: could not get string from id_name tuple.");
return -1;
}
*len = PyString_GET_SIZE(id);
return 0;
}
/*
Compute the distance between two feature vectors.
*/
inline void compute_distance(DistanceType distance_type, const double* known_buf,
int known_len, const double* unknown_buf, double* distance,
const int* selections, const double* weights) {
if (distance_type == CITY_BLOCK) {
*distance = city_block_distance(known_buf, known_buf + known_len, unknown_buf,
selections, weights);
} else if (distance_type == FAST_EUCLIDEAN) {
*distance = fast_euclidean_distance(known_buf, known_buf + known_len, unknown_buf,
selections, weights);
} else {
*distance = euclidean_distance(known_buf, known_buf + known_len, unknown_buf,
selections, weights);
}
}
/*
Compute the distance between a known and an unknown image
with weights. This version takes an image and a buffer
for the unknown image.
*/
inline int compute_distance(DistanceType distance_type, PyObject* known,
double* unknown_buf, double* distance,
int* selections, double* weights, Py_ssize_t unknown_len) {
double* known_buf;
Py_ssize_t known_len;
if (image_get_fv(known, &known_buf, &known_len) < 0)
return -1;
if (unknown_len != known_len) {
PyErr_SetString(PyExc_IndexError, "Array lengths do not match");
return -1;
}
compute_distance(distance_type, known_buf, known_len, unknown_buf, distance,
selections, weights);
return 0;
}
/*
Compute the distance between a known and an unknown image with weights. This version takes
an image and a buffer for the unknown image. Arguments must be images - no type checking
is performed.
*/
inline int compute_distance(DistanceType distance_type, PyObject* known,
PyObject* unknown, double* distance,
int* selections, int selections_len,
double* weights, int weights_len) {
double *known_buf, *unknown_buf;
Py_ssize_t known_len, unknown_len;
if (image_get_fv(known, &known_buf, &known_len) < 0)
return -1;
if (image_get_fv(unknown, &unknown_buf, &unknown_len) < 0)
return -1;
if (unknown_len != known_len) {
PyErr_SetString(PyExc_IndexError, "Array lengths do not match");
return -1;
}
if (unknown_len != selections_len) {
PyErr_SetString(PyExc_IndexError, "Array lengths do not match");
return -1;
}
if (unknown_len != weights_len) {
PyErr_SetString(PyExc_IndexError, "Array lengths do not match");
return -1;
}
compute_distance(distance_type, known_buf, known_len, unknown_buf, distance,
selections, weights);
return 0;
}
#endif
|