普通
比如说是conda的DL环境,路径是D:\Miniconda3\envs\DL
VC++目录->包含目录里加入D:\Miniconda3\envs\DL\include
VC++目录->库目录里加入D:\Miniconda3\envs\DL\libs
链接器->输入->附加依赖项里加入D:\Miniconda3\envs\DL\libs\python37.lib
在libs底下,将python37.lib复制一份改成python37_d.lib
将python37.dll复制到exe所在路径里
python37.dll一般跟python在一块
exe一般在cpp的上一级的x64里,如果需要debug,就复制到debug里,如果哟啊release,就复制到release里
创建一个python_script
python_script/main.py
#!/usr/bin/env python
# _*_ coding:utf-8 _*_
import os
def func():
print('hello world')
if __name__ == '__main__':
func()
main.cpp
Py_SetPythonHome里是python路径
sys.path.append(‘python_script’)是用来找python文件的
#include <Python.h>
#include <iostream>
#include <string>
int main() {
Py_SetPythonHome(L"D:\\Miniconda3\\envs\\DL");
Py_Initialize();
if (0 == Py_IsInitialized()) {
std::cout << "python init fail" << std::endl;
return -1;
}
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append('python_script')");
//相当于import
PyObject* pModule = PyImport_ImportModule("main");
if (NULL == pModule) {
std::cout << "module not found" << std::endl;
return -1;
}
PyObject* pFunc = PyObject_GetAttrString(pModule, "func");
if (NULL == pFunc || 0 == PyCallable_Check(pFunc)) {
std::cout << "not found function func" << std::endl;
return -1;
}
PyObject_CallObject(pFunc, NULL);
Py_Finalize();
return 0;
}
opencv+numpy+pytorch
我这里,只成功了release模式,debug模式搞不定
然后imgaug这个库也加载不了= =
main.cpp
load_model
加载模型
get_predict_xy
用C++的opencv读图片,转numpy传入python
python再用pytorch预测,返回一个numpy
simple_test
用C++的opencv读图片,转numpy传入python
python直接传回来给C++,转opencv
顺带提一下,import_array()一定要写
#include <Python.h>
#include <iostream>
#include <string>
#include <numpy/arrayobject.h>
#include <opencv2/opencv.hpp>
size_t init_numpy() {
import_array();
return 1;
}
void load_model(PyObject* pModule, const std::string& model_path) {
PyObject* init_model = PyObject_GetAttrString(pModule, "init_model");
if (NULL == init_model || 0 == PyCallable_Check(init_model)) {
std::cout << "not found function init_model" << std::endl;
exit(-1);
}
PyObject* pArgs = PyTuple_New(1);
PyTuple_SetItem(pArgs, 0, Py_BuildValue("s", model_path.c_str()));
PyObject* result = PyObject_CallObject(init_model, pArgs);
if (NULL == result) {
std::cout << "init_model failed" << std::endl;
exit(-1);
}
int return_value = -1;
PyArg_Parse(result, "i", &return_value);
std::cout << "returned " << return_value << std::endl;
}
void get_predict_xy(PyObject* pModule, const std::string& img_path) {
cv::Mat img = cv::imread(img_path, 0);
PyObject* predict = PyObject_GetAttrString(pModule, "get_predict_xy");
if (NULL == predict || 0 == PyCallable_Check(predict)) {
std::cout << "not found function get_predict_xy" << std::endl;
exit(-1);
}
npy_intp dims[] = { img.rows, img.cols };
PyObject* pValue = PyArray_SimpleNewFromData(2, dims, NPY_UINT8, img.data);
PyObject* pArgs = PyTuple_New(1);
// PyTuple_SetItem(pArgs, 0, Py_BuildValue("s", img_path.c_str()));
PyTuple_SetItem(pArgs, 0, pValue);
PyObject* result = PyEval_CallObject(predict, pArgs);
if (NULL == result) {
std::cout << "get_predict_xy failed" << std::endl;
exit(-1);
}
if (!PyArray_Check(result)) {//None
std::cout << "didn't return numpy" << std::endl;
exit(-1);
}
PyArrayObject* ret_array;
PyArray_OutputConverter(result, &ret_array);
if (2 != PyArray_NDIM(ret_array)) {
exit(-1);
}
npy_intp* shape = PyArray_SHAPE(ret_array);
int n = shape[0];
int m = shape[1];
cv::Mat return_key_points(n, m, CV_32F, PyArray_DATA(ret_array));
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
int* cur = reinterpret_cast<int*>(PyArray_GETPTR2(ret_array, i, j));
std::cout << *cur << ' ';
}
std::cout << std::endl;
}
//PyArray_GETPTR2
}
void simple_test(PyObject* pModule, const std::string& img_path) {
cv::Mat img = cv::imread(img_path, 0);
PyObject* predict = PyObject_GetAttrString(pModule, "simple_test");
if (NULL == predict || 0 == PyCallable_Check(predict)) {
std::cout << "not found function simple_test" << std::endl;
exit(-1);
}
npy_intp dims[] = { img.rows, img.cols };
PyObject* pValue = PyArray_SimpleNewFromData(2, dims, NPY_UINT8, img.data);
PyObject* pArgs = PyTuple_New(1);
// PyTuple_SetItem(pArgs, 0, Py_BuildValue("s", img_path.c_str()));
PyTuple_SetItem(pArgs, 0, pValue);
PyObject* result = PyEval_CallObject(predict, pArgs);
if (NULL == result) {
std::cout << "simple_test failed" << std::endl;
exit(-1);
}
if (!PyArray_Check(result)) {//None
std::cout << "didn't return numpy" << std::endl;
exit(-1);
}
PyArrayObject* ret_array;
PyArray_OutputConverter(result, &ret_array);
if (2 != PyArray_NDIM(ret_array)) {
exit(-1);
}
npy_intp* shape = PyArray_SHAPE(ret_array);
int n = shape[0];
int m = shape[1];
cv::Mat return_img(n, m, CV_8UC1, PyArray_DATA(ret_array));
// cv::imshow("test", return_img);
// cv::waitKey(0);
// cv::destroyAllWindows();
for (int i = 0; i < n; ++i) {
uchar* data1 = img.ptr<uchar>(i);
uchar* data2 = return_img.ptr<uchar>(i);
for (int j = 0; j < m; ++j) {
if (data1[j] != data2[j]) {
std::cout << "not equal" << std::endl;
return;
}
}
}
std::cout << "equal" << std::endl;
}
int main() {
Py_SetPythonHome(L"D:\\Miniconda3\\envs\\DL");
Py_Initialize();
if (0 == Py_IsInitialized()) {
std::cout << "python init fail" << std::endl;
return -1;
}
PyRun_SimpleString("import sys");
PyRun_SimpleString("import os");
PyRun_SimpleString("print(os.path.abspath('./python_script'))");
PyRun_SimpleString("sys.path.append('./python_script')");
init_numpy();
PyObject* pModule = PyImport_ImportModule("predict");
if (NULL == pModule) {
std::cout << "module not found" << std::endl;
return -1;
}
simple_test(pModule, "python_script\\001.bmp");
load_model(pModule, "python_script\\best.pth");
get_predict_xy(pModule, "python_script\\001.bmp");
get_predict_xy(pModule, "python_script\\001.bmp");
Py_Finalize();
return 0;
}
predict.py
UNet我没放出来
#!/usr/bin/env python
# _*_ coding:utf-8 _*_
import os
import numpy as np
from model.u2net import UNet
import torch
from cv2 import cv2
import imgaug.augmenters as iaa
model = UNet(in_channels=1, out_channels=19)
device = torch.device('cuda:0')
augmentation = iaa.Sequential([
iaa.Resize({"width": 416, "height": 512})
])
def init_model(path):
global model, device
if not os.path.exists(path):
print(f'not found {os.path.abspath(path)}')
return -1
model_state_dict = torch.load(path)
model.load_state_dict(model_state_dict)
model = model.to(device)
return 0
def get_img_aug(img):
global augmentation
print('----get_img_aug------')
print(img.shape)
print('------------------')
# img = cv2.imread(path, 0) # 2490*1935
img_aug = augmentation(image=img)
img_aug = (img_aug - img_aug.min()) / (img_aug.max() - img_aug.min())
img_aug = torch.FloatTensor(img_aug).unsqueeze(0).unsqueeze(0) # torch.Size([1, 1, 512, 416])
return img_aug
def get_heatmap_coordination_batch_numpy(heatmap):
"""
get heatmap coordination by batch
:param heatmap: (B,C,H,W) or (B,C,H,W,D) (C is the num of landmark)
:return: coordination (B,C,2) or (B,C,3)
"""
origin_shape = heatmap.shape
heatmap = heatmap.reshape(*origin_shape[:2], -1)
temp = np.argmax(heatmap, axis=-1)[..., np.newaxis]
# unravel_index
out = []
for dim in reversed(origin_shape[2:]):
out.append(temp % dim)
temp = np.floor_divide(temp, dim)
out = np.concatenate(out[::-1], axis=-1)
return out
def get_predict_xy(img):
global model
# if not os.path.exists(path):
# return None
img = get_img_aug(img).to(device)# 1 * 1 * 512 * 416
output = model(img)['output'].to('cpu').detach().numpy() # 1 * 1 * 19 * 2
predict_xy = get_heatmap_coordination_batch_numpy(output).squeeze(0) # 19 * 2
print(predict_xy)
return predict_xy
def simple_test(img):
return img
if __name__ == '__main__':
path = '/mnt/data/datasets/landmark/ISBI2015_ceph/raw/001.bmp'
init_model('best.pth')
print('finish_init')
print(get_predict_xy(path).shape)
print(get_predict_xy(path).dtype)
https://zhuanlan.zhihu.com/p/377640206