How to compile OpenCV with Boost::Python? - c++

I'm trying to compile OpenCV in C++ with boost::python but I keep getting a linker error that I can't quite resolve.
Here is the code below.
cascade_handler.cpp
#include <iostream>
#include <boost/python.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/ocl/ocl.hpp>
#include "cascade_handler.h"
using namespace std;
using namespace boost::python;
void CascadeHandler::cascade_classifier_cpu(const string *cascade_file, std::vector<cv::Rect>& objects, double scale_factor, int min_neighbors){
/*cv::Mat image;
cv::CascadeClassifier cascade_classifier;
cascade_classifier.load(*cascade_file);
cascade_classifier.detectMultiScale(image, objects, scale_factor, min_neighbors, 0 | CASCADE_SCALE_IMAGE, Size(20, 20));
*/
}
void CascadeHandler::cascade_classifier_gpu(const string *cascade_file, std::vector<cv::Rect>& objects, double scale_factor, int min_neighbors){
/*Mat image;
cv::CascadeClassifier cascade_classifier;
*/
}
void CascadeHandler::handle(const string cascade_file, std::vector<cv::Rect>& objects, double scale_factor, int min_neighbors)
{
CascadeHandler cascade_handler;
cv::CascadeClassifier cascade_classifier;
//ocl::Context context;
/*
if (!cascade_classifier.load(cascade_file)){
cout << "[!] Error: You must load a Cascade file\n";
}
if (objects.empty()){
}
if (scale_factor == 0){
cout << "[!] Error: Unacceptable Scale Factor\n";
}
if (min_neighbors == 0){
cout << "[!] Error: Unacceptable Minimum Neighbors\n";
}
if (context.ndevices()){
cascade_handler.cascade_classifier_gpu(&cascade_file, objects, scale_factor, min_neighbors);
}
else if (!context.ndevices()){
cascade_handler.cascade_classifier_cpu(&cascade_file, objects, scale_factor, min_neighbors);
}
*/
}
void cascade_handler_wrapper(const string cascade_file, std::vector<cv::Rect>& objects,
double scale_factor, int min_neighbors){
CascadeHandler cascade_handler;
cascade_handler.handle(cascade_file, objects, scale_factor, min_neighbors);
}
BOOST_PYTHON_MODULE(cascade_handler){
def("handle", cascade_handler_wrapper);
}
The Header file
#ifndef _CASCADE_HANDLER
#define _CASCADE_HANDLER
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/ocl/ocl.hpp>
using namespace std;
class CascadeHandler
{
public:
void cascade_classifier_cpu(const string *cascade_file, std::vector<cv::Rect>& objects, double scale_factor, int min_neighbors);
void cascade_classifier_gpu(const string *cascade_file, std::vector<cv::Rect>& objects, double scale_factor, int min_neighbors);
void handle(const string cascade_file, std::vector<cv::Rect>& objects, double scale_factor, int min_neighbors);
};
#endif
The Makefile
CPP = g++
CPPFLAGS = -g -Wall -std=c++11
INCLUDES = -I /usr/local/include
LDFLAGS = -L /usr/local/lib
ARCH := $$(getconf LONG_BIT)
CUDA_PATH = /opt/cuda
CUDA_LDFLAGS = -L$(CUDA_PATH)/lib$(ARCH)
CUDA_INCLUDES = -I$(CUDA_PATH)/include
OPENCV_LDFLAGS = $(CUDA_LDFLAGS)
OPENCV_LIBS = $$(pkg-config --libs opencv)
OPENCV_INCLUDES = $$(pkg-config --cflags opencv) $(CUDA_INCLUDES)
PYTHON_VER = 2
ifeq ($(PYTHON_VER), 2)
BOOST_LIBS = -lboost_python
else
BOOST_LIBS = -lboost_python$(PYTHON_VER)
endif
PYTHON_LIBS = $$(pkg-config --libs python$(PYTHON_VER))
PYTHON_INCLUDES = $$(pkg-config --cflags python$(PYTHON_VER))
TARGET = cascade_handler
all: $(TARGET).so
$(TARGET).so: $(TARGET).o
$(CPP) -shared -Wl,--export-dynamic $(LDFLAGS) \
$(OPENCV_LIBS) $(BOOST_LIBS) $(PYTHON_LIBS) \
$(TARGET).o -o $(TARGET).so
$(TARGET).o: $(TARGET).cpp
$(CPP) $(CPPFLAGS) $(INCLUDES) $(OPENCV_INCLUDES) $(PYTHON_INCLUDES) \
-fPIC -c $(TARGET).cpp
clean:
rm -f *.o *.so
And the Output
g++ -shared -Wl,--export-dynamic -L /usr/local/lib \
$(pkg-config --libs opencv) -lboost_python $(pkg-config --libs python2) \
cascade_handler.o -o cascade_handler.so
ld: unknown option: --export-dynamic
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [cascade_handler.so] Error 1
The linker error is the thing I can't quite fix. I wanted to have everything compile on a Makefile because I couldn't find a way to compile OpenCV with the setup.py you normally use when using boost::python. I've also read that some people have been using numpy to wrap their code in and then compile that way, but I was wondering if this method may also work? I also have most of the code commented out because I just wanted to test if it would compile by just have the class cv::CascadeClassifier cascade_classifier;

Related

contiki C++ compile causes region `FLASH_CCA' overflowed for zoul

I need to compile a C++ library to use with contiki on the Zolertia Re-Mote. I am trying a simple program first:
hello-world.c
#include "contiki.h"
#include "misc.h"
/*---------------------------------------------------------------------------*/
PROCESS(hello_world_process, "Hello world process");
AUTOSTART_PROCESSES(&hello_world_process);
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(hello_world_process, ev, data)
{
PROCESS_BEGIN();
say_hello();
PROCESS_END();
}
/*---------------------------------------------------------------------------*/
misc.cpp
/* C++ implementation */
#ifdef CONTIKI_TARGET_ZOUL
void* __dso_handle;
void* __exidx_end;
void* __exidx_start;
#endif
#include <iostream>
using namespace std;
void cpp_say_hello(){
cout << "Hello world!" << endl;
}
/* C wrapper */
extern "C"{
#include "misc.h"
void say_hello(){
cpp_say_hello();
}
}
misc.h
#ifndef _MISC_H_
#define _MISC_H_
/**
* \brief Prints hello to stdout
*/
void say_hello();
#endif /* _MISC_H_ */
Makefile
ifeq ($(TARGET),)
TARGET = native
endif
CONTIKI_PROJECT = hello-world
all: $(CONTIKI_PROJECT)
PROJECT_LIBRARIES = obj_$(TARGET)/misc.o
include $(CONTIKI)/Makefile.include
obj_$(TARGET)/misc.o: misc.cpp
#mkdir -p obj_$(TARGET)
$(TRACE_CXX)
$(Q)$(CXX) $(CFLAGS) $(CXXFLAGS) -c $^ -o $#
This (with some modifications to the contiki Makefiles: here) made possible for me to use C++ code for the 'native' target. However when i try to compile for the Zolertia Re-Mote platform (TARGET=zoul) i obtain the following error:
/usr/lib/gcc/arm-none-eabi/8.2.0/../../../../arm-none-eabi/bin/ld: hello-world.elf section `.ARM.extab.text._Z13cpp_say_hellov' will not fit in region `FLASH_CCA'
/usr/lib/gcc/arm-none-eabi/8.2.0/../../../../arm-none-eabi/bin/ld: region `FLASH_CCA' overflowed by 788 bytes
collect2: error: ld returned 1 exit status
make: *** [/home/wellsaid/contiki/cpu/cc2538/Makefile.cc2538:103: hello-world.elf] Error 1
rm hello-world.co obj_zoul/startup-gcc.o
Any way to fix this?

Get a opencv_gpu function working in Qt5

I have an OpenSUSE 13.2 System with Qt5 and OpenCV installed with cudasupport. The Hardware is an Intel i5 processor with an integrated intel gpu chip and a NVidia GForce 940 M and i have tried to compile this file.
#include <iostream>
#include <time.h>
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/opencv.hpp"
#include "opencv2/gpu/gpu.hpp"
using namespace std;
int main()
{
try
{
cv::Mat dst_mat;
cv::Mat src_host = cv::imread("/home/peter/testCuda/testCuda/GothaOrangerie.JPG", CV_LOAD_IMAGE_GRAYSCALE);
cv::namedWindow("Result",cv::WINDOW_NORMAL);
cv::imshow("Result", src_host);
cv::waitKey();
cv::gpu::GpuMat dst, src;
src.upload(src_host);
clock_t t = clock();
cv::gpu::threshold(src, dst, 128.0, 255.0, CV_THRESH_BINARY);
t = clock() -t;
cv::Mat result_host(dst);
cout << ((float)t)/CLOCKS_PER_SEC << endl;
cv::imshow("Result", result_host);
cv::waitKey();
t = clock();
cv::threshold(src_host, dst_mat, 128.0, 255.0, CV_THRESH_BINARY);
t = clock() -t;
cout << ((float)t)/CLOCKS_PER_SEC << endl;
cv::imshow("Result", dst_mat);
cv::waitKey();
}
catch(const cv::Exception& ex)
{
cout << "Error: " << ex.what() << endl;
}
return 0;
}
The compilation in the shell with
g++ main.cpp -o threshold `pkg-config --cflags --libs opencv` -lopencv_gpu -L/usr/local/cuda-7.5/lib64
works pretty well i can run the small program without any issues. If i try it with the Qt5 IDE it returns me this error.
OpenCV Error: No GPU support (The library is compiled without CUDA support) in mallocPitch, file /home/abuild/rpmbuild/BUILD/opencv-2.4.9/modules/dynamicuda/include/opencv2/dynamicuda/dynamicuda.hpp, line 126
Error: /home/abuild/rpmbuild/BUILD/opencv-2.4.9/modules/dynamicuda/include/opencv2/dynamicuda/dynamicuda.hpp:126: error: (-216) The library is compiled without CUDA support in function mallocPitch
If i run the shellcompiled program with this command
optirun ./threshold
i get the same error.
The .pro File is
#-------------------------------------------------
#
# Project created by QtCreator 2015-10-15T04:02:07
#
#-------------------------------------------------
TARGET = testCuda
LIBS += -L/usr/lib64/
LIBS += -L/usr/local/cuda-7.5/lib64 -lopencv_gpu
LIBS += `pkg-config opencv --cflags --libs`
SOURCES += main.cpp
and the Qt compilation command is
22:58:12: Running steps for project testCuda...
22:58:12: Configuration unchanged, skipping qmake step.
22:58:12: Starting: "/usr/bin/make"
g++ -c -pipe -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/share/qt4/mkspecs/linux-g++ -I../testCuda -I/usr/include/QtCore -I/usr/include/QtGui -I/usr/include -I. -I../testCuda -I. -o main.o ../testCuda/main.cpp
g++ -Wl,-O1 -o testCuda main.o -L/usr/lib64 -L/usr/lib64/ -L/usr/local/cuda-7.5/lib64 -lopencv_gpu `pkg-config opencv --cflags --libs` -lQtGui -L/usr/lib64 -L/usr/X11R6/lib -lQtCore -lpthread
22:58:13: The process "/usr/bin/make" exited normally.
22:58:13: Elapsed time: 00:01.
Anybody an idea how to fix that?
Deinstalling the preinstalled libopencv-2.4.9 package solved it.

How to access global variable from .so in executable

Please help me, How to access run time varibale's data(att) in stub.exe of att variable that is defined in proc.so,
I have created proc.so and linked with attol.exe and stub.exe and
attol.exe updates 'att' variable and stub.exe is accessing 'att' variable and prints att's value.
I have used below commands to compile the code :
g++ -Wall -c attol.cc proc.cc stub.cc
g++ -shared -dynamiclib -fPIC -o libproc.so proc.o -ldl
g++ -rdynamic -o attol.exe attol.o /users/hbharti/DLOPEN/proc/libproc.so -ldl
g++ -rdynamic -o stub.exe stub.o /users/hbharti/DLOPEN/proc/libproc.so -ldl
When i am running both .exe at different terminal then attol.exe showing 'att:4' value but stub.exe is showing incorrect value,
But stub.exe should display '4' value or updated value.
out put attol.exe:
./attol.exe
Value of att is : 4
Enter the value of att :
out put stub.exe:
./stub.exe
Att : 0
----Complete Code Details----
proc.h:
#ifndef __X_H_INCLUDED__
#define __X_H_INCLUDED__
extern int att;
int fun();
#endif
proc.cc:
#include<iostream.h>
#include "proc.h"
int att;
int fun ()
{
att=4;
return 0;
}
Above code is generating proc.o and then this proc.o will converted into proc.so with below commands:
g++ -Wall -c attol.cc proc.cc stub.cc
g++ -shared -dynamiclib -fPIC -o libproc.so proc.o -ldl
attol.cc:
#include <iostream.h>
#include "proc.h"
using namespace std;
int main ()
{
int ch=1;
fun();
cout<<"\n Value of att is : "<<att;
do{
cout<<"\n Enter the value of att : ";
cin>>att;
cout<<"\n Do you want to continue the : ";
cin>>ch;
}while(ch!=0);
return 0;
}
attol.cc file creates attol.exe by using below command
g++ -rdynamic -o attol.exe attol.o /users/hbharti/DLOPEN/proc/libproc.so -ldl
out put:
Value of att is : 4
Enter the value of att :
stub.cc:
#include <iostream.h>
#include <dlfcn.h>
int main ()
{
void *handle;
char *error;
handle = dlopen ("/users/hbharti/DLOPEN/proc/libproc.so", RTLD_LAZY);
if (!handle) {
fputs (dlerror(), stderr);
exit(1);
}
int *att =(int*) dlsym(handle, "att");
if ((error = dlerror()) != NULL) {
fputs(error, stderr);
exit(1);
}
cout<<"\n Att : " <<*att;
cout<<"\n " ;
dlclose(handle);
}
stub.cc file creates stub.exe by using below command
g++ -rdynamic -o stub.exe stub.o /users/hbharti/DLOPEN/proc/libproc.so -ldl
Judging by the code, there seems to be a fundamental issue with the core-logic.
A shared-object (*.so) is loaded into the executing process's memory address space.
However it is NOT shared across multiple processes. When 2 or more executables attempt to access the same shared-object (*.so), they both get independent copies of it mapped into their respective memory address spaces.
Data (even globals) within a shared-object (*so) are NOT shared across 2 or more executables.

C++ code compiles fine with normal V8 engine, fails to build with V8 provided by Node

Makefile:
CC:=g++
OUTFILE?=addon
SOURCE?=src
CFLAGS+=-Iinclude -lv8 -m64
.PHONY: all clean
all:
$(CC) $(CFLAGS) -o $(OUTFILE) `ls $(SOURCE)/*.cc`
clean:
rm -f $(OUTFILE)
addon.h:
#ifndef __addon_h
#define __addon_h
#define BUILDING_NODE_EXTENSION
#define ADDON_VERSION "0.0.1"
#ifdef BUILDING_NODE_EXTENSION
#include <node/node.h>
#include <node/v8.h>
#else
#include <v8.h>
#endif
using namespace v8;
void init(Handle<Object> exports);
Handle<Object> setupExports(Handle<Object> exports);
#endif
addon.cc:
#include <cstdlib>
#include <cstdio>
#include <addon.h>
using namespace v8;
#ifndef BUILDING_NODE_EXTENSION
int main(int argc, char **argv) {
Isolate *isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
Handle<Context> context = Context::New(isolate);
Context::Scope context_scope(context);
Handle<Object> exports = Object::New();
init(exports);
printf("Version: %s\n", *String::Utf8Value(exports->Get(String::New("version"))));
return 0;
}
#else
int main() {
printf("This is a module compiled for Node.\nPlease use require in Node to use this file.\n");
return 0;
}
#endif
void init(Handle<Object> exports) {
setupExports(exports);
}
Handle<Object> setupExports(Handle<Object> exports) {
// Set version number.
exports->Set(String::New("version"), String::New(ADDON_VERSION));
return exports;
}
#ifdef BUILDING_NODE_EXTENSION
NODE_MODULE(addon, init)
#endif
When compiling the above code with the normal V8 engine without BUILDING_NODE_EXTENSION defined, the output is what we expect:
❱ make && ./addon
g++ -Iinclude -lv8 -m64 -o addon `ls src/*.cc`
Version: 0.0.1
When compiling with BUILDING_NODE_EXTENSION defined, using Node's <node/node.h> and <node/v8.h> for includes instead of the normal <v8.h>, I get this:
❱ make && ./addon
g++ -Iinclude -lv8 -m64 -o addon `ls src/*.cc`
Undefined symbols for architecture x86_64:
"v8::String::New(char const*, int)", referenced from:
setupExports(v8::Handle<v8::Object>) in ccRntYkS.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
make: *** [all] Error 1
Anyone have any idea what is going wrong here?
Building with node-gyp solved the problem.
Face. Palm.
Makefile change:
CC:=g++
OUTFILE?=addon
SOURCE?=src
CFLAGS+=-Iinclude -lv8 -m64
.PHONY: all clean
all:
if [ -d build ]; then \
node-gyp build; \
else \
$(CC) $(CFLAGS) -o $(OUTFILE) `ls $(SOURCE)/*.cc`; \
fi;
clean:
rm -f $(OUTFILE)

Make file Linking issue Undefined symbols for architecture x86_64

I am working on getting a few files to link together using my make file and c++ and am getting the following error when running make.
g++ -bind_at_load `pkg-config --cflags opencv` -c -o compute_gist.o compute_gist.cpp
g++ -bind_at_load `pkg-config --cflags opencv` -c -o gist.o gist.cpp
g++ -bind_at_load `pkg-config --cflags opencv` -c -o standalone_image.o standalone_image.cpp
g++ -bind_at_load `pkg-config --cflags opencv` -c -o IplImageConverter.o IplImageConverter.cpp
g++ -bind_at_load `pkg-config --cflags opencv` -c -o GistCalculator.o GistCalculator.cpp
g++ -bind_at_load `pkg-config --cflags opencv` `pkg-config --libs opencv` compute_gist.o gist.o standalone_image.o IplImageConverter.o GistCalculator.o -o rungist
Undefined symbols for architecture x86_64:
"color_gist_scaletab(color_image_t*, int, int, int const*)", referenced from:
_main in compute_gist.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
make: *** [rungist] Error 1
My makefile is as follows (Note, I don't need opencv bindings yet, but will be coding in opencv later.
CXX = g++
CXXFLAGS = -bind_at_load `pkg-config --cflags opencv`
LFLAGS = `pkg-config --libs opencv`
SRC = \
compute_gist.cpp \
gist.cpp \
standalone_image.cpp \
IplImageConverter.cpp \
GistCalculator.cpp
OBJS = $(SRC:.cpp=.o)
rungist: $(OBJS)
$(CXX) $(CXXFLAGS) $(LFLAGS) $(OBJS) -o $#
all: rungist
clean:
rm -rf $(OBJS) rungist
The method header is located in gist.h
float *color_gist_scaletab(color_image_t *src, int nblocks, int n_scale, const int *n_orientations);
And the method is defined in gist.cpp
float *color_gist_scaletab(color_image_t *src, int w, int n_scale, const int *n_orientation) {
And finally the compute_gist.cpp (main file)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "gist.h"
static color_image_t *load_ppm(const char *fname) {
FILE *f=fopen(fname,"r");
if(!f) {
perror("could not open infile");
exit(1);
}
int width,height,maxval;
if(fscanf(f,"P6 %d %d %d",&width,&height,&maxval)!=3 || maxval!=255) {
fprintf(stderr,"Error: input not a raw PPM with maxval 255\n");
exit(1);
}
fgetc(f); /* eat the newline */
color_image_t *im=color_image_new(width,height);
int i;
for(i=0;i<width*height;i++) {
im->c1[i]=fgetc(f);
im->c2[i]=fgetc(f);
im->c3[i]=fgetc(f);
}
fclose(f);
return im;
}
static void usage(void) {
fprintf(stderr,"compute_gist options... [infilename]\n"
"infile is a PPM raw file\n"
"options:\n"
"[-nblocks nb] use a grid of nb*nb cells (default 4)\n"
"[-orientationsPerScale o_1,..,o_n] use n scales and compute o_i orientations for scale i\n"
);
exit(1);
}
int main(int argc,char **args) {
const char *infilename="/dev/stdin";
int nblocks=4;
int n_scale=3;
int orientations_per_scale[50]={8,8,4};
while(*++args) {
const char *a=*args;
if(!strcmp(a,"-h")) usage();
else if(!strcmp(a,"-nblocks")) {
if(!sscanf(*++args,"%d",&nblocks)) {
fprintf(stderr,"could not parse %s argument",a);
usage();
}
} else if(!strcmp(a,"-orientationsPerScale")) {
char *c;
n_scale=0;
for(c=strtok(*++args,",");c;c=strtok(NULL,",")) {
if(!sscanf(c,"%d",&orientations_per_scale[n_scale++])) {
fprintf(stderr,"could not parse %s argument",a);
usage();
}
}
} else {
infilename=a;
}
}
color_image_t *im=load_ppm(infilename);
//Here's the method call -> :(
float *desc=color_gist_scaletab(im,nblocks,n_scale,orientations_per_scale);
int i;
int descsize=0;
//compute descriptor size
for(i=0;i<n_scale;i++)
descsize+=nblocks*nblocks*orientations_per_scale[i];
descsize*=3; // color
//print descriptor
for(i=0;i<descsize;i++)
printf("%.4f ",desc[i]);
printf("\n");
free(desc);
color_image_delete(im);
return 0;
}
Any help would be greatly appreciated. I hope this is enough info. Let me know if I need to add more.
I suspect that color_gist_scaletab should be declared as extern "C" in your header file:
extern "C" {
float *color_gist_scaletab(color_image_t *src, int nblocks, int n_scale, const int *n_orientations);
}
Your link command line is incorrect. See this answer.
However, that is likely not the problem you are seeing here.
What do the following commands print?
file gist.o
nm gist.o | grep color_gist_scaletab
I also see this very similar question. But there, color_gist_scaletab comes from gist.c, not gist.cpp. You didn't just rename gist.c to gist.cpp, did you? Don't do that.