C++调用Python脚本函数

文章目录

  • C++调用Python脚本函数
    • 1、编写python脚本,并下载安装所需的库文件(保证编写的python脚本在指定的虚拟环境下可以正常运行)
    • 2、在Vs2017中配置python运行环境
    • 3、代码编写(C++调用Python流程)

1、编写python脚本,并下载安装所需的库文件(保证编写的python脚本在指定的虚拟环境下可以正常运行)

我这边在做项目的时候需要使用C++调用低照度图像增强的python程序,以下是我这边测试时使用的代码。

# coding:utf-8
from datetime import datetime
import numpy as np
import cv2
from math import ceil
from scipy.sparse import spdiags
from scipy.misc import imresize
from scipy.optimize import fminbound
from scipy.stats import entropy
from scipy.sparse.linalg import spsolveimagePath = ""def computeTextureWeights(fin, sigma, sharpness):# print(fin)# fin = fin / 255.0dt0_v = np.diff(fin, 1, 0)  # 垂直差分dt0_v = np.concatenate((dt0_v, fin[:1, :] - fin[-1:, :]), axis=0)  # 第0行减去最后一行dt0_h = np.diff(fin, 1, 1)  # 水平差分dt0_h = np.concatenate((dt0_h, fin[:, :1] - fin[:, -1:]), axis=1)  # 第0列减去最后一列gauker_h = cv2.filter2D(dt0_h, -1, np.ones((1, sigma)), borderType=cv2.BORDER_CONSTANT)gauker_v = cv2.filter2D(dt0_v, -1, np.ones((sigma, 1)), borderType=cv2.BORDER_CONSTANT)# cv2这个filter2D(镜像翻转)与MATLAB的filter2(补0)不同W_h = 1.0 / (abs(gauker_h) * abs(dt0_h) + sharpness)W_v = 1.0 / (abs(gauker_v) * abs(dt0_v) + sharpness)return W_h, W_vdef convertCol(tmp):  # 按照列转成列。[[1, 2, 3], [4, 5, 6], [7, 8, 9]] # 转成[147258369].T(竖着)return np.reshape(tmp.T, (tmp.shape[0] * tmp.shape[1], 1))def solveLinearEquation(IN, wx, wy, lambd):# print('IN', IN.shape)r, c, ch = IN.shape[0], IN.shape[1], 1k = r * cdx = -lambd * convertCol(wx)  # 按列转成一列dy = -lambd * convertCol(wy)tempx = np.concatenate((wx[:, -1:], wx[:, 0:-1]), 1)  # 最后一列插入到第一列前面tempy = np.concatenate((wy[-1:, :], wy[0:-1, :]), 0)  # 最后一行插入到第一行前面dxa = -lambd * convertCol(tempx)dya = -lambd * convertCol(tempy)tempx = np.concatenate((wx[:, -1:], np.zeros((r, c - 1))), 1)  # 取wx最后一列放在第一列,其他为0tempy = np.concatenate((wy[-1:, :], np.zeros((r - 1, c))), 0)  # 取wy最后一行放在第一行,其他为0dxd1 = -lambd * convertCol(tempx)dyd1 = -lambd * convertCol(tempy)wx[:, -1:] = 0  # 最后一列置为0wy[-1:, :] = 0  # 最后一行置为0dxd2 = -lambd * convertCol(wx)dyd2 = -lambd * convertCol(wy)Ax = spdiags(np.concatenate((dxd1, dxd2), 1).T, np.array([-k + r, -r]), k, k)Ay = spdiags(np.concatenate((dyd1, dyd2), 1).T, np.array([-r + 1, -1]), k, k)# spdiags,与MATLAB不同,scipy是根据行来构造sp,而matlab是根据列来构造spD = 1 - (dx + dy + dxa + dya)A = (Ax + Ay) + (Ax + Ay).T + spdiags(D.T, np.array([0]), k, k)A = A / 1000.0  # 需修改matCol = convertCol(IN)# print('spsolve开始', str(datetime.now()))OUT = spsolve(A, matCol, permc_spec="MMD_AT_PLUS_A")# print('spsolve结束', str(datetime.now()))OUT = OUT / 1000OUT = np.reshape(OUT, (c, r)).Treturn OUTdef tsmooth(I, lambd=0.5, sigma=5, sharpness=0.001):# print(I.shape)wx, wy = computeTextureWeights(I, sigma, sharpness)S = solveLinearEquation(I, wx, wy, lambd)return Sdef rgb2gm(I):# print('I', I.shape)# I = np.maximum(I, 0.0)if I.shape[2] and I.shape[2] == 3:I = np.power(np.multiply(np.multiply(I[:, :, 0], I[:, :, 1]), I[:, :, 2]), (1.0 / 3))return Idef YisBad(Y, isBad):  # 此处需要修改得更高效return Y[isBad >= 1]# Z = []# [rows, cols] = Y.shape# for i in range(rows):#     for j in range(cols):#         if isBad[i, j] >= 122:#             Z.append(Y[i, j])# return np.array([Z]).Tdef applyK(I, k, a=-0.3293, b=1.1258):# print(type(I))if not type(I) == 'numpy.ndarray':I = np.array(I)# print(type(I))beta = np.exp((1 - (k ** a)) * b)gamma = (k ** a)BTF = np.power(I, gamma) * beta# try:#    BTF = (I ** gamma) * beta# except:#    print('gamma:', gamma, '---beta:', beta)#    BTF = Ireturn BTFdef maxEntropyEnhance(I, isBad, mink=1, maxk=10):# Y = rgb2gm(np.real(np.maximum(imresize(I, (50, 50), interp='bicubic') / 255.0, 0)))Y = imresize(I, (50, 50), interp='bicubic') / 255.0Y = rgb2gm(Y)# bicubic较为接近# Y = rgb2gm(np.real(np.maximum(cv2.resize(I, (50, 50), interpolation=cv2.INTER_LANCZOS4  ), 0)))# INTER_AREA 较为接近# import matplotlib.pyplot as plt# plt.imshow(Y, cmap='gray');plt.show()# print('isBad', isBad.shape)isBad = imresize(isBad.astype(int), (50, 50), interp='nearest')# print('isBad', isBad.shape)# plt.imshow(isBad, cmap='gray');plt.show()# 取出isBad为真的Y的值,形成一个列向量Y# Y = YisBad(Y, isBad)  # 此处需要修改得更高效Y = Y[isBad >= 1]# Y = sorted(Y)# print('-entropy(Y)', -entropy(Y))def f(k):return -entropy(applyK(Y, k))# opt_k = mink# k = mink# minF = f(k)# while k<= maxk:#     k+=0.0001#     if f(k)<minF:#         minF = f(k)#         opt_k = kopt_k = fminbound(f, mink, maxk)# print('opt_k:', opt_k)# opt_k = 5.363584# opt_k = 0.499993757705# optk有问题,fminbound正确,f正确,推测Y不一样导致不对# print('opt_k:', opt_k)J = applyK(I, opt_k) - 0.01return Jdef HDR2dark(I, t_our, W):  # 过亮的地方变暗W = 1 - WI3 = I * WisBad = t_our > 0.8J3 = maxEntropyEnhance(I, isBad, 0.1, 0.5)  # 求k和曝光图J3 = J3 * (1 - W)  # 曝光图*权重fused = I3 + J3  # 增强图return Idef oneHDR(I, mu=0.5, a=-0.3293, b=1.1258):# mu照度图T的指数,数值越大,增强程度越大I = I / 255.0t_b = I[:, :, 0]  # t_b表示三通道图转成灰度图(灰度值为RGB中的最大值),亮度矩阵Lfor i in range(I.shape[2] - 1):  # 防止输入图片非三通道t_b = np.maximum(t_b, I[:, :, i + 1])# t_b2 = cv2.resize(t_b, (0, 0), fx=0.5, fy=0.5)# print('t_b', t_b.shape)# t_b2 = misc.imresize(t_b, (ceil(t_b.shape[0] / 2), ceil(t_b.shape[1] / 2)),interp='bicubic')# print('t_b2', t_b2.shape)# t_b2 = t_b / 255.0t_b2 = imresize(t_b, (256, 256), interp='bicubic', mode='F')  # / 255t_our = tsmooth(t_b2)  # 求解照度图T(灰度图)# print('t_our前', t_our.shape)t_our = imresize(t_our, t_b.shape, interp='bicubic', mode='F')  # / 255# print('t_our后', t_our.shape)# W: Weight Matrix 与 I2# 照度图L(灰度图) ->  照度图L(RGB图):灰度值重复3次赋给RGB# size为(I, 3) , 防止与原图尺寸有偏差t = np.ndarray(I.shape)for ii in range(I.shape[2]):t[:, :, ii] = t_our# print('t', t.shape)W = t ** mu  # 原图的权重。三维矩阵# cv2.imwrite(filepath + 'W.jpg', W * 255)# cv2.imwrite(filepath + '1-W.jpg', (1 - W) * 255)# cv2.imwrite(filepath + 't.jpg', t * 255)# cv2.imwrite(filepath + '1-t.jpg', (1 - t) * 255)# print('W', W.shape)# 变暗# isBad = t_our > 0.8  # 是高光照的像素点# I = maxEntropyEnhance(I, isBad)  # 求k和曝光图# 变暗I2 = I * W  # 原图*权重# 曝光率->k ->JisBad = t_our < 0.5  # 是低光照的像素点J = maxEntropyEnhance(I, isBad)  # 求k和曝光图J2 = J * (1 - W)  # 曝光图*权重fused = I2 + J2  # 增强图# 存储中间结果# cv2.imwrite(filepath + 'I2.jpg', I2 * 255.0)# cv2.imwrite(filepath + 'J2.jpg', J2 * 255.0)# 变暗# fused = HDR2dark(fused, t_our, W)return fused# return resdef test(imagePath):print('程序开始', str(datetime.now()))filepath = imagePath inputImg = cv2.imread(filepath + 'Grey.jpg')outputImg = oneHDR(inputImg)# outputImg = outputImg * 255.0cv2.imwrite(filepath + '1out.jpg', outputImg * 255)# print("HDR完成,已保存到本地")print('程序结束', str(datetime.now()))# cv2.imshow('inputImg', inputImg)# cv2.imshow('outputImg', outputImg)# print(inputImg.dtype,outputImg.dtype)# outputImg = outputImg.astype(int)# print(inputImg.dtype, outputImg.dtype)# compare = np.concatenate((inputImg,outputImg),axis=1)# cv2.imshow('compare', compare)# cv2.waitKey(0)# cv2.destroyAllWindows()flag = 1return flagif __name__ == '__main__':# print('程序开始', str(datetime.now()))test('C:/Users/Administrator/Desktop/image/')

代码来源:https://zhuanlan.zhihu.com/p/84450561
        需要的python环境:python3、numpy、opencv-pyhon、scipy,对应版本可参考如下:


        强烈推荐:使用豆瓣镜像安装python库文件(可解决下载慢,超时下载异常)

pip install (库文件名称) -i https://pypi.doubanio.com/simple

2、在Vs2017中配置python运行环境

在Vs2017中配置python运行环境其实跟就配置Opencv运行环境类似,需要将Python安装路径下的include、libs和该路径下相关的Dll配置到Vs项目上即可。具体如下:

1、打开python环境安装路径(如下图),获取include文件夹的路径信息,并将该路径信息复制到Vs项目->点击右键属性->VC++目录->包含目录下方。


    2、在当前项目工程下创建两个文件夹DLLs、libs(如下图1)。在python环境安装路径下的libs中找到python36.lib(如下图2),将其复制到新创建的libs文件夹中,且需将其再复制一份并重命名为python36_d.lib,同时放置在该libs文件夹下(如下图3);同理,在python环境安装路径下找到python36.dll(如下图4),将其复制到新创建的DLLs文件夹中,在将其再复制一份并重命名为python36_d.dll,放置在该DLLs文件夹下(如下图5)。






    3、点击项目右键属性->调试->环境下添加:
    PATH=$(SolutionDir)C++调用Python接口实现图像增强\DLLs;%PATH%(添加DLl路径信息)

点击项目右键属性->VC++ 目录->库目录下添加:
    $(SolutionDir)C++调用Python接口实现图像增强\libs(添加libs路径信息)

点击项目右键属性->链接器->输入->附加依赖项下添加:
    python36_d.lib、python36.lib

3、代码编写(C++调用Python流程)

C++调用Python流程如下:
        1、首先需要包含头文件 <Python.h>
        2、初始化Python环境 Py_Initialize()
        3、添加脚本路径 PyRun_SimpleString()
        4、导入模块 PyImport_ImportModule()
        5、导入函数 PyObject_GetAttrString()
        6、导入参数 Py_BuildValue()、PyEval_CallObject()
        7、获取返回值 PyArg_Parse()
        8、结束释放 Py_Finalize()

代码如下:

#include <iostream>
#include <Python.h>int main()
{wchar_t wt[] = L"E:\\Anaconda2\\envs\\python3\\envs\\enhance";Py_SetPythonHome(wt);//初始化Python环境Py_Initialize();//添加模块路径PyRun_SimpleString("import sys");//当前目录下PyRun_SimpleString("sys.path.append('./')");//导入模块PyObject *pModule = PyImport_ImportModule("enhance");if (!pModule){std::cout << "Python模块导入失败" << std::endl;return 0;}std::cout << "Python模块导入成功" << std::endl;//导入函数PyObject *pFun = PyObject_GetAttrString(pModule, "test");if (!pFun){std::cout << "Python函数导入失败" << std::endl;return 0;}std::cout << "Python函数导入成功" << std::endl;//导入参数PyObject *args = Py_BuildValue("(s)", "C:/Users/Administrator/Desktop/image/");PyObject *pArg = PyEval_CallObject(pFun, args);  //PyObject_CallObject(pFun, args)都行if (!pArg){std::cout << "Python函数参数导入失败" << std::endl;return 0;}std::cout << "Python函数参数导入成功" << std::endl;//获取函数返回值int res = 0;PyArg_Parse(pArg, "i", &res);std::cout << res << std::endl;//结束释放Py_Finalize();return 1;
}

在此、说一下我在编写程序的过程中遇到的问题:

1、初始化Python环境 Py_Initialize()时,运行程序报错(如下图):原因是因为电脑上存在多个虚拟环境,要指定到所需的虚拟环境路径才行。因此要在初始化之前加上Py_SetPythonHome(wt),wt为指定虚拟环境的路径信息。


        2、在导入模块 PyImport_ImportModule()时,总是返回Null:原因是因为PyRun_SimpleString(“sys.path.append(’./’)”);该语句指定Python脚本应位与当前项目工程下,而我的Python脚本放置在桌面上,导致无法加载成功。需将Python脚本放置在当前项目工程下,或将sys.path.append()中的路径改为桌面路径即可。我这边直接将Python脚本放在当前工程下,已解决。


        3、在导入参数Py_BuildValue()时,参考如下列表导入参数(暂时就知道这么多,往后用到了新的我会及时更新):

命令 实际输入
Py_BuildValue("") None
Py_BuildValue("(i)", 123) 123
Py_BuildValue("(i,i)", 123, 456) (123, 456)
Py_BuildValue(“(s)”, “hello”) ‘hello’

效果展示:

C++调用Python脚本函数相关推荐

  1. C语言调用Python脚本

    目录 一.头文件 二.使用步骤 1.初始化python模块 2.设置python的搜索路径 3.导入python脚本 4.导入调用的方法 5.构建参数 6.调用方法 7.解析返回值 8.释放资源 三. ...

  2. Java调用python脚本

    Java调用python脚本 最近也是刚开始学python,所以这里写了一个简单的小方法用Java来调用python脚本.后期再进行更新. 1.Java启动程序的方法 在Java中提供了两种方法来启动 ...

  3. 【Python】如何在Excel中调用Python脚本,实现数据自动化处理

    这次我们会介绍如何使用xlwings将Python和Excel两大数据工具进行集成,更便捷地处理日常工作. 说起Excel,那绝对是数据处理领域王者般的存在,尽管已经诞生三十多年了,现在全球仍有7.5 ...

  4. java 调用python脚本过程_通过Java调用Python脚本

    在进行开发的过程中,偶尔会遇到需要使用Java调用Python脚本的时候,毕竟Python在诸如爬虫,以及科学计算等方面具有天然的优势.最近在工作中遇到需要在Java程序中调用已经写好的Python程 ...

  5. python 调用控制台并获取返回结果_Java调用Python脚本并获取返回值

    在Java程序中有时需要调用Python的程序,这时可以使用一般的PyFunction来调用python的函数并获得返回值,但是采用这种方法有可能出现一些莫名其妙的错误,比如ImportError.在 ...

  6. python脚本编程实例_C程序调用Python脚本的例子

    下面我们一起来看看关于C程序调用Python脚本的例子,如果你对此有兴趣的希望此教程对各位同学会有所帮助. 代码如下 复制代码 #include int main(){ PyObject * g_pM ...

  7. java执行python返回null_[转]java调用python脚本以及通过Process.waitFor()直接调用python模块返回错误代码1的一种解决办法...

    常见的java调用python脚本方式 通过jython提供的类库实现 通过Runtime.getRuntime()开启进程来执行脚本文件 通过jython提供的类库实现 通过jython实现的话,我 ...

  8. C++ QT调用python脚本并将软件打包发布

    对我来说主要就是打包的问题比较难解决,弄了一个下午都没解决,不知道是minconda的问题,还是Qt更新的原因,网上的很多解决方法都不行,经过我的一项一项排查,最后发现就是少导了一个文件夹. 怎么调用 ...

  9. 如何在Excel中调用Python脚本,实现数据自动化处理!

    大家好, 这次我们会介绍如何使用xlwings将Python和Excel两大数据工具进行集成,更便捷地处理日常工作. 说起Excel,那绝对是数据处理领域王者般的存在,尽管已经诞生三十多年了,现在全球 ...

最新文章

  1. 博科b8网络版定位服务器位置,如何在企业服务器中采集奥维GPS定位设备的位置...
  2. 图解排序算法(四)之归并排序
  3. dup和dup2的使用方法
  4. 网络编程之 keepalive(zz)
  5. Python中函数式编程的学习感想~
  6. 影视光盘制作专家 6.3简体中文免费版
  7. Redis教程:主从复制
  8. wifi协议_图解 802.11wifi协议
  9. 金融行业数据仓库分层
  10. 从python爬虫以及数据可视化的角度来为大家呈现“227事件”后,肖战粉丝的数据图
  11. 涨跌的例题用C语言编辑,涨跌比率指标用法及源代码(ADR)
  12. 史玉柱给创业者的五条建议
  13. 小霸王其乐无穷~FC红白机游戏600合集(支持mac 12.x系统)
  14. 实现内网(局域网)控制所有电脑一键关机并且系统还原的方案
  15. 运维GO-2021年书单-产品运营 篇
  16. android 常用机型尺寸_Android中图片大小与各种hdpi
  17. L3级自动驾驶接管实验测试平台及其应用研究
  18. <<计算机操作系统(慕课版)>>第五章参考答案
  19. Facebook要“变脸”,网友乐了:你这不就是抄微信嘛
  20. 腾讯云服务器香港机房速度怎么样? – PING速度/路由跟踪和下载速度真实评测

热门文章

  1. debug assertion failed是什么意思?_如何使用 pdb 来性感 debug 你的 Python 代码?
  2. 数据分析 超市条码_郑州科脉助力和美超市店面软件升级智赢
  3. 对计算机上的浏览器的介绍,挖掘IE浏览器的潜在功能(一) -电脑资料
  4. 计算机管理游戏,网吧游戏管理系统
  5. 电脑常见问题_电脑常见问题解决方法(二)
  6. java输入输出及文件_(java基础)Java输入输出流及文件相关
  7. 华兴数控g71外圆循环编程_数控车床加工时的复合循环指令G70,G71,G72,G73
  8. flask get 参数_Python web 用它5分钟以后,我放弃用了四年的 Flask
  9. spring boot: 支持jsp,支持freemarker
  10. linux安装nord,卸载nord源