I have the same error as many of the questions here: OSError: exception: access violation reading 0x000002369EF14000. However, the situation is different and I couldn't figure out why this happens. Moreover, the address appears to be different every time I run the code.
I ran the following python code and get the error above. How do I fix this issue? (Or what is the general cause for the OSError: exception: access violation reading error?)
from ctypes import *
import numpy as np
splines = CDLL('splines.dll')
splines.spline_basis.argtypes = [POINTER(c_double), POINTER(c_int), POINTER(c_int), POINTER(c_double), POINTER(c_int),
POINTER(c_int), POINTER(c_double), POINTER(c_int)]
x = np.random.rand(10)
ord = 3
knots = np.linspace(0, 1, 5)
nk = len(knots)
nx = len(x)
ind = sorted(range(x.shape[0]), key=lambda k: x[k])
sortx = x[ind]
derivs = nx
derivs = [derivs if i == 0 else np.nan for i in ind]
ncoef = nk - ord
temp = splines.spline_basis(np.array(knots).ctypes.data_as(POINTER(c_double)), POINTER(c_int)(c_int(ncoef)),
POINTER(c_int)(c_int(ord)),
sortx.ctypes.data_as(POINTER(c_double)), np.array(derivs).ctypes.data_as(POINTER(c_int)),
POINTER(c_int)(c_int(nx)), np.zeros([ord, nx]).ctypes.data_as(POINTER(c_double)),
POINTER(c_int)(c_int(nx)))
print(temp)
The dll file is compiled from the c code below, which builds a spline basis. The main function used is the spline_basis function
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "splines.h"
double* ldel, * rdel;
long orderm1;
void
diff_table(double* ti, double x, int ndiff)
{
register double* r = rdel, * l = ldel, * dpt = ti;
while (ndiff--) {
*r++ = *dpt++ - x;
*l++ = x - *--ti;
}
}
void
basis_funcs(double* ti, double x, double* b)
{
int j, r;
double saved, term;
diff_table(ti, x, orderm1);
b[0] = 1.;
for (j = 1; j <= orderm1; j++) {
saved = 0.;
for (r = 0; r < j; r++) {
term = b[r] / (rdel[r] + ldel[j - 1 - r]);
b[r] = saved + rdel[r] * term;
saved = ldel[j - 1 - r] * term;
}
b[j] = saved;
}
}
double
evaluate(double* ti, double x, double* a, int nder)
{
register double* lpt, * rpt, * apt;
register int inner;
int outer = orderm1;
while (nder--) {
for (inner = outer, apt = a, lpt = ti - outer; inner--; apt++, lpt++)
*apt = outer * (*(apt + 1) - *apt) / (*(lpt + outer) - *lpt);
outer--;
}
diff_table(ti, x, (long)outer);
while (outer--)
for (apt = a, lpt = ldel + outer, rpt = rdel, inner = outer + 1;
inner--; lpt--, rpt++, apt++)
*apt = (*(apt + 1) * *lpt + *apt * *rpt) / (*rpt + *lpt);
return(*a);
}
void
spline_value(double* knots, double* coeff, int * ncoeff,
int * order, double* x, int * nx, int * deriv,
double* y)
{
long n = *nx;
double* a, * last = knots + *ncoeff;
a = calloc(*order, sizeof(double));
orderm1 = *order - 1L; /* allocate difference tables */
rdel = calloc(orderm1, sizeof(double));
ldel = calloc(orderm1, sizeof(double));
knots += *order; /* First *order knots must be <= all x's */
while (n--) {
while (knots <= last && *knots <= *x) { knots++; coeff++; }
memcpy(a, coeff, *order);
*y++ = evaluate(knots, *x++, a, (int)*deriv);
}
free(ldel); free(rdel); free(a);
}
void spline_basis(double* knots, int * ncoeff, int * order,
double* xvals, int * derivs, int * nx,
double* basis, int * offsets)
{ /* evaluate the non-zero B-spline basis */
/* functions (or their derivatives) at */
/* xvals. */
int n = *nx, i, j;
double* dpt, * coeff, * last = knots + *ncoeff;
orderm1 = *order - 1L;
rdel = calloc(orderm1, sizeof(double));
ldel = calloc(orderm1, sizeof(double));
coeff = calloc(*order, sizeof(double));
dpt = (knots += *order); /* first *order knots must be <= all xvals */
for (; n--; xvals++, derivs++) {
while (dpt < last && *dpt <= *xvals) dpt++;
if (*derivs) { /* slow method for derivatives */
for (i = 0; i < *order; i++) {
for (j = 0; j < *order; j++) coeff[j] = 0;
coeff[i] = 1;
*basis++ = evaluate(dpt, *xvals, coeff, (int)*derivs);
}
}
else {
basis_funcs(dpt, *xvals, basis); /* fast method for value */
basis += *order;
}
*offsets++ = (long)(dpt - knots);
}
free(ldel); free(rdel); free(coeff);
}
void lin_interp(double* x, double* y, double* x0, double* y0, int * nvals)
{
int n = *nvals;
double* firstx = x;
while (n--) {
while (*x < *x0) { x++; y++; }
if (x > firstx) { x--; y--; }
if (*x > * x0) *y0++ = *y + (*(y + 1) - *y) * (*x0 - *x) / (*(x + 1) - *x);
else *y0++ = *y;
x0++;
}
}
The header file includes declaration of functions only.
void diff_table(double* ti, double x, int ndiff);
void basis_funcs(double* ti, double x, double* b);
double evaluate(double* ti, double x, double* a, int nder);
void spline_value(double* knots, double* coeff, int* ncoeff, int* order, double* x, int* nx, int* deriv, double* y);
__declspec(dllexport) void spline_basis(double* knots, int* ncoeff, int* order, double* xvals, int* derivs, int* nx, double* basis, int* offsets);
void lin_interp(double* x, double* y, double* x0, double* y0, int* nvals);
Related
I am trying to convert this C++ function into Python code but I am having trouble in doing so for the pointer and turning the python variables into uint32_t and uint8_t respectively. I am not sure how to declare the functions such that it returns uint32_t and also what to do with the pointer uint8_t *buf. Please help me in figuring out on how to convert the function, from C++ to python.
This is my C++ code:
uint32_t Functions::Do_calc(uint8_t *buf, uint32_t len){
return Do_calc(25, buf, len);
}
uint32_t Functions::Do_calc(uint32_t val, uint8_t *buf, uint32_t len){
uint32_t temp_int, c = val;
uint32_t ip_buf[128];
uint32_t j, rem = 0, tf = 0, p = 0;
rem = len;
while(rem > 0){
if(rem <= 512){
tf = rem;
}
else{
tf = 512;
}
for(j = 0; j < 128; j++){
ip_buf[j]=0;
}
for(j = 0; j < tf; j += 2){
temp = ((buf[p * 512 + (j + 3)]<<24) +
(buf[p * 512 + (j + 2)]<<16) +
(buf[p * 512 + (j + 1)]<<8) +
buf[p * 512 + j]);
ip_buf[j / 4] = temp;
}
c = c_cal(ip_buf, tf, c, 0x04C22AB9, 2, true);
p++
}
return c;
}
uint32_t Functions::c_cal(uint32_t *d_base, uint32_t d_size, uint32_t c, uint32_t poly, uint8_t c_size, bool b_r_ip)
{
unsigned long d_offset;
unsigned long d, d_temp;
unsigned char c_bit;
d = 0;
for(d_offset = 0; d_offset < d_size; (d_offset += c_size))
{
u32_d_temp = 0;
d_temp = d_base[d_offset/c_size];
if(FALSE == b_r_ip)
{
d = d_temp;
}
else
{
d = 0;
for(c_bit = 0; c_bit < (c_size << 3); c_bit++)
{
d <<= 1;
d |= (d_temp & 1);
d_temp >>= 1;
}
}
for(c_bit = 0; c_bit < (c_size << 3); c_bit++)
{
if(((c >> ((c_size << 3) - 1)) ^ d) & 1)
{
c <<= 1;
d >>= 1;
c ^= poly;
}
else
{
c <<= 1;
d >>= 1;
}
}
}
return (c & (0xFFFFFFFF >> (32 - (c_size << 3))));
}
This is my attempted Python implementation. As you can see I just did a basic implementation as I did not worry about the pointer and the size of the integer which is very much needed:
def Do_calc(buf, len):
return Do_calc(0, buf, len)
def Do_calc(val, buf, len):
ip_buf = []
c = val
p = 0
rem = len
while rem > 0:
if rem <= 512:
tf = rem
else:
tf = 512
for j in range(128):
ip_buf[j].append = 0
for j in xrange(0, tf, 2):
temp_int = ((buffer[packet * 512 + (i + 3)] << 24) +
(buffer[packet * 512 + (i + 2)] << 16) +
(buffer[packet * 512 + (i + 1)] << 8) +
buffer[packet * 512 + i])
ip_buf[j/4] = temp
c = c_cal(ip_buf, tf, c, 0x04C22AB9, 2, true)
p += 1
return c
How do I properly do the conversion after taking care of all the aspects?
How to pass 3D python array to C code then get return back?
I have researched,
Pass a 2d numpy array to c using ctypes
I have tried for 2D
Source :
- http://cboard.cprogramming.com/c-programming/61578-4-dimensional-array-contiguous-allocation.html#post438210
test1.py
import numpy as np
import numpy.ctypeslib as npct
from numpy.ctypeslib import ndpointer
import ctypes
import sys
import time
_doublepp = ndpointer(dtype=np.uintp, ndim=2, flags='C')
_dll = ctypes.CDLL("foo_test.dll")
_foobar = _dll.foobar
_foobar.argtypes = [ctypes.c_int, ctypes.c_int, _doublepp, _doublepp]
_foobar.restype = None
def foobar(x):
y = np.zeros_like(x)
print x.__array_interface__
print x.shape[0]
print x.strides
xpp = (x.__array_interface__['data'][0]
+ np.arange(x.shape[0])*x.strides[0]).astype(np.uintp)
ypp = (y.__array_interface__['data'][0]
+ np.arange(y.shape[0])*y.strides[0]).astype(np.uintp)
print xpp
print ypp
m = ctypes.c_int(x.shape[0])
n = ctypes.c_int(x.shape[1])
o = ctypes.c_int(x.shape[2])
_foobar(m, n, o, xpp, ypp)
return y
if __name__ == '__main__':
n = sys.argv[1]
n = float(n)
dim = np.sqrt(n)
s1=time.clock()
x = np.arange(n).reshape((3,3,3))
# x = np.arange(9).reshape((3,3))
y = foobar(x)
f1 = time.clock()
print 'Execution Time is ', f1-s1, ' Second'
print y[:]
foo_test.c
#include <stdio.h>
#include <stdlib.h>
#ifdef FOO_DLL
#ifdef FOO_EXPORTS
#define FOO_API __declspec(dllexport)
#else
#define FOO_API __declspec(dllimport)
#endif //For FOO_Export
#else
#define FOO_API extern
#endif //for FOO_DLL
#ifdef __cplusplus
extern "C" {
#endif
// http://cboard.cprogramming.com/c-programming/61578-4-dimensional-array-contiguous-allocation.html#post438210
void* my_malloc(char *expr, size_t size)
{
void* result = malloc(size);
printf("Malloc (%s) is size %lu, resulting %p\n", expr, (unsigned long)size, result );
return result;
}
void my_free(void* ptr)
{
printf("Freeing : %p\n", ptr);
free(ptr);
}
#define MY_MALLOC(x) my_malloc(#x, x)
#define MY_FREE(x) my_free(x)
//Create float 2D
float **array2D(int dimx, int dimy)
{
float **allx = MY_MALLOC(dimx * sizeof *allx);
float *ally = MY_MALLOC(dimx * dimy * sizeof *ally);
float **result = allx;
int x;
for(x = 0; x < dimx ; x++, ally += dimy)
{
result[x] = ally;
}
return result;
}
//create float 3D
float ***array3D(int dimx, int dimy, int dimz)
{
float ***allx = MY_MALLOC(dimx * sizeof *allx);
float **ally = MY_MALLOC(dimx * dimy * sizeof *ally);
float *allz = MY_MALLOC(dimx * dimy * dimz * sizeof *allz);
float ***result = allx;
int x, y;
for(x = 0; x < dimx ; x++, ally += dimy)
{
result[x] = ally;
for (y = 0; y <dimy ; y++, allz += dimz)
{
result[x][y] = allz;
}
}
return result;
}
void foobar(const int m, const int n, const int o, const double*** x, double*** y)
{
float ***array3d;
// int x, y;
array3d = array3D(m,n,o);
size_t i,j,k;
for(i = 0; i< m; i++)
{
for(j = 0; j < n; j++)
{
for(k = 0; k < o; k++)
{
array3d[i][j][k] = 5.0;
y[i][j][k] = array3d[i][j][k];
}
}
}
}
#ifdef __cplusplus
}
#endif
The Error said,
Traceback (most recent call last): File "test1.py", line 40, in
y = foobar(x) File "test1.py", line 30, in foobar
_foobar(m, n, o, xpp, ypp) ctypes.ArgumentError: argument 3: : argument must be an ndarray
Finally, I solved my problem, (Thanks to Evert for suggestion)
c_multiply.c
#include "c_multiply.h"
#include <stdio.h>
void ccmultiply4d(double* array, double multiplier, int m, int n, int o, int p) {
int i, j,k, l ;
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
for (k = 0; k < o; k++)
for (l = 0; l < p; l++)
{
array[i*m*n*o + j*n*o + k*o + l] = array[i*m*n*o + j*n*o + k*o + l] ;
printf("Array[%d*%d*%d*%d + %d*%d*%d + %d*%d + %d] * Multiplier = Array[%d] * %d = %.lf\n", i,m,n,o,j,n,o,k,o,l, i*m*n*o + j*n*o + k*o + l, multiplier, array[i*m*n*o + j*n*o + k*o + l]);
}
}
test.pyx
import cython
# import both numpy and the Cython declarations for numpy
import numpy as np
cimport numpy as np
# declare the interface to the C code
cdef extern from "c_multiply.h":
void ccmultiply4d(double* array, double value, int m, int n, int o, int p)
#cython.boundscheck(False)
#cython.wraparound(False)
def multiply(np.ndarray[double, ndim=4, mode="c"] input not None, double value):
"""
multiply (arr, value)
Takes a numpy arry as input, and multiplies each elemetn by value, in place
param: array -- a 2-d numpy array of np.float64
param: value -- a number that will be multiplied by each element in the array
"""
cdef int m, n, o, p
m, n, o, p = input.shape[0], input.shape[1], input.shape[2], input.shape[3]
ccmultiply4d(&input[0,0,0,0], value, m, n, o, p)
I know this question has been asked before, but I don't find a useful solution. The full error is :
Executing: "/home/mint/Documents/test_sensor/cycl_test/top_block.py"
Using Volk machine: avx_64_mmx_orc
Traceback (most recent call last):
File "/home/mint/Documents/test_sensor/cycl_test/top_block.py", line 87, in <module>
tb = top_block()
File "/home/mint/Documents/test_sensor/cycl_test/top_block.py", line 61, in __init__
self.cycl_MME_cpp_0 = cycl.MME_cpp(1000, 16, 0.1)
AttributeError: 'module' object has no attribute 'MME_cpp'
I have found some possible reasons from previous questions:
mismatching of function parameter(including referencing function in .cc and .h)
swig problem
callbacks in .xml file
nm -C -u libgnuradio-.so
I've checked the first 3 reasons, but I'm not sure how to find out the undefined symblos using the last methods. There is part of the outcome:
U gsl_linalg_SV_decomp
U gsl_matrix_alloc
U gsl_matrix_set
U gsl_matrix_set_zero
U gsl_vector_alloc
U gsl_vector_get
Does this means all the gsl functions are undefined? If so how can I deal with it?
Except for the four reasons,is there any other hints about my questions?
I appreciate your help.
addendum:
1.MME_cpp_impl.cc
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gnuradio/io_signature.h>
#include "MME_cpp_impl.h"
#include <stdio.h>
#include <math.h>
#include <gsl/gsl_matrix.h>
#include <gsl/gsl_vector.h>
#include <gsl/gsl_linalg.h>
namespace gr {
namespace cycl {
MME_cpp::sptr
MME_cpp::make(int Ns, int M, float Pfa)
{
return gnuradio::get_initial_sptr
(new MME_cpp_impl(Ns, M, Pfa));
}
/*
* The private constructor
*/
MME_cpp_impl::MME_cpp_impl(int Ns, int M, float Pfa)
: gr::sync_block("MME_cpp",
gr::io_signature::make(1, 1, sizeof(float)),
gr::io_signature::make(1, 1, sizeof(float))),
d_Ns(Ns), d_M(M), d_Pfa(Pfa)
{}
/*
* Our virtual destructor.
*/
MME_cpp_impl::~MME_cpp_impl()
{
}
/*This function gives the CDF value for the pfa in input*/
float
TracyWidom (float p){
float pd, tw;
tw = 0.45;
pd = 1 - p;
if (pd >= 0.01 && pd <= 0.05){
tw = 18*(pd - (17/75)); printf("a - %f\n", tw);
}else if (pd >= 0.05 && pd <= 0.1){
tw = 8*(pd - (179/400)); printf("b - %f\n", tw);
}else if (pd >= 0.1 && pd <= 0.3){
tw = (87/20)*(pd - (643/870)); printf("c - %f\n", tw);
}else if (pd >= 0.3 && pd <= 0.5){
tw = (16/5)*(pd - (287/320)); printf("d - %f\n", tw);
}else if (pd >= 0.5 && pd <= 0.7){
tw = (17/5)*(pd - (297/340)); printf("e - %f\n", tw);
}else if (pd >= 0.7 && pd <= 0.9){
tw = (5.2)*(pd - (0.813)); printf("f - %f\n", tw);
}else if (pd >= 0.9 && pd <= 0.95){
tw = (53/5)*(pd - (909/1060)); printf("g - %f\n", tw);
}else if (pd >= 0.95 && pd <= 1){
tw = 26*(pd - (593/650)); printf("h - %f\n", tw);
}else{
printf ("wrong pfa value: it must be between 0 and 1\n");
printf ("the pfa value standard is 0.1\n");
tw = (53/5)*(0.9 - (909/1060));
}
return tw;
}
/*this function calculates the threshold for the test
the inputs are:
ns = numbers of samples/L;
L = length of the correlation function;
pfa = probability of false alarm*/
float
gamma (int ns, int L, float tw){
float A, B, C, ratio1, ratio2, g;
A = sqrt(ns)+sqrt(L*ns);
B = sqrt(ns)-sqrt(L*ns);
C = ns*ns*L;
ratio1 = pow(A,2)/pow(B,2);
ratio2 = 1+( pow(A,-0.667) / pow(C,0.167) )*tw;
g = ratio1*ratio2;
return g;
}
/*This function makes the detection test*/
float
test (float r, float t){
float decision;
if(r > -1){
if(r <= t){
decision = 0;
}
else{
decision = 1;
}
}
return decision;}
//-------------end functions-----------
int
MME_cpp_impl::work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
const float *in = (const float *) input_items[0];
float *out = (float *) output_items[0];
//float cov;
//int ninputs = input_items.size ();
//for(int i=0; i<noutput_items*Ns; ++i){
// cov = compute_convariance(in[i]);
//int lenght = floor(d_samples / d_L) * d_L;
float vett[d_Ns];
int lenght = floor(d_Ns / d_M) ;
int p, j, k=0;
float thr, lmax, lmin, ratio=-1, TW, mem=0;
// char c[1];
gsl_matrix * hankel = gsl_matrix_alloc (lenght,d_M);
gsl_matrix * V = gsl_matrix_alloc (d_M,d_M);
gsl_vector * S = gsl_vector_alloc (d_M);
gsl_vector * temp = gsl_vector_alloc (d_M);
//FILE *story;
gsl_matrix_set_zero (hankel);
TW = TracyWidom (d_Pfa);
thr = gamma(lenght, d_M, TW); //calculate the threshold
for (int i = 0; i < noutput_items; i++){
vett[k]=in[i];
k++;
if (k >= lenght*d_M){
k = 0;
// story = fopen("filestory.txt", "a");
for( p=0; p<lenght; p++ ){
for( j=0; j<d_M; j++ ){
gsl_matrix_set (hankel, p, j, vett[p+j]);
}
}
gsl_linalg_SV_decomp (hankel, V, S, temp);//using SDV to calculate eigenvalue
lmax = gsl_vector_get(S, 0);//maximal eigenvalue
lmin = gsl_vector_get(S, (d_M -1));//minimal eigenvalue
ratio = lmax/lmin;
mem = test(ratio, thr);
//fprintf(story, "%f - ratio=%f - soglia=%f\n ", mem, ratio, thr);
//fclose(story);
}
out[i] = mem;
}
// Tell runtime system how many output items we produced.
return noutput_items;
}
} /* namespace cycl /
} / namespace gr */
2.MME_cpp_impl.h
#ifndef INCLUDED_CYCL_MME_CPP_IMPL_H
#define INCLUDED_CYCL_MME_CPP_IMPL_H
#include <cycl/MME_cpp.h>
namespace gr {
namespace cycl {
class MME_cpp_impl : public MME_cpp
{
private:
int d_Ns, d_M;
float d_Pfa;
public:
MME_cpp_impl(int Ns, int M, float Pfa);
~MME_cpp_impl();
int Ns() const { return d_Ns; }
void set_Ns(int Ns) { d_Ns = Ns; }
int M() const { return d_M; }
void set_M(int M) { d_M = M; }
float Pfa() const { return d_Pfa; }
void set_Pfa(float Pfa) { d_Pfa = Pfa; }
// Where all the action really happens
int work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
//float compute_covariance(float & d, int i, int j);
friend float TracyWidom (float p);
friend float gamma (int ns, int L, float tw);
friend float test (float r, float t);
};
float TracyWidom (float p);
float gamma (int ns, int L, float tw);
float test (float r, float t);
} // namespace cycl
} // namespace gr
#endif /* INCLUDED_CYCL_MME_CPP_IMPL_H */
3.MME_cpp.h
#ifndef INCLUDED_CYCL_MME_CPP_H
#define INCLUDED_CYCL_MME_CPP_H
#include <cycl/api.h>
#include <gnuradio/sync_block.h>
namespace gr {
namespace cycl {
/*!
* \brief <+description of block+>
* \ingroup cycl
*
*/
class CYCL_API MME_cpp : virtual public gr::sync_block
{
public:
typedef boost::shared_ptr<MME_cpp> sptr;
/*!
* \brief Return a shared_ptr to a new instance of cycl::MME_cpp.
*
* To avoid accidental use of raw pointers, cycl::MME_cpp's
* constructor is in a private implementation
* class. cycl::MME_cpp::make is the public interface for
* creating new instances.
*/
static sptr make(int Ns, int M, float Pfa);
virtual int Ns() const = 0;
virtual void set_Ns(int Ns) = 0;
virtual int M() const = 0;
virtual void set_M(int M) = 0;
virtual float Pfa() const = 0;
virtual void set_Pfa(float Pfa) = 0;
};
} // namespace cycl
} // namespace gr
#endif /* INCLUDED_CYCL_MME_CPP_H */
4.cycl_MME_cpp.xml
<?xml version="1.0"?>
<block>
<name>MME_cpp</name>
<key>cycl_MME_cpp</key>
<category>cycl</category>
<import>import cycl</import>
<make>cycl.MME_cpp($Ns, $M, $Pfa)</make>
<callback>set_Ns($Ns)</callback>
<callback>set_M($M)</callback>
<callback>set_Pfa($Pfa)</callback>
<param>
<name>Number of samples</name>
<key>Ns</key>
<type>int</type>
</param>
<param>
<name>Length of correlation function</name>
<key>M</key>
<type>int</type>
</param>
<param>
<name>false probability</name>
<key>Pfa</key>
<type>float</type>
</param>
<sink>
<name>in</name>
<type>float</type>
</sink>
<source>
<name>out</name>
<type>float</type>
</source>
</block>
I had the same problem while developing a block. I noticed that the CMake script complained that the swig library is missing. Although this was not a fatal error, it does not work without it.
After installing swig I could use my module: sudo apt-get install swig
This is likely due to the path that your .so is installed by default. I recently ran into this issue, and found that /usr/local/lib was not in my /etc/ld.so.conf by default (Arch Linux). After updating /etc/ld.so.conf, I ran:
sudo ldconfig
and the issue was resolved.
somehow I get different results using numpy's linalg.inv and OpenCv's Mat::inv, e.g. given a matrix S:
[747.8561839552103, 359.9317804054358, 204.6165451419812, 241.7376332155144, 126.132733370211, 81.57610562583466;
359.9317804054358, 204.6165451419812, 140.4788277943211, 126.132733370211, 80.55127348381332, 47.7506303038364;
204.6165451419812, 140.4788277943211, 116.7472083846913, 80.55127348381332, 63.86033402962857, 35.56970826526131;
241.7376332155144, 126.132733370211, 80.55127348381332, 81.57610562583466, 47.7506303038364, 29.55106507912703;
126.132733370211, 80.55127348381332, 63.86033402962857, 47.7506303038364, 35.56970826526131, 20.31193086803655;
81.57610562583466, 47.7506303038364, 35.56970826526131, 29.55106507912703, 20.31193086803655, 12]
OpenCV S.inv() results in
[-19562262532715.65, 137.3094415699439, -44015090698406.93, 78249050130618.84, 88030181396160.73, -78249050129617.47;
124.2797501878658, 19.14093204142484, 301.2737811201993, -531.0713785028685, -686.3332686269306, 655.5356524828615;
-44015090698424.45, 330.6065529853437, -99033954070961.39, 176060362793110.9, 198067908140346.2, -176060362790691.7;
78249050130642.06, -583.2397919514979, 176060362793093.2, -312996200521532.5, -352120725583424.9, 312996200517305.3;
88030181396256.19, -744.9706630355842, 198067908140482.2, -352120725583702.1, -396135816277430.2, 352120725578288.9;
-78249050129732.52, 707.7008280168318, -176060362790880.5, 312996200517672.6, 352120725578424.8, -312996200512573.6]
numpy's linalg.inv results in:
[[2685109332201.37, -23.46, 6041495997420.42, -10740437328763.82, -12082991994731.51, 10740437328597.41]
[-32.56, 19.14, -51.60, 96.23, 19.43, 28.24]
[6041495997407.60, -31.13, 13593365994129.85, -24165983989574.97, -27186731988120.73, 24165983989366.80]
[-10740437328747.65, 59.84, -24165983989589.86, 42961749314884.59, 48331967978891.43, -42961749314440.71]
[-12082991994663.29, -21.50, -27186731988024.93, 48331967978691.32, 54373463976152.90, -48331967978849.60]
[10740437328516.33, 64.62, 24165983989235.66, -42961749314181.06, -48331967978757.62, 42961749314608.99]]
Okay, now some detail of how I stumbled across this:
I am working on a routine to fit an ellipse given a point set; I have transferred code from: http://nicky.vanforeest.com/misc/fitEllipse/fitEllipse.html to C++:
template <typename InputIt>
std::array<double, 6> fit_ellipse(InputIt first, InputIt last) {
typedef double value_type;
auto num_points = std::distance(first, last);
cv::Mat_<value_type> D(num_points, 6);
size_t row(0);
for (auto it(first); it != last; ++it, ++row) {
auto &point = *it;
auto &x = std::get<0>(point);
auto &y = std::get<1>(point);
D(row, 0) = x * x;
D(row, 1) = x * y;
D(row, 2) = y * y;
D(row, 3) = x;
D(row, 4) = y;
D(row, 5) = 1.f;
}
auto S = D.t() * D;
cv::Mat_<value_type> C = cv::Mat_<value_type>::zeros(6, 6);
C(0, 2) = C(2, 0) = 2; C(1, 1) = -1;
cv::Mat Sinv = S.inv();
std::cout << "Sinv:" << Sinv << std::endl;
cv::Mat_<value_type> E, V; cv::eigen(Sinv * C, E, V);
int n;
cv::minMaxIdx(cv::abs(E), nullptr, nullptr, nullptr, &n);
return {{V(n, 0), V(n, 1), V(n, 2), V(n, 3), V(n, 4), V(n, 5)}};
}
To comparison the Python code:
import numpy as np
from numpy.linalg import eig, inv
def fitEllipse(x,y):
x = x[:,np.newaxis]
y = y[:,np.newaxis]
D = np.hstack((x*x, x*y, y*y, x, y, np.ones_like(x)))
S = np.dot(D.T,D)
C = np.zeros([6,6])
C[0,2] = C[2,0] = 2; C[1,1] = -1
Sinv = inv(S)
print("Sinv: %s" % Sinv)
E, V = eig(np.dot(Sinv, C))
n = np.argmax(np.abs(E))
a = V[:,n]
return a
The code is run initializing following points:
TEST(fit_ellipse, test_example) {
namespace bmc = boost::math::constants;
typedef std::array<double, 2> point_type;
std::vector<point_type> points;
auto arc = .8;
for (size_t i(0); i < 12; ++i) {
auto r = i * arc * bmc::pi<double>() / 12;
points.push_back({1.5 * std::cos(r) + 2, std::sin(r) + 1});
}
auto a = fit_ellipse(points.begin(), points.end());
std::cout << "Parameters: "
for (auto &p : a)
std::cout << p << ' ';
std::cout << std::endl;
}
Same in Python:
R = np.arange(0, arc * np.pi, arc * np.pi / 12)
x = 1.5 * np.cos(R) + 2
y = np.sin(R) + 1.
print("Parameters: %s" % fitEllipse(x,y))
Any Idea what I am missing out?
I am looking to use some C code that returns multiple arrays of unknown size. Because there are multiple arrays, I think I need to use passed in pointers, and I'm not sure how to combine that with malloc, which is used to setup the arrays.
This is some representative C code:
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
//gcc -fPIC -shared -o array_test_c.so array_test_c.c
void return_array(int * outdata1v, int * outdata2v) {
int i;
int N = 10;
int * mydatav2, * mydatav3;
mydatav2 = (int *) malloc(sizeof(int) * N);
mydatav3 = (int *) malloc(sizeof(int) * N);
for (i = 0; i<N; i++){
mydatav2[i] = i;
mydatav3[i] = i*2;
}
//this doesn't work which makes sense
outdata1v = mydatav2;
outdata2v = mydatav3;
}
And I'm trying to hook it to Python with something along these lines (this does not work):
import os
import ctypes
#for c interface
test_module = ctypes.cdll.LoadLibrary(
os.path.join(os.path.dirname(__file__), './array_test_c.so'))
outdata1 = (ctypes.c_int * 0)()
outdata2 = (ctypes.c_int * 0)()
test_module.return_array(outdata1, outdata2)
outdata1 = (ctypes.c_int*10).from_address(ctypes.addressof(outdata1))
print "out", outdata1[-1], outdata1, outdata2
This does not work, and I can never get 20 to print out. Any ideas?
test.c
#include <stdlib.h>
#define N 10
void test(int *size, int **out1, int **out2) {
int i;
int *data1, *data2;
data1 = (int *)malloc(sizeof(int) * N);
data2 = (int *)malloc(sizeof(int) * N);
for (i = 0; i < N; i++){
data1[i] = i;
data2[i] = i * 2;
}
*size = N;
*out1 = data1;
*out2 = data2;
}
test.py
from ctypes import CDLL, POINTER, c_int, byref
dll = CDLL('test.so')
data1 = POINTER(c_int)()
data2 = POINTER(c_int)()
size = c_int()
dll.test(byref(size), byref(data1), byref(data2))
for i in range(size.value):
print i, data1[i], data2[i]
Edit: You should consider providing a function to free the malloc'd data. So you can then do, e.g. dll.cleanup(data1, data2)
You need pointers to pointers:
void return_array(int **outdata1v, int **outdata2v) {
int i;
int N = 10;
int * mydatav2, * mydatav3;
mydatav2 = (int *) malloc(sizeof(int) * N);
mydatav3 = (int *) malloc(sizeof(int) * N);
for (i = 0; i<N; i++){
mydatav2[i] = i;
mydatav3[i] = i*2;
}
*outdata1v = mydatav2;
*outdata2v = mydatav3;
}
I don't know about the python part.