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

news2025/6/30 22:35:10

任务目的:

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

实现过程

1.新建QT项目

说明:QT的编译环境我使用的MinGW 64,编译的release包
(1)按照下图依次选择Application,Qt Widgets Application, 然后点击右下角Choose。
在这里插入图片描述
然后给项目起一个名字,名称:Qt_call_Python,创建路径:D:\QTWorkSpace(选择自己的路径)
在这里插入图片描述
继续下一步
在这里插入图片描述
继续下一步,在这里我使用的是Widget,在Base class里面选择QWiget即可,其它会自动默认,无须改变,当然改一下名字也可以,没什么问题。
在这里插入图片描述
继续下一步
在这里插入图片描述
这里注意,我选择的是Desktop Qt 5.14.2 MinGW 64-bit,主要是因为我编译Opencv时使用的就是这个,因此这里我选用这个编译器,这里需要搞清楚自己的opencv编译时自己选择的编译器,否则乱用的话可能会出现报错,例如找不到opencv中某些dll文件等等。
在这里插入图片描述
继续下一步
在这里插入图片描述
到此,项目新建完成,可以运行一下,看是否出现了空白窗体。

在这里插入图片描述

2.配置项目环境

(1)图像的读取操作需要借助Opencv库进行,因此项目新建完成后首先要配置Opencv库目录
首先在项目上右键,选择“添加库”
在这里插入图片描述
选择外部库
在这里插入图片描述
点击库文件,依次参照我的目录层级,找到自己opencv编译好的文件,也就是libopencv_world410.dll.a的目录,然后选中该文件,点击打开。
在这里插入图片描述
如下图,此处1位置,就是我们刚刚选择的libopencv_world410.dll.a的路径。注意2这个位置,包含路径在选择了1之后默认自己生成了一个目录,这个目录是错的,我们要通过浏览自己选择include的目录位置。
在这里插入图片描述
选到include之后,然后其它的不要动,全部默认即可,点击下一步
在这里插入图片描述
点击完下一步,出现这个界面,点击完成即可。
在这里插入图片描述
(2)配置python环境
由于我们需要调用python,所以python环境我们也需要添加到库目录中,执行步骤与上面类似。
选择库文件,我使用的是anaconda的虚拟环境,如果电脑是使用的python,也参照我的目录去寻找红色标记3位置的文件,然后选择打开即可。
在这里插入图片描述
包含路径同样是错误的,需要自己选择到include目录下。
在这里插入图片描述

然后点击下一步,随后选择完成即可。
在这里插入图片描述

(3)配置numpy环境

python科学计算库,numpy的使用频率太高,所以设计到图像的运算一般离不开它,但凡使用到python的numpy库了,不管是显示的调用还是潜在的调用,如果不配置这一步,都会报错

选择numpu库里面的npymath.lib即可,而且这次的包含目录不用自己选择,选择好库文件之后,包含路径正好就是numpy目录的include目录,如果不是的话自己修改一下即可。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
至此,环境配置完毕,运行一下,看没有报错吧
此时的项目文件增加了很多库目录的配置代码,如下
在这里插入图片描述
按照下面的步骤依次选择编译器运行,可以下是否报错,没报错就说明成功了,没什么大问题,但是不保证
在这里插入图片描述

(4)运行代码

python文件一定要放置在运行目录下面,也就是func.py
在这里插入图片描述
func.py代码如下

# This Python file uses the following encoding: utf-8
import cv2
import numpy as np
def myfunc(imgdata):
    print(121)
    image = cv2.imread("3.jpeg")
    cv2.imshow("mywindow", image)
    print(123)
    print(imgdata.shape)
    print(124)
    a,b=imgdata.shape[0],imgdata.shape[1]
    print(125)
    result=imgdata[0:a>>1,0:b>>1]
    print(126)
    print("python out",result.shape)
    #return result,0
    # print(imgdata.shape)
    #a,b=imgdata.shape[0],imgdata.shape[1]
    #result=imgdata[0:a>>1,0:b>>1]
    #print("python out",result.shape)
    #return result,0
    print(np.arange(2))
    return image
    
def myfunc1(data):
    print(911)
    print(data)
    print("over")
# if__name__ == "__main__":
#     pass

QT项目中,其它都默认即可,主要是对main.cpp进行了改动,代码如下

#include "widget.h"
#include <QApplication>
#include <Python.h>
#include <opencv2/opencv.hpp>
#include <QApplication>
#include <iostream>
#include <numpy/ndarrayobject.h>
#include <QDebug>

using namespace std;
using namespace cv;
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    // 设置主目录,就是python的主目录
    Py_SetPythonHome(L"D:\\Anaconda3\\envs\\python38");

    // 初始化python模块
    Py_Initialize();
    import_array();
    // 判定是否初始化成功
    if(!Py_IsInitialized())
    {
        cout<<"初始化python环境失败!"<<endl;
        return -1;
    }
    /*
     * 测试初始化后的python环境,自测使用
    PyRun_SimpleString("import sys");//引入sys模块
    PyRun_SimpleString("sys.path.append('./')");//将存放python文件的路径加入搜寻路径
    PyRun_SimpleString("import numpy as np");
    PyRun_SimpleString("import os");
    PyRun_SimpleString("from datetime import datetime, time");
    PyRun_SimpleString("print(\"hello python\")");
    cout << "point1" << endl;
    */
    // 将python文件导入成PyObject对象,func是python文件的名称,此处不要加.py
    PyObject* m_pyObj = PyImport_ImportModule("func");
    // 获取函数,myfunc表示调用的python文件内的myfunc函数
    PyObject *pFunc = PyObject_GetAttrString(m_pyObj, "myfunc");
    /*
     * 简单调用测试,测试python文件是否调用成功
    QString inputPara = "this is paras";
    //调用python中的Myfun函数,返回值是ret,s代表是字符串格式,如果是int则写i,double写d
    auto ret = PyObject_CallMethod(m_pyObj, "myfunc", "i", 2);
    */
    /

    // 读取一张图像
    cv::Mat image = cv::imread("3.jpeg");
    // 打印图像的大小
    cout<<image.size()<< endl;
    // 保存图像大小
    auto sz = image.size();
    int x = sz.width;
    int y = sz.height;
    int z = image.channels();
    //注意这个维度数据!
    npy_intp Dims[3] = {y, x, z};
    cout<<"point2"<<endl;
    cout << Dims[0] << endl;

    
    int array_x = 3;
    int array_y = 3;
    // 定义二维数组
    double CArrays[3][3] = {{1.3, 2.4, 5.6}, {4.5, 7.8, 8.9}, {1.7, 0.4, 0.8}};
    // 设置维度数据
    npy_intp Dims_array[2] = {3, 3};
    int nElem_array = 3 * 3;
    uchar* m_array = new uchar[nElem_array];
    // 将数组复制到新建的数组中
    std::memcpy(m_array, image.data, nElem_array * sizeof(uchar));
    // 生成包含这个多维数组的PyObject对象,使用PyArray_SimpleNewFromData函数,第一个参数3表示维度,第二个为维度数组Dims,第三个参数指出数组的类型,第四个参数为数组
    PyObject *PyArray_array  = PyArray_SimpleNewFromData(2, Dims_array, NPY_DOUBLE, (void*)m_array);
    // 创建一个大小为1的元组对象
    PyObject *ArgArray_array = PyTuple_New(1);
    // 设置Tuple的某一个元素,参数为索引index和要传入的PyObject对象
    PyTuple_SetItem(ArgArray_array, 0, PyArray_array);
    // 调用函数,传入Numpy Array 对象。
    PyObject_CallObject(pFunc, ArgArray_array);
    //调用函数,传入Numpy Array 对象。
    PyObject_CallMethod(m_pyObj, "myfunc1", "O", PyArray_array);
    

    // 所有像素点的数量,要乘以通道数,灰度图单通道,彩色图三通道
    int nElem = x * y * z;
    // 创建与像素个数大小相同的数组
    uchar* m = new uchar[nElem];
    // 将Mat格式矩阵数据复制到新建的数组中
    std::memcpy(m, image.data, nElem * sizeof(uchar));
    // 生成包含这个多维数组的PyObject对象,使用PyArray_SimpleNewFromData函数,第一个参数3表示维度,第二个为维度数组Dims,第三个参数指出数组的类型,第四个参数为数组
    PyObject *PyArray  = PyArray_SimpleNewFromData(3, Dims, NPY_UINT8, (void*)m);
    // 创建一个大小为1的元组对象
    PyObject *ArgArray = PyTuple_New(1);
    // 设置Tuple的某一个元素,参数为索引index和要传入的PyObject对象
    PyTuple_SetItem(ArgArray, 0, PyArray);
    // 调用函数,传入Numpy Array 对象。
    PyObject_CallObject(pFunc, ArgArray);
    //调用函数,传入Numpy Array 对象。
    PyObject *rest = PyObject_CallMethod(m_pyObj, "myfunc", "O", PyArray);
    // 获取返回值
    if(rest)
    {
        PyObject *repr = PyObject_Repr(rest);
        PyObject *imgfrompy = PyUnicode_AsEncodedString(repr, "utf-8", "strict");
        char *result = PyBytes_AsString(imgfrompy);
        // 打印返回值
        qDebug()<<result<<"end"<<endl;
    }
    Py_Finalize();

    Widget w;
    w.show();
    return a.exec();
}

然后就是愉快的运行程序了,不出意外的话结果如下
在这里插入图片描述
上图中1标记,表示的是QT接收的python的返回结果,打印的是图像的像素矩阵,标识2,是python代码运行时的窗口,显示的是一幅图像。

在这里插入图片描述
上图1是python程序的打印结果,1标记是图像部分,2标记是QT传递二维数据,python打印结果,显然打印结果跟QT里面结果是不一致的,这里我还没有研究是怎么回事,但是对于传递参数起到了一个参考作用。可以借鉴进行。

整个项目包括运行目录的程序包组合可以在下面的链接进行获取。
https://download.csdn.net/download/weixin_43552197/87323611

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[Cortex-M3]-5-cache uncache

目录 1 cache的引入 2 cache的工作原理 3 cache使用限制 1 cache的引入 程序运行的流程&#xff08;很简单&#xff09;&#xff1a; 程序编译&#xff1a;存放在flash&#xff1b;程序加载&#xff1a;程序加载到内存&#xff1b;程序运行&#xff1a;指令从内存复制到CP…

【产品人卫朋】自媒体运营的5个阶段,以及增长策略

本篇内容以微信公众号为例讲解自媒体的运营策略。 建立一个快速发展的微信公众号&#xff0c;需要多长时间呢&#xff1f; 有些人在一年内就可以建立一个蓬勃发展的公众号&#xff0c;而其他人则可能需要两年、三年甚至是五年的时间。 在发展的过程中&#xff0c;你的公众号将经…

阿里工程师告诉你,0基础如何自学python进大厂

大概一年前这个朋友就想学习Python了&#xff0c;但因为工作比较忙&#xff0c;而且觉得Python肯定不太好学&#xff0c;所以一直搁置在那里。 宅家学Python 到了今年1月28日也就是大年初三的时候&#xff0c;眼看新冠肺炎疫情不会短时间结束了&#xff0c;全国各地都在严控&…

原型模式

开始原型模式前&#xff0c;我们要知道深拷贝的定义&#xff0c;因为原型模式中的克隆操作核心就是深拷贝。 深拷贝和浅拷贝 下图为浅拷贝(即是编译器的默认版本), 只拷贝了指针, 两个指针同时指向一个内存, 会有危险(a改变时b也改变, 称为别名) , 导致内存泄漏 调用strcpy复…

Qt扫盲-QTreeWidget理论总结

QTreeWidget理论总结1. 简述2. QTreeWidgetItem 简述3. 头标签4. 常用功能5. 槽函数6. 信号1. 简述 QTreeWidget 类是Qt提供了一个标准的树部件&#xff0c;该部件具有经典的基于 Item 的界面&#xff0c;每个Item都是一个 QTreeWidgetItem。这个标准的树控件不需要model/view…

文科女进德国IBM实习做程序媛,我是怎么办到的?

很快我在IBM德国区实习的第一个月就要结束了。 作为一个土生土长的文科生&#xff08;硕士语言学、本科语言学商科&#xff09;&#xff0c;现在竟在欧洲混入跨国科技公司做编程技术类实习生&#xff0c;我自己也挺意外的。 尽管只是一点点微不足道的个人经历&#xff0c;此时…

教你如何优雅的转行Python程序员,一学就会

在实际的工作中&#xff0c;我们经常发现&#xff0c;很多朋友在某一个工作中做了一段时间&#xff0c;发现自己越做越没兴趣&#xff0c;越做越不开心&#xff0c;想跳不敢跳&#xff0c;想辞不敢辞&#xff0c;最后影响了自己的本职工作&#xff0c;陷入两难的窘境。 其实&am…

【Qbot】3.加入内容审核功能

该项目计划长期进行维护更新&#xff0c;欢迎star&#xff1a;https://github.com/zstar1003/Qbot 前言 在ChatGPT上线Q群不久&#xff0c;不少人对其进行了测试&#xff0c;但随着时间的延续&#xff0c;测试话题逐渐走向失控&#xff0c;迫使我不得不紧急暂停。 对同胞素质的…

【Python百日进阶-数据分析】Day134 - plotly饼图:go.pie()实例

文章目录4.2 go.Pie() 的基本饼图4.2.1 基本饼图4.2.2 样式饼图4.2.3 使用 uniformtext 控制文本字体大小4.2.4 控制饼图中的文本方向4.2.5 甜甜圈图4.2.6 从中心拉出扇区4.2.7 子图中的饼图4.2.8 自定义颜色集的子图4.2.9 绘制面积与总计数成比例的图表4.2.10 旭日图4.2.11 Da…

电脑软件、微信多开

因为办公需要在电脑上登录 2 个微信&#xff0c;但是直接双击微信图标只有 1 个登录界面&#xff0c;无法是现实登录 2 个微信。那么怎么才能在 1 个电脑上打开 2 个微信&#xff0c;方法有四种&#xff1a;1、安装&#xff1b;2、Enter&#xff1b;3、连续点击&#xff1b;4、…

『 canvas 特效』一文教你绘制绚丽的星空背景 TS + ES6

介绍 很久没有写关于 canvas 效果的文章了&#xff0c;刚好最近又学到了一个新的特效&#xff0c;使用 canvas 绘制多层次动态星空背景&#xff0c;今天就分享给大家。首先我们依旧来看一下最终实现的效果&#xff0c;如图所示&#xff1a; 由于录制 GIF 造成失帧&#xff0c;…

实战三十三:STAMP算法实现商品推荐实战 代码+数据

1.案例知识点 推荐系统任务描述:通过用户的历史行为(比如浏览记录、购买记录等等)准确的预测出用户未来的行为;好的推荐系统不仅如此,而且能够拓展用户的视野,帮助他们发现可能感兴趣的却不容易发现的item;同时将埋没在长尾中的好商品推荐给可能感兴趣的用户。STAMP推荐…

记录Win7系统下的node版本升级过程及后续项目启动所遇问题

目录 Windows7系统如何“安装”高版本Node 后续项目运行启动时遇到的问题 Bug &#xff1a; 背景 &#xff1a; 银行内网开发&#xff0c;接到一个新的项目开发&#xff0c;但前提因为开发所使用的云桌面更换了&#xff0c;由原来的Windows10系统降到了现在的Windows7系统&am…

【自媒体必备】AI文字转语音,支持多种人声选择,在线生成一键导出【电脑永久版】

AI文字转语音&#xff0c;支持多种人声选择&#xff0c;在线生成一键导出 软件是电脑版安装版本&#xff0c;大家根据自己安软件的习惯进行安装即可&#xff0c;安装后打开软件即可&#xff0c;且完全免费。语音选择方面就有晓晓、云扬、云希等等常用选择。点击后面的播放按钮…

腾讯大佬告诉你,写Python到底用什么IDE合适

不管你是 Python 新手还是老鸟&#xff0c;肯定纠结过一个问题&#xff1a; 到底用什么编辑器写 Python 代码好&#xff1f; 为此&#xff0c;我们调查了数十位鹅厂程序猿们爱用的 Python IDE&#xff0c;从他们对每款编辑器的看法中&#xff0c;也许能给你一点启示&#xff1…

我对程序员做副业有这几点建议

疫情这几年&#xff0c;“副业”的概念非常火。各大平台上都在说“副业赚钱”、“副业是刚需”等相关的内容、视频&#xff0c;有免费的&#xff0c;还有付费观看的。 其实在2020年疫情之前&#xff0c;大家对于“副业”并没有很关心。 从百度指数上可以明显看出&#xff0c;…

【笔记】Pade Approximations

1 pade approximations是什么&#xff1f; Pad Approximations是一种对pure delay使用常规传函进行近似替换的方法&#xff0c;matlab提供了的一个库函数pade。 在传递函数中&#xff0c;用e−τse^{-\tau s}e−τs表示纯延时pure delay环节&#xff0c;它对信号的幅值不会有任…

微服务框架 SpringCloud微服务架构 微服务面试篇 54 微服务篇 54.2 Nacos的服务注册表结构是怎样的? 54.2.1 多级存储模型

微服务框架 【SpringCloudRabbitMQDockerRedis搜索分布式&#xff0c;系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 微服务面试篇 文章目录微服务框架微服务面试篇54 微服务篇54.2 Nacos的服务注册表结构是怎样的&#xff1f;54.2.1 多级存储模型54 微服务篇…

《Redis实战篇》四、分布式锁

文章目录4.1 基本原理和实现方式对比4.2 Redis分布式锁的实现核心思路4.3 实现分布式锁版本一4.4 Redis分布式锁误删情况说明4.5 解决Redis分布式锁误删问题4.6 分布式锁的原子性问题4.7 Lua脚本解决多条命令原子性问题4.8 利用Java代码调用Lua脚本改造分布式锁4.1 基本原理和实…

Oracle时间函数

Oracle 时间函数INTERVAL间隔一年间隔一天间隔一小时间隔一分钟NUMTODSINTERVAL间隔一天间隔一小时间隔一分钟MyBatis xml 中计算时间间隔需要处理的问题INTERVAL 函数整合到 MyBatis$ 符号拼接 sql 源码追踪NUMTODSINTERVAL 函数整合到 MyBatisOracle 时间间隔函数有INTERVAL、…