Passing frames to c++ from python VideoCapture() - python

I read usb camera as cv2.VideoCapture() function and showing frames. I need to some c++ application read frames from python application.
How can i make this ?
Steps:
Read camera with python from usb camera.
Show frames cv2.imshow("usb_cam_frame", frame).
Run c++ application.
Transfer frames to c++ application. ???
Show same frames with c++ application.

You can use embedding python in C++ and call python function in a C++ program. Put the python module and define a dict in this module that contain data of frame in file for example test.py.
#include <Python.h>
int main(int argc, char *argv[])
{
Py_Initialize();
pName = PyString_FromString("test.py");
pModule = PyImport_Import(pName);
pDict = PyModule_GetDict(pModule);
pFunc = PyDict_GetItemString(pDict, "frame");
if (PyCallable_Check(pFunc))
{
PyObject_CallObject(pFunc, NULL);
}
else
{
PyErr_Print();
}
// Clean up
Py_DECREF(pModule);
Py_DECREF(pName);
// Finish the Python Interpreter
Py_Finalize();
return 0;
}

Related

Debugging mixed C++/embedded Python

Firstly my problem is similar to this one:
Debugging embedded Python
However although the description in that case is very helpful, it doesn't alas contain all the information needed to debug a mixed C++/embedded Python app.
Background: I have a C++ app that is calling Python code with some argument:
bool
ui::runLUOvershoot4(PyObject*inData)
{
// Get the python module.
PyObject* const pName = PyBytes_FromString("lu_overshoot4");
PyObject* pModule = nullptr;
PyObject* const pMod = PyImport_AddModule("lu_overshoot4");
if (pMod != nullptr) {
pModule = PyImport_ReloadModule(pMod);
}
/* NB pMod is borrowed and must not be Py_DECREF-ed */
if (pModule == nullptr) {
PyErr_Print();
return false;
}
Py_DECREF(pName);
// Get the dictionary for the lu_overshoot4 module
PyObject* const pDict = PyModule_GetDict(pModule);
Py_DECREF(pModule);
// Get the function in the dictionary
PyObject* const pFunc = PyDict_GetItemString(pDict, "LU_Overshoot4");
if (pFunc == nullptr) {
PyErr_Print();
return false;
}
Py_INCREF(pFunc);
if (pFunc && PyCallable_Check(pFunc)) {
// Call the python func with inData as arg
PyObject* arglist = Py_BuildValue("(O)", inData);
PyObject* const pValue = PyObject_Call(pFunc, arglist, nullptr);
if (pValue == nullptr) {
PyErr_Print();
return false;
}
Py_DECREF(pFunc);
return true;
}
return false;
}
All works as expected. But I want to be able to step in the debugger from the C++ PyObject_Call into the python code. So far I have been able to do this only if I start the C++ code without the debugger, then attach the debugger to the running process. If I try and start in the debugger, the breakpoints in the python code are disabled with the tooltip 'The breakpoint will not currently be hit. No symbols have been loaded for this document'.
A little detail on the setup: this is a Visual Studio 2022 solution with a C++ project (with the debugger to launch being the Python/Native Debugger) and a Python project containing the python files. It's not clear to me what settings to give the Python project, what I have is in the General tab,
Startup File -
Working Directory - .
Windows Application - ticked (makes no difference though)
Interpreter - env(Python 3.8 64-bit).
In the Debug tab,
Search Paths - .;\env
Script args -
Interpreter Path - \env
Interpreter Args -
Environment Variables -
Debug - 'Enable native code debugging' checked.
The python project's Python Environment was set up with a virtual env, set to the \env directory, which contains the include/Lib/Scripts/share dirs and python.exe, python38.dll, python.pdb etc. i.e. python installation and pdb files. This is how (I believe) 'Lambda' describes their setup.
One of the issues I faced was that at first VS2022 (v 17.2.6) did not give the option of setting the debugger to python/native; a fix is described in https://learn.microsoft.com/en-us/answers/questions/860222/the-option-34pythonnative-debugging34-is-missing-f.html. But with that set and starting the debugger with F5, it is not possible to step into Python code from C++ or break on Python code - only if debugging is done by attaching to the running process.
Any help gratefully received.

Embed / Include Python.h into C++ [Full Guide] (Python 3.9) (Windows) (Qt 5.15) [duplicate]

This question already has answers here:
how can i include python.h in QMake
(1 answer)
Embedding python 3.4 into C++ Qt Application?
(4 answers)
Closed 2 years ago.
When I was trying to embed a Python script into my Qt C++ program, I run into multiple problems when trying to include Python.h.
The following features, I would like to provide:
Include python.h
Execute Python Strings
Execute Python Scripts
Execute Python Scripts with Arguments
It should also work when Python is not installed on the deployed machine
Therefore I searched around the Internet to try to find a solution. And found a lot of Questions and Blogs, but non have them covered all my Problems and it still took me multiple hours and a lot of frustration.
That's why I have to write down a StackOverflow entry with my full solution so it might help and might accelerate all your work :)
(This answer and all its code examples work also in a non-Qt environment. Only 2. and 4. are Qt specific)
Download and install Python https://www.python.org/downloads/release
Alter the .pro file of your project and add the following lines (edit for your correct python path):
INCLUDEPATH = "C:\Users\Public\AppData\Local\Programs\Python\Python39\include"
LIBS += -L"C:\Users\Public\AppData\Local\Programs\Python\Python39\libs" -l"python39"
Example main.cpp code:
#include <QCoreApplication>
#pragma push_macro("slots")
#undef slots
#include <Python.h>
#pragma pop_macro("slots")
/*!
* \brief runPy can execut a Python string
* \param string (Python code)
*/
static void runPy(const char* string){
Py_Initialize();
PyRun_SimpleString(string);
Py_Finalize();
}
/*!
* \brief runPyScript executs a Python script
* \param file (the path of the script)
*/
static void runPyScript(const char* file){
FILE* fp;
Py_Initialize();
fp = _Py_fopen(file, "r");
PyRun_SimpleFile(fp, file);
Py_Finalize();
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
runPy("from time import time,ctime\n"
"print('Today is', ctime(time()))\n");
//uncomment the following line to run a script
//runPyScript("test/decode.py");
return a.exec();
}
Whenever you #include <Python.h> use the following code instead. (The Slots from Python will otherwise conflict with the Qt Slots
#pragma push_macro("slots")
#undef slots
#include <Python.h>
#pragma pop_macro("slots")
After compiling, add the python3.dll, python39.dll, as well as the DLLs and Lib Python folders to your compilation folder. You can find them in the root directory of your Python installation. This will allow you to run the embedded c++ code even when python is not installed.
With these steps, I was able to get python running in Qt with the 64 bit MinGW and MSVC compiler. Only the MSVC in debug mode got still a problem.
FURTHER:
If you want to pass arguments to the python script, you need the following function (It can be easy copy-pasted into your code):
/*!
* \brief runPyScriptArgs executs a Python script and passes arguments
* \param file (the path of the script)
* \param argc amount of arguments
* \param argv array of arguments with size of argc
*/
static void runPyScriptArgs(const char* file, int argc, char *argv[]){
FILE* fp;
wchar_t** wargv = new wchar_t*[argc];
for(int i = 0; i < argc; i++)
{
wargv[i] = Py_DecodeLocale(argv[i], nullptr);
if(wargv[i] == nullptr)
{
return;
}
}
Py_SetProgramName(wargv[0]);
Py_Initialize();
PySys_SetArgv(argc, wargv);
fp = _Py_fopen(file, "r");
PyRun_SimpleFile(fp, file);
Py_Finalize();
for(int i = 0; i < argc; i++)
{
PyMem_RawFree(wargv[i]);
wargv[i] = nullptr;
}
delete[] wargv;
wargv = nullptr;
}
To use this function, call it like this (For example in your main):
int py_argc = 2;
char* py_argv[py_argc];
py_argv[0] = "Progamm";
py_argv[1] = "Hello";
runPyScriptArgs("test/test.py", py_argc, py_argv);
Together with the test.py script in the test folder:
import sys
if len(sys.argv) != 2:
sys.exit("Not enough args")
ca_one = str(sys.argv[0])
ca_two = str(sys.argv[1])
print ("My command line args are " + ca_one + " and " + ca_two)
you get the following output:
My command line args are Progamm and Hello

Windows application using python and c++

I want to start working on my own windows software. I know python and I am learning c++. How can I create windows software with the frontend written in c++ and the backend in python?
I know this is possible because blender is written in c++ and python aswell
You can embed Python into C++.
Documentation
The simplest form of embedding Python is the use of the very high level interface. This interface is intended to execute a Python script without needing to interact with the application directly. This can for example be used to perform some operation on a file.
#define PY_SSIZE_T_CLEAN
#include <Python.h>
int
main(int argc, char *argv[])
{
wchar_t *program = Py_DecodeLocale(argv[0], NULL);
if (program == NULL) {
fprintf(stderr, "Fatal error: cannot decode argv[0]\n");
exit(1);
}
Py_SetProgramName(program); /* optional but recommended */
Py_Initialize();
PyRun_SimpleString("from time import time,ctime\n"
"print('Today is', ctime(time()))\n");
if (Py_FinalizeEx() < 0) {
exit(120);
}
PyMem_RawFree(program);
return 0;
}

How to embed Python code with matplotlib in interactive mode into C?

I'd like to re-use a Python script that makes use of matplotlib in interactive mode by embedding a call to it from a C application -- what do I need to do in order to get interactive mode in an embedded Python script working?
I set up an extremely simple example using PyRun_SimpleString(); it works when interactive mode is turned off, but when interactive mode is on the plot window only shows up for a brief interval right before the application ends
#include <Python.h>
int
main(int argc, char *argv[])
{
wchar_t *program = Py_DecodeLocale(argv[0], NULL);
if (program == NULL) {
fprintf(stderr, "Fatal error: cannot decode argv[0]\n");
exit(1);
}
Py_SetProgramName(program); /* optional but recommended */
Py_Initialize();
PyRun_SimpleString("from time import time,ctime,sleep\n"
"import matplotlib.pyplot as plt\n"
"import matplotlib\n"
"print(matplotlib.get_backend())\n"
"plt.ion()\n"
"plt.plot([1,2,3,4,3,5,7])\n"
"sleep(5)\n");
Py_Finalize();
PyMem_RawFree(program);
return 0;
}
The backend used by matplotlib is Qt4Agg. When I execute the lines above in the Python interpreter, it behaves as I'd expect. If I change the plt.ion() to a plt.ioff() and put in a plt.show() after the plt.plot() call, I also see the plot.
I'm assuming when you say, "[w]hen I execute the lines above in the Python interpreter, it behaves as I'd expect," you're referring to running it within the Python command line/REPL. The right way to test one to one behavior with embedded Python would be to instead place your in a python script and then try running it with python script.py.
You'll notice that within a script your code gives a similar problem. I think the trick is to use plt.pause(5) instead of sleep(5), this allows the event loop for the plot GUI to fire and actually draw the window properly (https://stackoverflow.com/a/35119003/11365663).
For REPLs, matplotlib has some extra magic so that the details of the event loop are hidden from you.
This worked for me:
#include <Python.h>
int
main(int argc, char *argv[])
{
wchar_t *program = Py_DecodeLocale(argv[0], NULL);
if (program == NULL) {
fprintf(stderr, "Fatal error: cannot decode argv[0]\n");
exit(1);
}
Py_SetProgramName(program); /* optional but recommended */
Py_Initialize();
PyRun_SimpleString("from time import time,ctime,sleep\n"
"import matplotlib.pyplot as plt\n"
"import matplotlib\n"
"print(matplotlib.get_backend())\n"
"plt.ion()\n"
"plt.plot([1,2,3,4,3,5,7])\n"
"plt.pause(5)\n");
Py_Finalize();
PyMem_RawFree(program);
return 0;
}

Segmentation fault error in python embedded code in C++ code of Omnet++ simple module

I want to call a Python function from C++ code in OMNeT++ simple module.
I debugged the code using gdb. It passes all lines fine, but at the end the
segmentation fault occurs after Py_Finalize();.
I found the following issue on GitHub that describes the same problem.
But it did not help me to resolve the problem.
double result=0;
// 1) Initialise python interpretator
if (!Py_IsInitialized()) {
Py_Initialize();
//Py_AtExit(Py_Finalize);
}
// 2) Initialise python thread mechanism
if (!PyEval_ThreadsInitialized()) {
PyEval_InitThreads();
assert(PyEval_ThreadsInitialized());
}
PyGILState_STATE s = PyGILState_Ensure();
PyRun_SimpleString("import sys; sys.path.append('/home/mypath/')");
PyObject *pName = PyUnicode_DecodeFSDefault((char*)"integrationTest");
PyObject* pModule = PyImport_Import(pName);
if (pModule != NULL)
{
PyObject* pFunction = PyObject_GetAttrString(pModule, (char*)"calculateExecutionTime");
/// changement will be held in this level Args and function result.
PyObject* pArgs = PyTuple_Pack(2,PyFloat_FromDouble(2.0),PyFloat_FromDouble(8.0));
PyObject* pResult = PyObject_CallObject(pFunction, pArgs);
result = (double)PyFloat_AsDouble(pResult);
///////
}
// Clean up
PyGILState_Release(s);
Py_DECREF(pName);
Py_DECREF(pModule);
Py_Finalize();
The problem occurs after the first initialization/uninitialization of python interpreter. What happens during the OmneT++ simulation is initializing/uninitializing/re-initializing/... the Python interpreter. However, Numpy doesn't support this;
So, I resolved this problem by initializing python interpreter just one time in the beginning of the simulation in initialize() method. Then, I called Py_Finalize(); in the destructor.

Categories