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

这篇具有很好参考价值的文章主要介绍了QT调用python传递图像和二维数组,并接受python返回值(图像)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

任务目的:

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

实现过程

1.新建QT项目

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

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

2.配置项目环境

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

然后点击下一步,随后选择完成即可。
QT调用python传递图像和二维数组,并接受python返回值(图像)

(3)配置numpy环境

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

选择numpu库里面的npymath.lib即可,而且这次的包含目录不用自己选择,选择好库文件之后,包含路径正好就是numpy目录的include目录,如果不是的话自己修改一下即可。
QT调用python传递图像和二维数组,并接受python返回值(图像)
QT调用python传递图像和二维数组,并接受python返回值(图像)
QT调用python传递图像和二维数组,并接受python返回值(图像)
至此,环境配置完毕,运行一下,看没有报错吧
此时的项目文件增加了很多库目录的配置代码,如下
QT调用python传递图像和二维数组,并接受python返回值(图像)
按照下面的步骤依次选择编译器运行,可以下是否报错,没报错就说明成功了,没什么大问题,但是不保证
QT调用python传递图像和二维数组,并接受python返回值(图像)

(4)运行代码

python文件一定要放置在运行目录下面,也就是func.py
QT调用python传递图像和二维数组,并接受python返回值(图像)
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");
    PyObject *pFunc_1 = PyObject_GetAttrString(m_pyObj, "myfunc1");
    /*
     * 简单调用测试,测试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, CArrays);
    // 创建一个大小为1的元组对象
    PyObject *ArgArray_array = PyTuple_New(1);
    // 设置Tuple的某一个元素,参数为索引index和要传入的PyObject对象
    PyTuple_SetItem(ArgArray_array, 0, PyArray_array);
    // 调用函数,传入Numpy Array 对象。
    PyObject_CallObject(pFunc_1, 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();
}

然后就是愉快的运行程序了,不出意外的话结果如下
QT调用python传递图像和二维数组,并接受python返回值(图像)
上图中1标记,表示的是QT接收的python的返回结果,打印的是图像的像素矩阵,标识2,是python代码运行时的窗口,显示的是一幅图像。

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

上图1是python程序的打印结果,1标记是图像部分,2标记是QT传递二维数据,python打印结果。部分代码已经做了二次修正,结果都是正确没问题的。

整个项目包括运行目录的程序包组合可以在下面的链接进行获取。
https://download.csdn.net/download/weixin_43552197/87360247文章来源地址https://www.toymoban.com/news/detail-488550.html

到了这里,关于QT调用python传递图像和二维数组,并接受python返回值(图像)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Java基础教程】(八)面向对象篇 · 第二讲:Java 数组全面解析——动态与静态初始化、二维数组、方法参数传递、排序与转置、对象数组、操作API~

    掌握数组的动态及静态创建方式、使用及特征; 掌握引用类型数据的特征; 掌握数组的排序、转置操作; 数组可以将多个变量进行统一的命名,这样相同类型的元素就可以按照一定的顺序进行组合排列 。在 Java中,数组属于引用类型数据,所以在数组的操作过程中,也一定

    2024年02月13日
    浏览(50)
  • 【算法训练-数组 三】【数组矩阵】螺旋矩阵、旋转图像、搜索二维矩阵

    废话不多说,喊一句号子鼓励自己:程序员永不失业,程序员走向架构!本篇Blog的主题是螺旋矩阵,使用【二维数组】这个基本的数据结构来实现 二维数组的结构特性入手 根据题目示例 matrix = [[1,2,3],[4,5,6],[7,8,9]] 的对应输出 [1,2,3,6,9,8,7,4,5] 可以发现,顺时针打印矩阵的顺序

    2024年02月06日
    浏览(51)
  • QT调用百度地图并返回点击地的经纬度

    最近需要使用百度地图,并返回某个点的经纬度值。网上基本都是根据经纬度定位,而没有获取经纬度的。自己用QT简单实现了下。 这块耗时最久。因为之前QT默认的MinGW 64bit无法编译,需要安装MSVC2017(注意:安装Visual Studio 2017,最开始安装2022也不行)。安装过程,自行百度。

    2024年02月07日
    浏览(36)
  • QT调用不同UI界面响应,对话框跳转到主页面UI,用信号与槽传递信息,两级信号传递

    在MainWindow界面有一个按键”新建”,点击后需要生成一个输入对话框,实例用到了processDialog类对象。 我新建一行数据完成后,需要更新MainWindow表格的视图,此时就需要调用写在MainWIndow下的函数MainWindow::showProcess(vectorPCB* readyQueue) 但是如果实例化一个MainWidow对象,此时修改的

    2024年02月12日
    浏览(52)
  • 【Python】函数进阶 ① ( 函数返回多个返回值 | 函数参数传递类型简介 | 位置参数 | 关键字参数 )

    在函数中 , 如果要 返回 多个返回值 , 可以 在 return 语句中 , 设置多个返回值 , 这些返回值之间使用 逗号 隔开 , 这些返回值的类型是 元组 tuple 类型的 ; 在下面的代码中 , 返回了 3 个返回值 , 其 本质上是返回了一个包含 3 个元素的 元组 数据容器 , 可以使用多重赋值将返回的

    2024年02月11日
    浏览(54)
  • Python 创建二维数组

    一. 创建二维数组遇到的问题 List (列表)是 Python 中最基本的数据结构。在用法上,它有点类似数组,因为每个列表都有一个下标,下标从 0 开始。因此,我们可以使用 list[1] 来获取下标对应的值。如果我们深入下列表的底层原理,会发现列表是基于 PyListObject 实现的。PyL

    2024年02月09日
    浏览(44)
  • Python调用腾讯云函数传递json数据

    前言   有些时候有一些公共的方法,需要放在服务器上,在不同的电脑上使用。但是我们有没有自己的服务器,所以考虑将公共的方法放在腾讯云、华为云、阿里云、百度云等云平台上,方便在不同的电脑上复用。   我们这里使用的是腾讯云,并且函数的编程语言使用

    2024年02月06日
    浏览(38)
  • python:使用RESTful API(flask)调用python程序传递参数,实现Web端调用python程序

    现有一个用python写的程序(或者是一个或几个的函数接口),需要在Web前端调用python写的函数。如果直接用前端java来调用会很不方便,而且会出现各种麻烦的问题,下面给出如何在web前端调用python的接口。 使用python的RESTful API库将python写的函数封装为Web端可调用的接口,在

    2024年01月20日
    浏览(40)
  • chatgpt赋能python:Python如何创建二维数组

    在Python编程中,经常需要使用到二维数组,它是一个由多个一维数组组成的数组。本篇文章将介绍Python如何创建二维数组,包括几种常用方法。 可以使用list和for循环来创建二维数组。代码如下:

    2024年02月11日
    浏览(47)
  • Python 将二维数组或矩阵变为三维

    之前,我们已经介绍过了 Python 将一维数组或矩阵变为三维。然而,很多时候,我们也需要对二维矩阵进行操作,这里特来介绍一下如何将二维矩阵扩展为三维。 阅读这一篇前推荐优先阅读 np.concatenate()函数。 采用 reshape 方法我们依然可以做到这一点。 reshape 方法扩展数组或

    2024年02月19日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包