Я выживаю, чтобы моя программа на C ++ могла встроить сценарий python, чтобы я мог изменять код обработки изображения извне.
Мне удалось сделать так, чтобы он мог работать на одном изображении,
но когда я пытаюсь снять непрерывное изображение и выполнить обработку изображения, это не удалось.
Можете ли вы мне помочь?
Моя среда:
- Windows 10, Python версия: 3.8.1 (32 бита) и соответствующая numpy
- Visual Studio 2019 v16.4.3 [vcvarsall.bat] Среда, инициализированная для: 'x86'
- Qt creator 5.14 (MSV C 2017,32 bit) и его qmake как моя IDE
Ниже приведены мои исходные коды.
Файл проекта Qt: testPyScript.pro
QT -= gui
CONFIG += c++11 console
CONFIG -= app_bundle
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
Python_wrapper.cpp \
main.cpp
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
HEADERS += \
Python_wrapper.h
# Python
INCLUDEPATH += "C:/Python/Python38-32/include"
LIBS += -L"C:/Python/Python38-32/libs" \
-lpython38 \
-lpython3
#numpy
INCLUDEPATH +="C:/Python/Python38-32/Lib/site-packages/numpy/core/include"
# opencv
INCLUDEPATH += "C:/opencv/include"
CONFIG(debug, debug|release) {
LIBS += -L"C:/opencv/lib/Debug" \
-lopencv_core420d \
-lopencv_highgui420d \
-lopencv_imgcodecs420d \
-lopencv_imgproc420d \
-lopencv_videoio420d
}
CONFIG(release, debug|release) {
LIBS += -L"C:/opencv/lib/Release" \
-lopencv_core420 \
-lopencv_highgui420 \
-lopencv_imgcodecs420 \
-lopencv_imgproc420 \
-lopencv_videoio420
}
Python_wrapper.h
#ifndef PYTHON_WRAPPER_H
#define PYTHON_WRAPPER_H
#pragma push_macro("slots")
#undef slots
#include <Python.h>
#include <numpy/arrayobject.h>
#include <opencv2/core.hpp>
extern PyObject *pyModule,*pyFunc;
bool init_python();
void end_python();
PyObject* convertImage(const cv::Mat& image) ;
std::string type2str(int type) ;
#pragma pop_macro("slots")
#endif // PYTHON_WRAPPER_H
Python_wrapper. cpp
#include"Python_wrapper.h"
#include<fstream>
#include<QDebug>
#include <sys/stat.h>
PyObject *pyModule=nullptr;
PyObject *pyFunc=nullptr;
bool IsPathExist(const std::string &s)
{
struct stat buffer;
return (stat (s.c_str(), &buffer) == 0);
}
bool init_python()
{
if (!Py_IsInitialized())
{
//set python path
std::ifstream infile;
infile.open("PYTHON_PATH",std::ios::in);
if(infile)
{
qDebug()<<"Given python_path file."<<endl;
std::string python_path;
infile>>python_path;
infile.close();
qDebug()<<"Given python path:"<<python_path.c_str()<<endl;
// check path if exists
if(!IsPathExist(python_path))
{
qDebug()<<"Can not find given python path."<<endl;
return false;
}
std::string env = getenv("PATH");
env += ";"+python_path;
putenv(env.c_str());
}
else
{
qDebug()<<"No specify on python path. Default python will be used."<<endl;
}
qDebug()<<"Py_Initialize..."<<endl;
Py_Initialize();
if(Py_IsInitialized())
qDebug()<<"Py_Initialize. OK."<<endl;
else
{
qDebug()<<"Failed to initialize Python."<<endl;
return false;
}
qDebug()<<"Python version:"<<Py_GetVersion()<<endl;
//add current folder to module serach parth
QString modulePath=QString::fromWCharArray(Py_GetPath());
qDebug()<<"Module search path:"<<modulePath<<endl;
//import modoule
qDebug()<<"Import python module <py_cv>..."<<endl;
pyModule = PyImport_ImportModule("py_cv");
if (pyModule == nullptr)
{
qDebug()<<"Failed to load python module <py_cv>"<<endl;
PyErr_Print();
return false;
}
//import module function
qDebug()<<"Import python function <test>"<<endl;
pyFunc =PyObject_GetAttrString(pyModule,"test");
if (pyFunc == NULL)
{
qDebug()<<"Failed to load python function <test>"<<endl;
PyErr_Print();
return false;
}
}
import_array();
}
void end_python()
{
if(Py_IsInitialized())
Py_Finalize();
}
PyObject* convertImage(const cv::Mat& image) {
//2D image with 3 channels.
npy_intp dimensions[3] = {image.rows, image.cols, image.channels()};
//image.dims = 2 for a 2D image, so add another dimension for channels.
return PyArray_SimpleNewFromData(image.dims + 1, (npy_intp*)&dimensions, NPY_UINT8, image.data);
}
std::string type2str(int type) {
std::string r;
uchar depth = type & CV_MAT_DEPTH_MASK;
uchar chans = 1 + (type >> CV_CN_SHIFT);
switch ( depth ) {
case CV_8U: r = "8U"; break;
case CV_8S: r = "8S"; break;
case CV_16U: r = "16U"; break;
case CV_16S: r = "16S"; break;
case CV_32S: r = "32S"; break;
case CV_32F: r = "32F"; break;
case CV_64F: r = "64F"; break;
default: r = "User"; break;
}
r += "C";
r += (chans+'0');
return r;
}
main. cpp
#include "Python_wrapper.h"
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include<iostream>
int py_image_process(cv::Mat &img)
{
int ierr=-1;
std::cout<<"MatToNDArray"<<std::endl;
PyObject *pyMat =convertImage(img);
std::cout<<"Image type:"<<type2str(img.type()).c_str()<<std::endl;
double d=100.0;
PyObject *pyArgs = PyTuple_New(2);
PyObject* pyD=PyFloat_FromDouble(d);
PyTuple_SetItem(pyArgs,0, pyMat);
PyTuple_SetItem(pyArgs,1,pyD);
PyObject *pyValue= PyObject_CallObject(pyFunc, pyArgs);
if (pyValue != NULL)
{
std::cout<<"Function performed OK"<<std::endl;
if (PyTuple_Check(pyValue))
{
std::cout<<"Check PyValue as Tuple OK"<<std::endl;
ierr = PyLong_AsLong(PyTuple_GetItem(pyValue, 0));
PyObject* bytes = PyTuple_GetItem(pyValue, 1);
std::string msg = PyUnicode_AsUTF8(bytes);
std::cout<<"msg:"<<msg.c_str()<<std::endl;
}
Py_DECREF(pyValue);
}
else
std::cout<<"Failed to perform function"<<std::endl;
Py_XDECREF(pyArgs);
return ierr;
}
int main()
{
int ierr=-1;
std::cout<<"Test embeded python"<<std::endl;
if(!init_python())
{
end_python();
return 2;
}
cv::VideoCapture cap =cv::VideoCapture(0);
// cv::Mat img =cv::imread("0.jpg",cv::IMREAD_COLOR);
cv::Mat img;
for(;;)
{
cap.read(img);
if(!img.empty())
{
// ierr= py_image_process(img);
cv::imshow("image",img);
}
else
break;
if(cv::waitKey(5)>=0) break;
}
cv::destroyAllWindows();
return ierr;
}
и python тестовый скрипт: py_cv.py
import cv2
import numpy as np
def test(img,d):
print(type(img),type(d))
rows,cols,chs=img.shape
cx,cy=int(rows/2),int(cols/2)
d=int(d/2.0)
cv2.circle(img,(cx,cy),d,(0,255,0),2)
return -99,"test message"
Ваша помощь очень важна.