QT C++调用python传递RGB图像和三维数组,并接受python返回值(图像)

目的:

用QT调用python代码,将QT读取的图像(Qimage)作为参数传入python中,将QT的三维数组作为参数传递给python,python接收QT传入的图像进行计算,将结果返回给QT并显示。

一   .pro 头文件的配置,和lib库的配置


INCLUDEPATH += \
    -I D:\tools\python3_9\include
INCLUDEPATH += \
    -I D:\tools\python3_9\Lib\site-packages\numpy\core\include
LIBS += \
    -L D:\tools\python3_9\libs -lpython39

 二。系统环境变量的配置  在path添加 python环境   D:/tools/python3_9

三,python环境的初始化

//加入python环境
  1.  Py_SetPythonHome(L"D:/tools/python3_9");

  2. 类似于先连接上Python    Py_Initialize();


  3. 注意使用这个 import_array1(); 用于后边numpy数组的调用,   import_array();会报无返回值的错误。

其他看代码注释

 


void  MainForm::init_python()
{

    //加入python
    Py_SetPythonHome(L"D:/tools/python3_9");
    // 1. 类似于先连接上Python

    Py_Initialize();
    import_array1();
    if (!Py_IsInitialized()) {
        qDebug() << "Fail to init Python.";
    }


    // 2. 加入python文件的路径
    PyRun_SimpleString("import os");
    PyRun_SimpleString("import sys");
    std::string path = "sys.path.append('E:/DigitalScreen/StuEmo/realtime_detect')";
    PyRun_SimpleString(&path[0]);
    PyRun_SimpleString("print(sys.path)");

    // 3. 找到要用的python文件
     PyObject * pModule = PyImport_ImportModule("capture_xjh");
    if (pModule == NULL) {
        qDebug() <<"Fail to load Python module (capture_xjh.py)";
    }

    // 1. 找到Python的类
    PyObject* pDict = PyModule_GetDict(pModule);
    if(!pDict) {
        qDebug() << "Cant find dictionary.";
    }
     Py_DECREF(pModule);

    PyObject* pClassCalc = PyDict_GetItemString(pDict, "RtDetector");
    if (!pClassCalc) {
        qDebug() << "Cant find PythonClass class.";
    }
    Py_DECREF(pDict);
    // 2. 初始化对象
    PyObject* pConstruct = PyInstanceMethod_New(pClassCalc);
    if (!pConstruct) {
        qDebug() << "Cant find PythonClass constructor.";
    }
    Py_DECREF(pClassCalc);

    PyObject* cons_args = PyTuple_New(5);
    PyTuple_SetItem(cons_args, 0, Py_BuildValue("s",  "group1"));
    PyTuple_SetItem(cons_args, 1, Py_BuildValue("s",  "E:/DigitalScreen/StuEmo/GROUP_DATA/"));
    PyTuple_SetItem(cons_args, 2, Py_BuildValue("s",   "E:/DigitalScreen/StuEmo/weights/detr_face_body.pt"));
    PyTuple_SetItem(cons_args, 3, Py_BuildValue("s",   "E:/DigitalScreen/StuEmo/realtime_detect/Person_reID/model/ft_ResNet50/net_last.pth"));
    PyTuple_SetItem(cons_args, 4, Py_BuildValue("O",   Py_True));

    pInstance = PyObject_CallObject(pConstruct, cons_args);
    if (!pInstance) {
        qDebug() << "Cant construct instance.";
    }
    Py_DECREF(cons_args);
    Py_DECREF(pConstruct);

    // PyObject* methods = PyObject_Dir(pInstance);
    // if (methods) {
    //     // 遍历返回的方法列表
    //     for (Py_ssize_t i = 0; i < PyList_GET_SIZE(methods); ++i) {
    //         PyObject* method = PyList_GET_ITEM(methods, i);
    //         const char* methodName = PyUnicode_AsUTF8(method);
    //         qDebug() << "Method Name:" << methodName;
    //     }
    //     Py_DECREF(methods);
    // } else {
    //     qDebug() << "Failed to get methods of the instance.";
    // }

    //测试
    // PyObject* pRet =PyObject_CallMethod(pInstance,"addTest1","ii",5,6);
    // if (!pRet) {
    //     qDebug() << "Cant addTest.";
    // }
    // else{
    //     double ret = PyFloat_AsDouble(pRet);
    //     qDebug() << "sum: " << ret;
    // }

    // Py_DECREF(pRet);

    //通过图片检测
     QImage qImage ("E:/DigitalScreen/StuEmo/images/1.png");
     UsePythonface(  qImage);
}

四,Qimage  转换到numpy数组的使用

Qimage 传入的是QImage::Format_RGB888格式图片,通过

  for (int i = 0; i < height; i++)
        {
            for (int j = 0; j < width; j++)
            {
                QRgb pixel = qImage.pixel( j,i);

                CArrays[index++] = qRed(pixel);
                CArrays[index++] = qGreen(pixel);
                CArrays[index++] = qBlue(pixel);
            }
        }转换为一维数组CArrays

 // 创建 NumPy 数组 通过CArrays转换而来
        npy_intp dims[3] = { height, width, 3 }; // 图像是RGB格式的
        PyObject* imageArray = PyArray_SimpleNewFromData(3, dims, NPY_UINT8, (void*)CArrays);

返回值又通过 mempcpy(CArrays,PyArray_DATA(imageData),width*height*3);
  再生成      QImage img((unsigned char*)CArrays, width, height,  QImage::Format_RGB888);

调用 disp_image( img);显示图像


void MainForm::UsePythonface( QImage qImage)
{
    if(!qImage.isNull())
    {
        int width = qImage.width();
        int height = qImage.height();
        unsigned char *CArrays = (unsigned  char*)malloc(sizeof(unsigned char) * width*height*3);
        qDebug()<<"qImage.width()"<<qImage.width()<<"qImage.height()"<<qImage.height()<<"qImage.format()"<<qImage.format()<<endl;

        int index =0;
        for (int i = 0; i < height; i++)
        {
            for (int j = 0; j < width; j++)
            {
                QRgb pixel = qImage.pixel( j,i);

                CArrays[index++] = qRed(pixel);
                CArrays[index++] = qGreen(pixel);
                CArrays[index++] = qBlue(pixel);
            }
        }
        //qDebug()<< CArrays[width*height*3-1] <<endl;
        // 创建 NumPy 数组
        npy_intp dims[3] = { height, width, 3 }; // 假设图像是RGB格式的
        PyObject* imageArray = PyArray_SimpleNewFromData(3, dims, NPY_UINT8, (void*)CArrays);



        //qDebug()<<"start UsePythonface"<<endl;
        PyObject* imageData = PyObject_CallMethod(pInstance, "process_frame", "O", imageArray);
        Py_DECREF(imageArray);
        if(!imageData)
        {
            PyErr_Print(); // 打印 Python 错误信息
            qDebug()<<"cant UsePythonface"<<endl;
            return;
        }

        // qDebug()<<"end UsePythonface"<<endl;
        mempcpy(CArrays,PyArray_DATA(imageData),width*height*3);
        QImage img((unsigned char*)CArrays, width, height,  QImage::Format_RGB888);
        //qDebug()<<"img.width()"<<img.width()<<"img.height()"<<img.height()<<"img.format()"<<img.format()<<endl;

        CArrays = nullptr;
        delete[] CArrays;

        Py_DECREF(imageData);
        disp_image( img);

    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/292634.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

在 Mac 上轻松安装和配置 JMeter

Apache JMeter 是一个开源的负载测试工具&#xff0c;可以用于测试静态和动态资源&#xff0c;确定服务器的性能和稳定性。在本文中&#xff0c;我们将讨论如何下载和安装 JMeter。 安装 Java&#xff08;已安装 Java 的此步骤可跳过&#xff09; 要安装 Java&#xff0c;请按…

数字孪生与边缘计算的结合

数字孪生与边缘计算的结合可以在物理实体附近进行实时数据处理和决策&#xff0c;从而提高响应速度、降低延迟&#xff0c;并有效地利用边缘资源。以下是数字孪生在边缘计算中的一些应用&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开…

JavaWeb——后端之SpringBoot基础知识

2. SpringBoot 官网&#xff1a;https://spring.io/ Spring全家桶&#xff1a;Spring已经形成了一种开发生态圈&#xff0c;其提供的若干子项目分别用于完成特定的功能 Spring Boot简化了Spring Framework&#xff0c;不用底层实现那么配置繁琐&#xff0c;可以快速构建应用…

【Java EE初阶八】多线程案例(计时器模型)

1. java标准库的计时器 1.1 关于计时器 计时器类似闹钟&#xff0c;有定时的功能&#xff0c;其主要是到时间就会执行某一操作&#xff0c;即可以指定时间&#xff0c;去执行某一逻辑&#xff08;某一代码&#xff09;。 1.2 计时器的简单介绍 在java标准库中&#xff0c;提供…

ChatGPT怎么帮我上班的

1.解放生产力 1&#xff09;标准格式&#xff0c;完美输出。GPT对于公文等具有一定标准格式的文件&#xff0c;可以进行完美仿写&#xff0c;随随便便以假乱真那都是小菜一碟&#xff0c;这对于经常要开展规范成文的人来说&#xff0c;简直就是个福音&#xff0c;只要前期调教…

使用“反向代理服务器”的优点是什么?

反向代理服务器是一种网络架构模式&#xff0c;通常位于客户端和实际服务器之间&#xff0c;用于处理客户端请求并转发到实际服务器。以下是使用反向代理服务器的优点&#xff1a; 1.安全性&#xff1a;反向代理服务器可以提供额外的安全层。通过在反向代理服务器上配置防火墙和…

Jmeter 性能压测 —— 常见问题

1、怎么确定系统最大负载&#xff1f; 通过负载测试&#xff0c;不断增加用户数&#xff0c;随着用户数的增加&#xff0c;各项性能指标也会相应产生变化&#xff0c;当出现了性能拐点。 比如&#xff0c;当用户数达到某个数量级时&#xff0c;响应时间突然增长&#xff0c;那…

电脑重装后恢复音频输出(安装声卡驱动)

写在前面&#xff1a;本博客仅作记录学习之用&#xff0c;部分图片来自网络&#xff0c;如需引用请注明出处&#xff0c;同时如有侵犯您的权益&#xff0c;请联系删除&#xff01; 文章目录 前言基本设置检查声卡驱动自带Realtek高清晰音频管理器不带Realtek高清晰音频管理器 总…

ROS学习笔记(8)进一步深入了解ROS第二步

0.前提 在上一讲中我提到过该系列是基于宾夕法尼亚大学工程学院的ROS公开课&#xff0c;系列文章将来源于公开课中的课后习题。该系列可以很好的帮助大家更加深入的了解ROS的一些概念。&#xff08;有效面对HR的提问。&#xff09; 1. (C)What is a nodehandle object? Can we…

vscode无识别已有的maven java项目(visual studio code not recognizing java project)

文章目录 事情经过尝试疑惑问题解决结论 事情经过 未安装任何Java Extension Pack使用 Maven 的 archetype:generate 命令来创建一个新的项目使用vscode打开了该目录然后安装Java Extension Pack等java插件配置了vscode settings.json中的 java.configuration.runtimes和 java…

网站迁移和SEO:损害排名的常见错误

正在规划站点迁移&#xff1f; 迁移是更困难的 - 通常是可怕的 - SEO任务之一。 为了让它发挥作用&#xff0c;你需要避免常见的陷阱&#xff0c;这些陷阱可能会影响你的知名度&#xff0c;并导致流量和收入的损失。 8 月 11 日&#xff0c;我主持了一场赞助的搜索引擎杂志网…

TypeScript 从入门到进阶之基础篇(二) ts进阶类型篇

TypeScript 从入门到进阶系列 TypeScript 从入门到进阶之基础篇(一) ts基础类型篇 文章目录 TypeScript 从入门到进阶系列前言一、object 类型1、基础运用2、可选属性3、任意属性4、只读属性 readonly5、对象中的函数 二、数组类型1、数组的运用2、使用接口定义数组3、argumen…

关于标准那些事——第六篇 四象之“玄武”(格式的编排)

两仪生四象——东方青龙&#xff08;木&#xff09;、西方白虎&#xff08;金&#xff09;、南方朱雀&#xff08;火&#xff09;、北方玄武&#xff08;水&#xff09; 分别对应标准编写之四象——层次的编写、要素的编写、要素的表述、格式的编排。 今天来分享一下 格式的编…

Python 标准库中的 csv 包

0. Abstract 官方文档很罗嗦&#xff0c;长篇大论例子少。本文将举例说明 csv 包的用法&#xff0c;然后补充一些必要的说明。 1.0 CSV 文件 CSV(Comma-Separated Values,逗号分隔值)文件是一种常见的以纯文本形式存储数据的文件格式。它使用逗号作为字段之间的分隔符&#…

【Linux】——基本指令(二)

&#x1f497;个人主页&#x1f497; ⭐个人专栏——数据结构学习⭐ &#x1f4ab;点击关注&#x1f929;一起学习C语言&#x1f4af;&#x1f4ab; 目录 导读&#xff1a;1. vim 指令2. head指令3. tail指令4. tree指令5. 输出重定向6. echo指令7. wc指令8. | 字符9. date指令…

CMake入门教程【核心篇】属性管理set_property和get_property

&#x1f608;「CSDN主页」&#xff1a;传送门 &#x1f608;「Bilibil首页」&#xff1a;传送门 &#x1f608;「本文的内容」&#xff1a;CMake入门教程 &#x1f608;「动动你的小手」&#xff1a;点赞&#x1f44d;收藏⭐️评论&#x1f4dd; 文章目录 1.概述2.设置属性 - …

JS中 focus 和 blur 焦点事件

发现的一个小知识点 focus 获取焦点事件 代码如下&#xff1a; <body><input type"text" placeholder"input输入框"><script>let input document.querySelector(input)input.addEventListener(focus, function (e) {e.target.style.…

Java学校教务管理系统源码带微信小程序

运行环境&#xff1a;jdk8mysql5.7IntelliJ IDEAmaven 技术&#xff1a;springbootmybatislayuishirojquery 教务管理系统是一个基于网络的在线管理平台, 帮助学校管理教务系统&#xff0c;用一个帐号解决学校教务教学管理&#xff0c; 灵活的定制符合学校自己实际情况的教务系…

如何理解面向对象的OO设计原则和设计模式?

一、如何理解面向对象的编程原则? 单一职责原则(Single Responsibility Principle) 一个类,应该由一组相关性很高的数据和方法组成。一个类应该仅有一个引起它变化的原因。单一职责最难界定的就是关于“职责”的定义,往往需要丰富的经验和对业务的认知程度,这也更加容易引…

WEB 3D技术 three.js 法向量演示性讲解

本文 我们来说法向 法向 又叫 法向量 就是 我们一个三维物体 顶点垂直于面 的方向 向量 他的作用 用来做光反射 根据光照的方向 根据面进行反射 我们上文写的这个代码 import ./style.css import * as THREE from "three"; import { OrbitControls } from "…
最新文章