Im not very good with python, but for this project I need to use a python GUI to test my program. Its compiling without any errors, but its giving errors when I go to test it in the GUI. The objective of the program is to create a English to French dictionary from a .txt file that has all the translations/definitions. My code is as follows. If anyone could help, that would be great.
These are the errors I am getting:
Exception in Tkinter callback
Traceback (most recent call last):
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk/Tkinter.py", line 1470, in __call__
return self.func(*args)
File "Dictionary.py", line 33, in <lambda>
lambda e, s=self: s.translate(english, french))
File "Dictionary.py", line 69, in translate
clearall(english, french)
NameError: global name 'clearall' is not defined
For further information, I'm supposed to check these conditions:
1)no command line arguments and 2) unsuccessful file openings.
Dictionary.cpp:
#include "HashTable.h"
#include "DictionaryEntry.h"
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
int main( int argc, char** argv )
{
HashTable <DictionaryEntry> table;
DictionaryEntry dictEntry;
string temp;
string entry;
string translation;
vector <string> engWords;
string uentry;
int randNum;
ifstream inputStream;
//If command line is empty, error
if( argc <= 1)
{
cout << "Invalid entry." << endl;
return 0;
}
inputStream.open(argv[1]);
//If no file is opened, error
/*if( !inputStream )
{
cout << "Invalid file." << endl;
return 0;
}*/
while( !inputStream.eof( ) )
{
getline( inputStream, temp );
unsigned location = temp.find_first_of( '\t' );
entry = temp.substr( 0, location );
int end = temp.length( );
translation = temp.substr( location + 1, end );
dictEntry.set( entry, translation );
table.insert( dictEntry );
engWords.push_back( entry );
}
while( 1 )
{
cout << "Insert english word: ";
cin >> uentry;
DictionaryEntry search;
search.set( uentry, "");
if( uentry == "random" )
{
randNum = rand( ) % engWords.size( );
temp = engWords.at( randNum );
search.set( temp, "" );
dictEntry = table.retrieve( search );
cout << dictEntry.getEntry( ) << endl;
cout << dictEntry.getTranslation( ) << endl;
}
else
{
dictEntry = table.retrieve( search );
if( dictEntry.getEntry( ) != "" )
{
cout << dictEntry.getEntry( ) << endl;
cout << dictEntry.getTranslation( ) << endl;
}
else
{
cout << "\n";
cout << "\n";
}
}
}
}
List.h:
#ifndef LIST_H
#define LIST_H
using namespace std;
template <typename Object>
class List
{
private:
struct Node
{
Object data;
Node *prev;
Node *next;
Node(const Object & d = Object{ }, Node * p = nullptr, Node * n = nullptr )
: data{ d }, prev{ p }, next{ n } { }
Node( Object && d, Node * p = nullptr, Node * n = nullptr )
: data{ std::move( d ) }, prev{ p }, next{ n } { }
};
public:
class const_iterator
{
public:
const_iterator( ) : current{ nullptr }
{ }
const Object & operator* ( ) const
{ return retrieve( ); }
const_iterator & operator++ ( )
{
current = current->next;
return *this;
}
const_iterator operator++ (int)
{
const_iterator old = *this;
++( *this );
return old;
}
bool operator== (const const_iterator & rhs ) const
{ return current == rhs.current; }
bool operator!= ( const const_iterator & rhs ) const
{ return !( *this == rhs ); }
protected:
Node *current;
Object & retrieve( ) const
{return current->data;}
const_iterator(Node *p ) : current{ p }
{ }
friend class List<Object>;
};
class iterator : public const_iterator
{
public:
iterator( )
{ }
Object & operator* ( )
{ return const_iterator::retrieve( ); }
const Object & operator* ( ) const
{ return const_iterator::operator*( ); }
iterator & operator++ ( )
{
this->current = this->current->next;
return *this;
}
iterator operator++ ( int )
{
iterator old = *this;
++( *this );
return old;
}
iterator operator--()
{
const_iterator::current = const_iterator::current->prev;
return *this;
}
iterator operator--(int)
{
iterator old = *this;
--(*this);
return old;
}
protected:
iterator( Node *p ) : const_iterator{ p }
{ }
friend class List<Object>;
};
public:
List( )
{ init( ); }
~List( )
{
clear( );
delete head;
delete tail;
}
List( const List & rhs )
{
init( );
for( auto & x : rhs )
push_back( x );
}
List & operator= ( const List & rhs )
{
List copy = rhs;
std::swap( *this, copy );
return *this;
}
List ( List && rhs )
: theSize{ rhs.theSize }, head{rhs.head }, tail{rhs.tail }
{
rhs.theSize = 0;
rhs.head = nullptr;
rhs.tail = nullptr;
}
List & operator= ( List && rhs )
{
std::swap( theSize, rhs.theSize );
std::swap( head, rhs.head );
std::swap( tail, rhs.tail );
return *this;
}
iterator begin( )
{ return { head->next }; }
const_iterator begin( ) const
{ return { head->next }; }
iterator end( )
{ return { tail }; }
const_iterator end( ) const
{ return { tail }; }
int size( ) const
{ return theSize; }
bool empty( ) const
{ return size( ) == 0; }
void clear( )
{
while( !empty( ) )
pop_front( );
}
Object & front( )
{ return *begin( ); }
const Object & front( ) const
{ return *begin( ); }
Object & back( )
{ return *--end( ); }
const Object & back( ) const
{ return *--end( ); }
void push_front( const Object & x )
{ insert( begin( ), x ); }
void push_front( Object && x )
{ insert( begin( ), std::move( x ) ); }
void push_back( const Object & x )
{ insert( end( ), x ); }
void push_back( Object && x )
{ insert( end( ), std::move( x ) ); }
void pop_front( )
{ erase( begin( ) ); }
void pop_back( )
{ erase( --end( ) ); }
//Insert x before itr
iterator insert( iterator itr, const Object & x )
{
Node *p = itr.current;
theSize++;
return { p->prev = p->prev->next = new Node{ x, p->prev, p } };
}
//Insert x before itr
iterator insert( iterator itr, Object && x )
{
Node *p = itr.current;
theSize++;
return { p->prev = p->prev->next = new Node{ std::move( x ), p->prev, p } };
}
//Erase item at itr
iterator erase( iterator itr )
{
Node *p = itr.current;
iterator retVal{ p->next };
p->prev->next = p->next;
p->next->prev = p->prev;
delete p;
theSize--;
return retVal;
}
iterator erase( iterator from, iterator to )
{
for( iterator itr = from; itr != to; )
itr.erase( itr );
return to;
}
iterator find( const Object & x )
{
iterator start= begin();
while(start!=end()){
if(x==*start)
return start;
start++;
}
return start;
}
/*
iterator find( string & x )
{
iterator start = begin();
while( start != end( ) ) {
if( strcasecmp( x.c_str( ),( *start ).getWord( ).c_str( ) )==0 )
return start;
else
start++;
}
return start;
}
*/
const_iterator find(const Object & x) const
{
const_iterator start=begin();
while(start!=end()){
if(x==*start)
return start;
start++;
}
return start;
}
/*
const_iterator find(const string & x){
const_iterator start = const_iterator(head);
while( start != end()){
if(strcasecmp(x.c_str(),(*start).getWord().c_str())==0)
return start;
else
start++;
}
return start;
}
*/
private:
int theSize;
Node *head;
Node *tail;
void init( )
{
theSize = 0;
head = new Node;
tail = new Node;
head->next = tail;
tail->prev = head;
}
};
#endif
HashTable.h:
#ifndef HASHTABLE_H
#define HASHTABLE_H
#include <vector>
#include <string>
#include "List.h"
#include "DictionaryEntry.h"
using namespace std;
//checks if a value is prime
bool isPrime(int n){
if( n==2 || n==3)
return true;
if( n==1 || n%2 == 0)
return false;
for(int i=3; i*i<n; i+=2)
if(n%i == 0)
return false;
return true;
}
//finds the next prime number
int nextPrime (int n) {
if( n%2==0)
n++;
while( !isPrime(n))
n+=2;
return n;
}
template <typename HashedObj>
class HashTable
{
public:
//constructor (explicit so no implicit conversion)
explicit HashTable( int size = 3500) : tableSize(size), currentSize(size), theLists(size) { }
//empty the Hashtable
void makeEmpty( )
{
currentSize=0;
//clear each linked list from hastable
for(int i=0; i<tableSize; i++)
theLists[i].clear( );
}
//search for x in Hashtable
bool contains( const HashedObj & x ) const{
//assign reference variable to rename the complicated object
const List<HashedObj> & whichList = theLists[ myhash( x ) ];
//return whether x already exists in the list
return whichList.find( x ) != whichList.end( );
}
//insert x into Hashtable (true if successful, false if already exists)
bool insert( const HashedObj & x ) {
//assign reference variable to rename the complicated object
List<HashedObj> & whichList = theLists[ myhash( x ) ];
//if x already exists in the list, return false
if( whichList.find( x ) != whichList.end() )
return false;
//otherwise push to list
whichList.push_front( x );
//rehash if new size is greater than hashtable size
if( ++currentSize >tableSize ) {
rehash( );
}
return true;
}
//remove x from Hashtable (true if successful, false if not found)
bool remove( const HashedObj & x ) {
//assign reference variable to rename the complicated object
List<HashedObj> & whichList = theLists[ myhash( x ) ];
//iterator is at end of list (i.e., not found)
if( whichList.find(x) == whichList.end() )
return false;
//erase x
whichList.erase( whichList.find (x) );
--currentSize;
return true;
}
HashedObj & retrieve( HashedObj & obj)
{
return *(theLists[myhash(obj)].find(obj));
}
private:
//The vector of linked-lists hashtable
vector<List<HashedObj> > theLists;
int currentSize;
int tableSize;
//Because coming with new stuff is hard <--Haha
void rehash( ){
vector<List<HashedObj> > oldLists=theLists;
int oldtableSize = tableSize;
tableSize = nextPrime( 2* oldtableSize );
//Create new double-sized, empty table
theLists.resize( tableSize );
for( int i=0; i<tableSize; i++ )
theLists[i].clear();
//copy table over
currentSize = 0;
for( int i=0; i<oldtableSize; i++ ){
while( !oldLists[i].empty() ){
insert( oldLists[i].front() );
oldLists[i].pop_front();
}
}
}
//call hash function and makes sure values fit in table
int myhash( const HashedObj & x ) const
{
int hashVal = hash2(x); //call hash function
//make sure the hash values fit into HashTable
hashVal %= tableSize;
if( hashVal < 0 )
{
hashVal += tableSize;
}
return hashVal;
}
/*
int myhash( const string & x ) const
{
int hashVal = hash( x );
hashVal %= tableSize;
if( hashVal < 0 )
{
hashVal += tableSize;
}
return hashVal;
}
*/
};
int hash2( const string & key )
{
int hashVal = 0;
for( int i = 0; i < key.length( ); i++ )
{
hashVal = 37 * hashVal + key[i];
}
return hashVal;
}
int hash2( const DictionaryEntry word )
{
return hash2(word.getEntry());
}
int hash2(int key)
{
return key;
}
#endif
DictionaryEntry.h:
#ifndef DICTIONARYENTRY_H
#define DICTIONARYENTRY_H
#include <string>
#include <iostream>
#include "HashTable.h"
using namespace std;
class DictionaryEntry
{
public:
DictionaryEntry( )
{
entry = "";
translation = "";
}
DictionaryEntry( const DictionaryEntry & rhs )
{
entry = rhs.entry;
translation = rhs.translation;
}
void set( string ent, string trans )
{
entry = ent;
translation = trans;
}
const string & getTranslation( ) const
{
return translation;
}
const string & getEntry( ) const
{
return entry;
}
bool operator== ( const DictionaryEntry & rhs ) const
{
return getEntry( ) == rhs.getEntry( );
}
bool operator!= ( const DictionaryEntry & rhs ) const
{
return (getEntry() != rhs.getEntry() );
}
private:
string entry;
string translation;
};
#endif
and Dictionary.py:
#!/usr/bin/python
from Tkinter import *
import subprocess
# general function for frame generation
def frame(root, side):
w = Frame(root)
w.pack(side=side, expand=YES, fill=BOTH)
return w
# general function for button generation
def button(root, side, text, command=None):
w = Button(root, text=text, command=command)
w.pack(side=side, expand=YES, fill=BOTH)
return w
# main class for GUI
class Translator(Frame):
def __init__(self):
Frame.__init__(self)
self.pack(expand=YES, fill=BOTH)
self.master.title("English-French Translator")
self.master.iconname("English-French Translator")
Label(self, text='English').pack(side=TOP, expand=YES, fill=BOTH)
english = StringVar()
Entry(self, relief=SUNKEN, textvariable=english).pack(side=TOP, expand=YES, fill=BOTH)
buttonsF = frame(self, TOP)
btn = button(buttonsF, LEFT, 'Translate')
btn.bind('<ButtonRelease-1>',
lambda e, s=self: s.translate(english, french))
clearF = frame(self, TOP)
btn = button(buttonsF, LEFT, 'Clear')
btn.bind('<ButtonRelease-1>',
lambda e, s=self: s.clearall(english, french))
randF = frame(self, TOP)
btn = button(buttonsF, LEFT, 'Flash Me (TM)')
btn.bind('<ButtonRelease-1>',
lambda e, s=self: s.random(english, french))
Label(self, text='French').pack(side=TOP, expand=YES, fill=BOTH)
french = StringVar()
Message(self, relief=SUNKEN, textvariable=french, width=200).pack(side=TOP, expand=YES, fill=BOTH)
# clear all text boxes
def clearall(self, english, french):
english.set('')
french.set('')
# translate english to french
def translate(self, english, french):
if (len(english.get()) > 0):
try:
# send english word to subprocess
process.stdin.write('%s\n'%english.get())
# read line of output from subprocess (original text)
original=process.stdout.readline()
# read line of output from subprocess (translated text)
translation=process.stdout.readline()
# set english textbox
english.set(original.rstrip())
# set french textbox
french.set(translation.rstrip())
except:
clearall(english, french)
def random(self, english, french):
try:
process.stdin.write('random\n')
original=process.stdout.readline()
translation=process.stdout.readline()
english.set(original.rstrip())
french.set(translation.rstrip())
except:
clearall(english, french)
if __name__ == '__main__':
args='French.txt'
process=subprocess.Popen('Dictionary %s'%args, shell=True,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
Translator().mainloop()
The error message is telling you exactly what's wrong: "global name 'clearall' is not defined". You have to ask yourself, 'why does python think it's not defined?" In this case, the clue is that it thinks clearall is a global function. Why? Because that's how you are using it.
In looking at your code, it appears you have a "clearall" method as part of an object, so likely all you need to do is change clearall(...) to self.clearall(...) everywhere you call clearall.
Related
I am using PyUnicode_FromString() and PyUnicode_AsUTF8() while doing python extension from CPP, which is crashing when we use more than one thread .
Is PyUnicode_FromString() and PyUnicode_AsUTF8() thread safe ?
predictGplaceBoxClockregion(int iterationNo,
std::string y_value,
std::string gplaceFeatureFile,
int levelNo,
bool analytical)
{
std::string result = "";
PyObject *d = PyDict_New();
if (iterationNo == 1) {
y_value = "ClockRegion_MultiLabel_iter1";
} else {
y_value = "ClockRegion_MultiLabel_iter2";
}
PyDict_SetItemString(d, "ip", PyUnicode_FromString(gplaceFeatureFile.c_str()));
PyDict_SetItemString(d, "y", PyUnicode_FromString(y_value.c_str()));
PyDict_SetItem(d, PyUnicode_FromString("iterNo"), PyLong_FromLong(iterationNo));
PyObject *methodcall = PyObject_CallMethod(instance, "bindScript", "O", d);
if ( methodcall == nullptr) {
PyErr_Print();
}
result = PyUnicode_AsUTF8(methodcall);
Py_DECREF (d);
return result;
}
I have a program written in python with OpenCV. I want to add a feature which is otsu thresholding with mask. So, I get a code from here written in c++. I tried to convert it as python, but it's too slow (because of python). Finally, I make up my mind to use c++ with python. I try to embedding, and I find pyopencv_to() function. But, I can't use it because of PyArray_Check(). When program entered this function, die immediately. It doesn't give any error message. I guess it may be segmentation fault. Many stack overflow's answers says that "use import_array()". But it doesn't work for me.
Here is my code.
convert.cpp
#include <Python.h>
#include "numpy/ndarrayobject.h"
#include "opencv2/core/core.hpp"
#include "convert.hpp"
static PyObject* opencv_error = 0;
static int failmsg(const char *fmt, ...)
{
char str[1000];
va_list ap;
va_start(ap, fmt);
vsnprintf(str, sizeof(str), fmt, ap);
va_end(ap);
PyErr_SetString(PyExc_TypeError, str);
return 0;
}
class PyAllowThreads
{
public:
PyAllowThreads() : _state(PyEval_SaveThread()) {}
~PyAllowThreads()
{
PyEval_RestoreThread(_state);
}
private:
PyThreadState* _state;
};
class PyEnsureGIL
{
public:
PyEnsureGIL() : _state(PyGILState_Ensure()) {}
~PyEnsureGIL()
{
PyGILState_Release(_state);
}
private:
PyGILState_STATE _state;
};
#define ERRWRAP2(expr) \
try \
{ \
PyAllowThreads allowThreads; \
expr; \
} \
catch (const cv::Exception &e) \
{ \
PyErr_SetString(opencv_error, e.what()); \
return 0; \
}
using namespace cv;
static PyObject* failmsgp(const char *fmt, ...)
{
char str[1000];
va_list ap;
va_start(ap, fmt);
vsnprintf(str, sizeof(str), fmt, ap);
va_end(ap);
PyErr_SetString(PyExc_TypeError, str);
return 0;
}
static size_t REFCOUNT_OFFSET = (size_t)&(((PyObject*)0)->ob_refcnt) +
(0x12345678 != *(const size_t*)"\x78\x56\x34\x12\0\0\0\0\0")*sizeof(int);
static inline PyObject* pyObjectFromRefcount(const int* refcount)
{
return (PyObject*)((size_t)refcount - REFCOUNT_OFFSET);
}
static inline int* refcountFromPyObject(const PyObject* obj)
{
return (int*)((size_t)obj + REFCOUNT_OFFSET);
}
class NumpyAllocator : public MatAllocator
{
public:
NumpyAllocator() {}
~NumpyAllocator() {}
void allocate(int dims, const int* sizes, int type, int*& refcount,
uchar*& datastart, uchar*& data, size_t* step)
{
PyEnsureGIL gil;
int depth = CV_MAT_DEPTH(type);
int cn = CV_MAT_CN(type);
const int f = (int)(sizeof(size_t)/8);
int typenum = depth == CV_8U ? NPY_UBYTE : depth == CV_8S ? NPY_BYTE :
depth == CV_16U ? NPY_USHORT : depth == CV_16S ? NPY_SHORT :
depth == CV_32S ? NPY_INT : depth == CV_32F ? NPY_FLOAT :
depth == CV_64F ? NPY_DOUBLE : f*NPY_ULONGLONG + (f^1)*NPY_UINT;
int i;
npy_intp _sizes[CV_MAX_DIM+1];
for( i = 0; i < dims; i++ )
_sizes[i] = sizes[i];
if( cn > 1 )
{
/*if( _sizes[dims-1] == 1 )
_sizes[dims-1] = cn;
else*/
_sizes[dims++] = cn;
}
PyObject* o = PyArray_SimpleNew(dims, _sizes, typenum);
if(!o)
CV_Error_(CV_StsError, ("The numpy array of typenum=%d, ndims=%d can not be created", typenum, dims));
refcount = refcountFromPyObject(o);
npy_intp* _strides = PyArray_STRIDES(o);
for( i = 0; i < dims - (cn > 1); i++ )
step[i] = (size_t)_strides[i];
datastart = data = (uchar*)PyArray_DATA(o);
}
void deallocate(int* refcount, uchar*, uchar*)
{
PyEnsureGIL gil;
if( !refcount )
return;
PyObject* o = pyObjectFromRefcount(refcount);
Py_INCREF(o);
Py_DECREF(o);
}
};
NumpyAllocator g_numpyAllocator;
enum { ARG_NONE = 0, ARG_MAT = 1, ARG_SCALAR = 2 };
int init_numpy() {
import_array();
return 0;
}
const static int numpy_initialized = init_numpy();
int pyopencv_to(const PyObject* o, Mat& m, const char* name, bool allowND)
{
if(!o || o == Py_None)
{
if( !m.data )
m.allocator = &g_numpyAllocator;
return true;
}
if( !PyArray_Check(o) ) // this line makes error without message
{
failmsg("%s is not a numpy array", name);
return false;
}
// NPY_LONG (64 bit) is converted to CV_32S (32 bit)
int typenum = PyArray_TYPE(o);
int type = typenum == NPY_UBYTE ? CV_8U : typenum == NPY_BYTE ? CV_8S :
typenum == NPY_USHORT ? CV_16U : typenum == NPY_SHORT ? CV_16S :
typenum == NPY_INT || typenum == NPY_LONG ? CV_32S :
typenum == NPY_FLOAT ? CV_32F :
typenum == NPY_DOUBLE ? CV_64F : -1;
if( type < 0 )
{
failmsg("%s data type = %d is not supported", name, typenum);
return false;
}
int ndims = PyArray_NDIM(o);
if(ndims >= CV_MAX_DIM)
{
failmsg("%s dimensionality (=%d) is too high", name, ndims);
return false;
}
int size[CV_MAX_DIM+1];
size_t step[CV_MAX_DIM+1], elemsize = CV_ELEM_SIZE1(type);
const npy_intp* _sizes = PyArray_DIMS(o);
const npy_intp* _strides = PyArray_STRIDES(o);
bool transposed = false;
for(int i = 0; i < ndims; i++)
{
size[i] = (int)_sizes[i];
step[i] = (size_t)_strides[i];
}
if( ndims == 0 || step[ndims-1] > elemsize ) {
size[ndims] = 1;
step[ndims] = elemsize;
ndims++;
}
if( ndims >= 2 && step[0] < step[1] )
{
std::swap(size[0], size[1]);
std::swap(step[0], step[1]);
transposed = true;
}
if( ndims == 3 && size[2] <= CV_CN_MAX && step[1] == elemsize*size[2] )
{
ndims--;
type |= CV_MAKETYPE(0, size[2]);
}
if( ndims > 2 && !allowND )
{
failmsg("%s has more than 2 dimensions", name);
return false;
}
m = cv::Mat(ndims, size, type, PyArray_DATA(o), step);
if( m.data )
{
m.u->refcount = *refcountFromPyObject(o);
m.addref(); // protect the original numpy array from deallocation
// (since Mat destructor will decrement the reference counter)
};
m.allocator = &g_numpyAllocator;
if( transposed )
{
cv::Mat tmp;
tmp.allocator = &g_numpyAllocator;
transpose(m, tmp);
m = tmp;
}
return true;
}
PyObject* pyopencv_from(const Mat& m)
{
if( !m.data )
Py_RETURN_NONE;
Mat temp, *p = (Mat*)&m;
if(!(p->u->refcount) || p->allocator != &g_numpyAllocator)
{
temp.allocator = &g_numpyAllocator;
ERRWRAP2(m.copyTo(temp));
p = &temp;
}
p->addref();
return pyObjectFromRefcount(&(p->u->refcount));
}
threshold.cpp
#include <Python.h>
#include "opencv2/opencv.hpp"
#include "convert.hpp"
#include "numpy/ndarrayobject.h"
using namespace std;
using namespace cv;
double otsu_8u_with_mask(const Mat1b src, const Mat1b& mask)
{
const int N = 256;
int M = 0;
int i, j, h[N] = { 0 };
for (i = 0; i < src.rows; i++)
{
const uchar* psrc = src.ptr(i);
const uchar* pmask = mask.ptr(i);
for (j = 0; j < src.cols; j++)
{
if (pmask[j])
{
h[psrc[j]]++;
++M;
}
}
}
double mu = 0, scale = 1. / (M);
for (i = 0; i < N; i++)
mu += i * (double)h[i];
mu *= scale;
double mu1 = 0, q1 = 0;
double max_sigma = 0, max_val = 0;
for (i = 0; i < N; i++)
{
double p_i, q2, mu2, sigma;
p_i = h[i] * scale;
mu1 *= q1;
q1 += p_i;
q2 = 1. - q1;
if (std::min(q1, q2) < FLT_EPSILON || std::max(q1, q2) > 1. - FLT_EPSILON)
continue;
mu1 = (mu1 + i * p_i) / q1;
mu2 = (mu - q1 * mu1) / q2;
sigma = q1 * q2*(mu1 - mu2)*(mu1 - mu2);
if (sigma > max_sigma)
{
max_sigma = sigma;
max_val = i;
}
}
return max_val;
}
static PyObject * otsu_with_mask(PyObject *self, PyObject * args) {
PyObject pySrc, pyMask;
Mat src, mask;
import_array();
if (!PyArg_ParseTuple(args, "OO", &pySrc, &pyMask))
return NULL;
pyopencv_to(&pySrc, src, "source");
pyopencv_to(&pyMask, mask, "mask");
double thresh = otsu_8u_with_mask(src, mask);
return Py_BuildValue("i", thresh);
}
static PyMethodDef ThresholdMethods[] = {
{"otsu_with_mask", otsu_with_mask, METH_VARARGS, "Otsu thresholding with mask."},
{ NULL, NULL, 0, NULL}
};
static struct PyModuleDef thresholdModule = {
PyModuleDef_HEAD_INIT,
"customThreshold",
"Thresholding module.",
-1,
ThresholdMethods
};
PyMODINIT_FUNC PyInit_customThreshold(void) {
return PyModule_Create(&thresholdModule);
}
convert.hpp
#ifndef __CONVERT_HPP__
#define __CONVERT_HPP__
#include <Python.h>
#include "opencv2/opencv.hpp"
using namespace cv;
int pyopencv_to(const PyObject* o, Mat& m, const char* name = "<unknown>", bool allowND=true);
PyObject* pyopencv_from(const Mat& m);
#endif
Why do you choose to use C++ with Python wrap to do this simple task? I think you could achieve the same result easily using Python only...?
I assume you want to use adaptive thresholding method in OpenCV.
First of all, you can compute the adaptive threshold value of the input gray image. The value can be computed by the following function:
def compute_otsu_value(im_gray):
hist = cv2.calcHist([im_gray], [0], None, [256], [0, 256])
hist_norm = hist.ravel() / hist.max()
cum_sum_mat = hist_norm.cumsum()
fn_min = np.inf
thresh = -1
for i in xrange(1, 256):
p1, p2 = np.hsplit(hist_norm, [i])
q1, q2 = cum_sum_mat[i], cum_sum_mat[255] - cum_sum_mat[i]
if q1 == 0 or q2 == 0:
continue
b1, b2 = np.hsplit(np.arange(256), [i])
m1, m2 = np.sum(p1 * b1) / q1, np.sum(p2 * b2) / q2
v1, v2 = np.sum(((b1-m1)**2)*p1)/q1, np.sum(((b2-m2)**2)*p2)/q2
fn = v1 * q1 + v2 * q2
if fn < fn_min:
fn_min = fn
thresh = i
return thresh
Finally, in the main() function, you can load the input image as a gray image, and get the threshold image accordingly.
im_gray = cv2.imread("input.png", 0)
otsu_value = comput_otsu_values(im_gray)
im_th = cv2.threshold(im_gray, otsu_value, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
In Ubuntu 14.04, I wrote a C file called hash.c:
/* hash.c: hash table with linear probing */
typedef struct {
void *key;
void *value;
} ht_entry;
typedef struct {
ht_entry *table;
int len;
int num_entries;
int (*hash_fn)(void *key);
int (*key_cmp)(void *k1, void *k2);
} hashtable;
and compiled it with
gcc -shared hash.c -o test.so -fPIC
Afterwards, I tried to load test.so in a Python script (for testing), but I got the following error: "OSError: .../test.so: undefined symbol: hash_fn"
hash_fn is a function pointer in the hashtable struct. It is referenced a number of times by functions later in the file.
I do not understand why this error is happening. I have Googled but all other cases either concern C++ or includes. In my case I just have 1 C file that includes only stdio and stdlib.
here is the FULL code.
When I comment out all but hash_create and print_info, it loads succesfully. When I uncomment find(), it the error happens.
(print_info is just for testing that ctypes works)
/* hash.c: hash table with linear probing */
#include <stdio.h>
#include <stdlib.h>
typedef struct {
void *key;
void *value;
} ht_entry;
typedef struct {
ht_entry *table;
int len;
int num_entries;
int (*hash_fn)(void *key);
int (*key_cmp)(void *k1, void *k2);
} hashtable;
static void close_gap(hashtable *ht, int i);
static int find(hashtable *ht, void *key);
hashtable* hash_create(int len, int (*hash_fn)(void*), int (*key_cmp)(void*, void*))
{
hashtable* ht = (hashtable*) malloc(sizeof(hashtable));
ht->len = len;
ht->table = calloc(len, sizeof(ht_entry));
ht->hash_fn = hash_fn;
ht->key_cmp = key_cmp;
ht->table[0].key = 2;
ht->table[0].value = 3;
return ht;
}
void print_info(hashtable *ht)
{
printf("%d, %d, %d\n", ht->len, ht->table[0].key, ht->table[0].value);
}
void* hash_retrieve(hashtable* ht, void *key)
{
int i = find(ht, key);
if(i < 0) {
return NULL;
}
return ht->table[i].value;
}
void hash_insert(hashtable* ht, void *key, void *value)
{
if(ht->num_entries == ht->len) {
return;
}
int i = hash_fn(key) % ht->len;
while(ht->table[i].key != NULL) {
i = (i + i) % ht->len;
}
ht->table[i].key = key;
ht->table[i].value = value;
}
void hash_remove(hashtable *ht, void *key)
{
int i = find(ht, key);
if(i < 0) {
return;
}
ht->table[i].key = 0;
ht->table[i].value = 0;
close_gap(ht, i);
}
static int find(hashtable *ht, void *key)
{
int i = hash_fn(key) % ht->len;
int num_checked = 0;
while(ht->table[i].key && num_checked != ht->len) {
if(!ht->key_cmp(ht->table[i].key, key)) {
return i;
}
num_checked++;
i = (i + i) % ht->len;
}
return -1;
}
static void close_gap(hashtable *ht, int i)
{
int j = (i + 1) % ht->len;
while(ht->table[j].key) {
int loc = ht->hash_fn(ht->table[j].key);
if((j > i && (loc <= i || loc > j)) || (j < i && (loc <= i && loc > j))) {
ht->table[i] = ht->table[j];
ht->table[j].key = 0;
ht->table[j].value = 0;
close_gap(ht, j);
return;
}
}
}
When I use your compilation line I get five warnings. There are several problems here. First you are trying to assign an int to void * in several places. That raises a warning, and it would crash at runtime because you are passing 2 and 3 as addresses.
Second, you are calling hash_fn in a couple of places instead of ht->hash_fn. That causes the linker error, but you should consider my other changes, otherwise it will crash at runtime with a SIGSEGV:
/* hash.c: hash table with linear probing */
#include <stdio.h>
#include <stdlib.h>
typedef struct {
void *key;
void *value;
} ht_entry;
typedef struct {
ht_entry *table;
int len;
int num_entries;
int (*hash_fn)(void *key);
int (*key_cmp)(void *k1, void *k2);
} hashtable;
static void close_gap(hashtable *ht, int i);
static int find(hashtable *ht, void *key);
hashtable* hash_create(int len, int (*hash_fn)(void*), int (*key_cmp)(void*, void*))
{
hashtable* ht = (hashtable*) malloc(sizeof(hashtable));
ht->len = len;
ht->table = calloc(len, sizeof(ht_entry));
ht->hash_fn = hash_fn;
ht->key_cmp = key_cmp;
// <<< Code changed here
/*
ht->table[0].key = 2;
ht->table[0].value = 3;
*/
{
int *p = malloc(sizeof(int));
*p = 2;
ht->table[0].key = p;
p = malloc(sizeof(int));
*p = 3;
ht->table[0].value = p;
}
// end of code change
return ht;
}
void print_info(hashtable *ht)
{
// <<<< Code changed
printf("%d, %d, %d\n", ht->len,
*(int *)ht->table[0].key, *(int *)ht->table[0].value);
}
void* hash_retrieve(hashtable* ht, void *key)
{
int i = find(ht, key);
if(i < 0) {
return NULL;
}
return ht->table[i].value;
}
void hash_insert(hashtable* ht, void *key, void *value)
{
if(ht->num_entries == ht->len) {
return;
}
// <<< Code changed
int i = ht->hash_fn(key) % ht->len;
while(ht->table[i].key != NULL) {
i = (i + i) % ht->len;
}
ht->table[i].key = key;
ht->table[i].value = value;
}
void hash_remove(hashtable *ht, void *key)
{
int i = find(ht, key);
if(i < 0) {
return;
ht->table[i].key = 0;
ht->table[i].value = 0;
close_gap(ht, i);
}
static int find(hashtable *ht, void *key)
{
// <<< Code changed
int i = ht->hash_fn(key) % ht->len;
int num_checked = 0;
while(ht->table[i].key && num_checked != ht->len) {
if(!ht->key_cmp(ht->table[i].key, key)) {
return i;
}
num_checked++;
i = (i + i) % ht->len;
}
return -1;
}
static void close_gap(hashtable *ht, int i)
{
int j = (i + 1) % ht->len;
while(ht->table[j].key) {
int loc = ht->hash_fn(ht->table[j].key);
if((j > i && (loc <= i || loc > j)) || (j < i && (loc <= i && loc > j))) {
ht->table[i] = ht->table[j];
ht->table[j].key = 0;
ht->table[j].value = 0;
close_gap(ht, j);
return;
}
}
}
I only coded around the errors and warnings, I did not check the logic. You will see that I have used malloc to allocate memory for key and value. Obviously you will need memory management on these two (i.e. free()).
I'm using embedded python interpreter in my app (iOS to be detailed).
Sometimes sys.exit(1) is invoked in interpreted script and it finishes the whole app process instead of stopping PyObject_callObject() invocation. I've tried to check errors using PyErr_Occured but it did not help.
How to prevent sys.exit(N) to finish the whole process in embedded python?
NSString *outputFile = nil;
for (int i=0; i<args.count; i++) {
if ([#"-o" isEqualToString:args[i]]) {
outputFile = args[i + 1];
break;
}
}
PyEval_AcquireLock();
PyThreadState *subState = Py_NewInterpreter();
PyObject *pModuleName, *pModule, *pFunc;
// init python
NSString *pythonHome = [[[NSBundle mainBundle] bundlePath] stringByAppendingString:#"/"];
Py_SetProgramName("python");
char *cPythonHome = (char*)[pythonHome UTF8String];
setenv("PYTHONPATH", cPythonHome, 1); // VERY IMPORTANT !!!
Py_SetPythonHome(cPythonHome);
NSString *libsPath = [pythonHome stringByAppendingString:#"lib/python2.7"];
if (!Py_IsInitialized())
Py_Initialize();
// invoke
int result = 0;
NSString *scriptFilename = args[1];
NSString *moduleName = [[scriptFilename lastPathComponent] stringByDeletingPathExtension];
pModuleName = PyString_FromString([moduleName UTF8String]); // module (script) name
pModule = PyImport_Import(pModuleName);
if (PyErr_Occurred())
PyErr_Print();
if (pModule != NULL) {
pFunc = PyObject_GetAttrString(pModule, "main__"); // module must have "def main__(args)"
if (pFunc != NULL && PyCallable_Check(pFunc)) {
// prepare args
PyObject *pArgs = PyList_New(args.count-1);
for (int i=0; i<args.count-1; i++) {
NSString *arg_i = args[i + 1]; // skip first argument (it's program name)
PyObject *pEachArg = PyString_FromString([arg_i UTF8String]);
PyList_SetItem(pArgs, i, pEachArg);
// WARNING: don't Py_DECREF for each argument
}
// for some reason arguments should be passed as s Tuple
PyObject *pTuple = PyTuple_New(1);
PyTuple_SetItem(pTuple, 0, pArgs);
// call func
NSLog(#"Invoke %# via main__(args)", scriptFilename);
PyObject *pyResult = PyObject_CallObject(pFunc, pTuple); // process killed here !
if (pyResult == NULL || PyErr_Occurred()) {
// print error
PyErr_Print();
// fix error
PyErr_Clear();
if (PyErr_ExceptionMatches(PyExc_SystemExit)) {
result = 3; // error: system.exit() called
} else
result = 4; // error: unknown exception
}
if (pyResult != NULL)
Py_DECREF(pyResult);
Py_DECREF(pTuple);
Py_DECREF(pArgs);
} else
result = 2; // error: can't find "def main__()" in module
if (pFunc != NULL)
Py_XDECREF(pFunc);
} else
result = 1; // error: can't import module
if (pModule != NULL)
Py_DECREF(pModule);
Py_DECREF(pModuleName);
// restore parent interpreter
Py_EndInterpreter(subState);
PyEval_ReleaseLock();
I had to hack Python sources and create my own function:
int MyPyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit, PyCompilerFlags *flags)
{
PyObject *m, *d, *v;
const char *ext;
int set_file_name = 0, ret, len;
m = PyImport_AddModule("__main__");
if (m == NULL)
return -1;
d = PyModule_GetDict(m);
if (PyDict_GetItemString(d, "__file__") == NULL) {
PyObject *f = PyString_FromString(filename);
if (f == NULL)
return -1;
if (PyDict_SetItemString(d, "__file__", f) < 0) {
Py_DECREF(f);
return -1;
}
set_file_name = 1;
Py_DECREF(f);
}
len = strlen(filename);
ext = filename + len - (len > 4 ? 4 : 0);
/*
if (maybe_pyc_file(fp, filename, ext, closeit)) {
// Try to run a pyc file. First, re-open in binary
if (closeit)
fclose(fp);
if ((fp = fopen(filename, "rb")) == NULL) {
fprintf(stderr, "python: Can't reopen .pyc file\n");
ret = -1;
goto done;
}
// Turn on optimization if a .pyo file is given
if (strcmp(ext, ".pyo") == 0)
Py_OptimizeFlag = 1;
v = run_pyc_file(fp, filename, d, d, flags);
} else { */
v = PyRun_FileExFlags(fp, filename, Py_file_input, d, d,
closeit, flags);
//}
if (v == NULL) {
//PyErr_Print(); // crashed here!
ret = -1;
goto done;
}
Py_DECREF(v);
if (Py_FlushLine())
PyErr_Clear();
ret = 0;
done:
if (set_file_name && PyDict_DelItemString(d, "__file__"))
PyErr_Clear();
return ret;
}
I had to use _SimpleFile instead of _SimpleString but i believe you can change _SimpleString in similar way.
The reason was PyErr_Print which caused app crash. The one drawback is that i had to comment pyc file checking and usage as maybe_pyc_file is not exported and is unavailable.
One more note: if SystemExit was raised (by sys.exit(1) f.e.) don't use PyErr_Print. Use the next checking:
if (PyErr_Occurred()) {
pythonSuccess = NO;
if (PyErr_ExceptionMatches(PyExc_SystemExit)) {
NSLog(#"sys.exit() in python");
} else {
// print error
PyErr_Print();
}
// fix error
PyErr_Clear();
}
If you have better solution, let us know.
So I've got some c code that looks like this:
#pragma comment(linker, "/SECTION:.SHARED,RWS")
#pragma data_seg(".SHARED")
HMODULE hInstance = 0;
HHOOK hKeyboardHook = 0;
int lastKey = 0;
int keyFlags = 0;
HHOOK hMouseHook = 0;
int mouseMsgID = 0;
MOUSEHOOKSTRUCT *mHookPt;
MOUSEHOOKSTRUCT mHookStruct;
#pragma data_seg()
BOOL WINAPI DllMain(HANDLE hModule, DWORD dwFunction, LPVOID lpNot)
{
hInstance = hModule;
return TRUE;
}
LRESULT CALLBACK KeyboardProc(int hookCode, WPARAM vKeyCode, LPARAM flags)
{
if(hookCode < 0)
{
return CallNextHookEx(hKeyboardHook, hookCode, vKeyCode, flags);
}
if(!hookCode)
{
lastKey = (int)vKeyCode;
keyFlags = (int)flags;
}
return CallNextHookEx(hKeyboardHook, hookCode, vKeyCode, flags);
}
LRESULT CALLBACK MouseProc(int hookCode, WPARAM msgID, LPARAM pMouseHookStruct)
{
if(hookCode < 0)
{
return CallNextHookEx(hMouseHook, hookCode, msgID, pMouseHookStruct);
}
if(!hookCode)
{
mouseMsgID = (int)msgID;
mHookPt = (MOUSEHOOKSTRUCT *)pMouseHookStruct;
mHookStruct = *mHookPt;
}
return CallNextHookEx(hMouseHook, hookCode, msgID, pMouseHookStruct);
}
__declspec(dllexport) int getLastKey(void)
{
if(!lastKey)
return 0;
return lastKey;
}
__declspec(dllexport) int getLastFlags(void)
{
if(!keyFlags)
return 0;
return keyFlags;
}
__declspec(dllexport) int getMsgID(void)
{
if(!mouseMsgID)
return 0;
return mouseMsgID;
}
__declspec(dllexport) MOUSEHOOKSTRUCT getMouseStruct(void)
{
return mHookStruct;
}
__declspec(dllexport) void InstallHooks(void)
{
hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, hInstance, 0);
hMouseHook = SetWindowsHookEx(WH_MOUSE, MouseProc, hInstance, 0);
}
__declspec(dllexport) void UninstallHooks(void)
{
UnhookWindowsHookEx(hKeyboardHook);
hKeyboardHook = 0;
lastKey = 0;
keyFlags = 0;
UnhookWindowsHookEx(hMouseHook);
mouseMsgID = 0;
mHookPt = NULL;
}
It's compiled into a dll, which is loaded into python using ctypes.CDLL('blah.dll'):
class MouseHookStruct(ctypes.wintypes.Structure):
_fields_ = [("pt", ctypes.wintypes.POINT),
("hwnd", ctypes.wintypes.HWND),
("dwExtraInfo", ctypes.wintypes.POINTER(ctypes.wintypes.c_ulong))]
dll = ctypes.CDLL('blah.dll')
dll.getMouseStruct.restype = MouseHookStruct
try:
dll.InstallHooks()
mStruct = MouseHookStruct()
while True:
mStruct = dll.getMouseStruct()
print mStruct.pt.x, mStruct.pt.y
except KeyboardInterrupt:
pass
finally:
dll.UninstallHooks()
All this does is print out 0 0 regardless of where the mouse is. The keyboard hook is fine because its callback proc does not make use of a struct. However, if I try a WH_KEYBOARD_LL I have the same issue (all values of the struct are 0). What am I missing with passing structs between the OS, C and Pythons ctypes?