I'm using OpenCV 2.4.9 and g++. I've also tried with python 2.7.8 and python 3.4.1.
Here's a simple example:
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc, char *argv[]) {
VideoCapture stream;
if (argc > 1) {
stream.open(argv[1]);
} else {
stream.open(0);
}
if (!stream.isOpened()) {
cout << "cannot open file";
}
while (true) {
Mat frame;
stream.read(frame);
imshow("preview", frame);
if (waitKey(30) >= 0)
break;
}
return 0;
}
This is compiled with:
g++ `pkg-config --libs opencv` -o test test.cpp
Works just fine with the camera, but not when reading from a file the program just hangs. Same is true with python. Any ideas?
Finally got around to fixing this. On Fedora 21 the opencv from the repository is built without ffmpeg support, because many codecs are not FOSS. Compiling from source did the trick.
Related
I'm facing an issue while interfacing python and cpp. I need to compute an optical flow with the GPU. To do so, I'm using the tvl1 algorithm with opencv on with cpp and cuda.
My cpp code is working well with GPU and I now want to call the function in my python code because there isn't a way to compute optical flow on GPU with this algo on Python.
I'm using ctypes to make the link beetwin cpp and python. Here are my codes :
python
from ctypes import cdll
opencvfunc = cdll.LoadLibrary('opt_flow_lib/test.so')
cpp
//test.cpp
#define DLLEXPORT extern "C"
#include "opencv2/xfeatures2d.hpp"
#include "opencv2/cudaarithm.hpp"
#include "opencv2/cudaoptflow.hpp"
#include "opencv2/cudacodec.hpp"
#include "opencv2/video/tracking.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/core/mat.hpp"
using namespace cv::cuda;
using namespace cv;
DLLEXPORT int tvl(int a, int b) {
int bound = 20;
Size new_size(224, 224);
Mat curr_gray, prev_gray, prev_image, curr_image;
Mat flow_x, flow_y;
GpuMat d_frame_0, d_frame_1;
GpuMat d_flow;
cv::Ptr<cuda::OpticalFlowDual_TVL1> alg_tvl1 =
cuda::OpticalFlowDual_TVL1::create();
return 3;
}
Here is how I build my cpp file :
gcc -o test.so -shared -fPIC test.cpp `pkg-config opencv --cflags --libs`
Here is what I have when I launch my python code :
OSError: opt_flow_lib/test.so: undefined symbol: _ZN2cv4cuda20OpticalFlowDual_TVL16createEdddiididdb
When I remove this line from cpp :
cv::Ptr<cuda::OpticalFlowDual_TVL1> alg_tvl1 =
cuda::OpticalFlowDual_TVL1::create();
Everything is going ok, I have my 3 int returned. But it seems that cuda doesn't want to do its job
Is someone who had ever turned opencv with cuda with ctypes and cpp/python could hepl me ?
Thanks you
EDIT :
Maybe it could be interesting to have my $ pkg-config opencv --cflags --libs :
-I/usr/local/include/opencv4/opencv2 -I/usr/local/include/opencv4 -L/usr/local/lib -lopencv_core -lopencv_imgproc -lopencv_highgui -lopencv_ml -lopencv_video -lopencv_xfeatures2d -lopencv_calib3d -lopencv_objdetect
I'm embedding Python in Qt C++. When I import cv2 in the Python script it crashes with segmentation fault. Running the script in Python works. Running from C++ without Qt works.
Python scrip: works
print("Importing cv2")
import cv2
print("cv2 imported")
C++: works
#include <Python.h>
#include <string>
int main(int argc, char *argv[])
{
std::string module_name("PythonModule");
Py_Initialize();
PyObject* sysPath = PySys_GetObject((char*)"path");
PyObject* pModuleDirPath = PyUnicode_FromString(".");
PyList_Append(sysPath, pModuleDirPath);
Py_DECREF(pModuleDirPath);
PyObject* pModuleName = PyUnicode_FromString(module_name.c_str());
PyObject* pModule = PyImport_Import(pModuleName);
Py_DECREF(pModuleName);
Py_DECREF(pModule);
Py_Finalize();
return 0;
}
Qt: segmentation fault after printing "Importing cv2"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
std::string module_name("PythonModule");
Py_Initialize();
PyObject* sysPath = PySys_GetObject((char*)"path");
PyObject* pModuleDirPath = PyUnicode_FromString(".");
PyList_Append(sysPath, pModuleDirPath);
Py_DECREF(pModuleDirPath);
PyObject* pModuleName = PyUnicode_FromString(module_name.c_str());
PyObject* pModule = PyImport_Import(pModuleName);
Py_DECREF(pModuleName);
Py_DECREF(pModule);
Py_Finalize();
}
.pro file:
LIBS += -L /usr/local/lib/python3.5m -lpython3.5m
INCLUDEPATH += /usr/include/python3.5m
Versions:
Ubuntu 16.04
Python 3.5
opencv-python 3.4.2.17
Qt Creator 4.7.0 Based on Qt 5.11.1
Do anyone recognize this problem?
The problem was that opencv uses Qt as well so a collision occurred.
The solution was to install opencv without Qt support:
pip install opencv-contrib-python-headless
https://pypi.org/project/opencv-contrib-python-headless/
I have a task in which I have to write the Python bindings for an existing C++ library. Since SWIG have support for not only Python but also for languages like Java and Perl, I am using SWIG. I am relatively new in SWIG so I have a doubt. I want my python library to be supportable under Python 2.7 and Python 3.x. But I don't have any idea regarding how to do this. So if anyone can suggest me. Any help would be appreciated. You can ask me for more details if you want.
What I have tried so far.
This is my code file.
/* example.c file */
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int my_mod(int n, int m) {
return n % m;
}
int sieve(int number) {
int* arr = malloc(sizeof (int) * (number + 10));
int* prime = malloc(sizeof (int) * (number + 10));
/* printf("Size of arr: %lu", sizeof(arr));
printf("Size of int: %lu", sizeof(int)); */
memset(arr, 0, sizeof(int) * (number + 10));
int counter = 0;
prime[counter++] = 2;
arr[0] = arr[1] = 0;
for (int i = 3; i * i <= number; i += 2) {
if (!arr[i]) {
for (int j = i + i; j < number; j += i) {
arr[j] = 1;
}
}
}
for (int i = 3; i < number; i += 2)
if (!arr[i])
prime[counter++] = i;
// free(arr);
// free(prime);
return counter;
}
And my interface file is
/* example.i */
%module example
%{
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
extern int my_mod(int n, int m);
extern int sieve(int number);
%}
extern int my_mod(int n, int m);
extern int sieve(int number);
My steps for compilation
swig -python example.i
gcc -fpic -c example.c example_wrap.c $(pkg-config --cflags --libs python3)
gcc -shared example.o example_wrap.o -o _example.so
In above compilation format module is working fine with python3 but failing in python2 with error log as
ImportError: ./_example.so: undefined symbol: PyUnicode_FromFormat
And if I use below compilation commands
swig -python example.i
gcc -fpic -c example.c example_wrap.c $(pkg-config --cflags --libs python2)
gcc -shared example.o example_wrap.o -o _example.so
Than module is working with python2 but when I try to import in python3 than error message is
ImportError: /home/deepanshu/env/swig/env/src/deep/_example.so: undefined symbol: PyInstance_Type
I am sure than the error is because $(pkg-config --cflags --libs pythonX) I am specifying version at place of X but how can I make sure my module works with both the Python versions?
I tried -py3 flag of swig, but I wasn't able to make module work for both of the Python version with above specified flag.
C extension don't work the same way in python3 vs python2. This link can help you identify what you need to do on the C level to have the library work for both python 2 and 3 (not using swig). http://python3porting.com/cextensions.html
Using Swig, what I would do is make use of the pip wheels naming convention :
https://packaging.python.org/tutorials/distributing-packages/#packaging-your-project
Doing so, I would package the library for python3 and make the package follow the wheel naming standard ("https://www.python.org/dev/peps/pep-0425/#id1" "py3-none-any") and then make the library for Python2 and package it using the same strategy("py2-none-any"). then you can upload it to Pypi and pip would know that it need to use the py2 for python2 and py3 for python3.
I used swig to generate a python module that is wrapping up some C++ code:
my .i file :
%module module_test
%{
#define SWIG_FILE_WITH_INIT
#include "headers.h"
%}
%include "headers.h"
I ran these commands :
swig -c++ -python swig.i
swig -Wall -c++ -python -external-runtime runtime_swig.h
After building, this generated a module_test.py and a _module_test.pyd files.
The wrapper works fine in python.
Now, from another C++ project I'm trying to load this new python module, using the following code:
Py_Initialize();
PySys_SetPath(L"path_to_my_files");
PyObject * pName = PyString_FromString("module_test.py");
PyObject *module = PyImport_Import(pName);
if(module == NULL)
{
PyErr_Print();
std::cout << "module == NULL !!";
exit(-1);
}
However the import fails with the error :
import imp
ImportError: No module named 'imp'
Can someone please tell me what's going on ? The module_test.py file generated by swig is doing an "import imp" in the code, but this import never failed when I run the file from python...
Do I need to specify something else so that the C++ code knows what "imp" is ?
thanks!
Solved it by using instead :
PyObject *sys = PyImport_ImportModule("sys");
PyObject *path = PyObject_GetAttrString(sys, "path");
PyList_Append(path, PyString_FromString("path_to_file"));
I am porting a project from C++ Embarcadero XE6 32 bit to XE6 64 bit. We use embedded python libraries (and also some Python modules written in C).
I was able to get it to compile, but I can not link because there aren't any libs in the Python directory that the compiler bcc64 (a clang based compiler) can use.
Here's my code, it's just the simple "Here's how to embed python" example from the documentation really. We use Python 3.1; we could upgrade but I don't see the libs in newer versions either.
#define HAVE_ROUND
#define HAVE_ACOSH
#define HAVE_ASINH
#define HAVE_ATANH
#include <Python.h>
#pragma hdrstop
#pragma argsused
#ifdef _WIN32
#include <tchar.h>
#else
typedef char _TCHAR;
#define _tmain main
#endif
#include <stdio.h>
int _tmain(int argc, _TCHAR* argv[])
{
// Invoke the python intepreter
Py_Initialize();
PyRun_SimpleString("from time import time,ctime\n"
"print('Today is', ctime(time()))\n");
Py_Finalize();
system("Pause");
return 0;
}
mkexp libpython31.a C:\Windows\System32\python31.dll
Thanks to Ignacio for the help.