文章目录
- 一、前言
- 二、配置过程
- 2.1.CMake与ITK的配置
- 2.2.改写ITK的生成drr代码
- 2.3.编译代码
- 2.4.python调用cpp
- 三、总结
- 四、参考博客
一、前言
最近在做配准,需要用ITK来生成数据,windows版本可以通过cmake与visual studio可以跑通生成。但是想要在linux上跑通,所以重新到linux来配置ITK的环境。同时想要使用python来调用生成drr的代码,方便后面批量生成数据以及标注数据。本文主要是写的是如何使用python通过cmakelist来生成.so动态库,主要利用的是python的ctypes。
需要准备的:
1)在linux安装好cmake;
2)在linux安装好ITK;
3)有生成drr的生成代码;(我使用的是这位博主提供的代码:win10+visual studio 2022+itk+生成drr)
4)我的环境是:ubuntu20.04 + vscode + cmake3.26.4 + ccmake3.26.4 + ITK5.2.1
二、配置过程
2.1.CMake与ITK的配置
这里因为我是按照这位博主走通的这个过程:ITK的安装与测试(Ubuntu系统),注意作者有一步漏了,这点在评论里面有提到:”make以后需要sudo make install“,如果少了这步会报错。
2.2.改写ITK的生成drr代码
跑通上面的过程后,因为我们需要使用ctypes来调用c++代码,这需要我们将代码改编为一个函数,来方便在python里面传参。
这里主要是将代码改写为一个函数了,以下是我改的开头,其他部分没有改动,加了一个extern " c"是为了让它按C语言的方式来编译:
extern "C"{
int Generate_drr(float rx_value, float ry_value, float rz_value,
float tx_value, float ty_value, float tz_value,
float cx_value, float cy_value, float cz_value,
float sid_value,
float sx_value, float sy_value,
int dx_value, int dy_value,
float o2Dx_value, float o2Dy_value,
double threshold_value,
const char* ct_file_path,
const char* drr_save_path
) {
float rx = rx_value;
float ry = ry_value;
float rz = rz_value;
float tx = tx_value;
float ty = ty_value;
float tz = tz_value;
float cx = cx_value;
float cy = cy_value;
float cz = cz_value;
float sid = sid_value;
float sx = sx_value;
float sy = sy_value;
int dx = dx_value;
int dy = dy_value;
float o2Dx = o2Dx_value;
float o2Dy = o2Dy_value;
float threshold = threshold_value;
const char* file_path = ct_file_path; //ct路径
const char* save_path = drr_save_path;
cout << "input_path = " << file_path << endl;
cout << "save_path = " << save_path << endl;
有两点需要注意:
1)有个别头文件有可能在windows上不报错,但是在linux会提示找不到,这时候需要可以重新按照那个头文件重新写一遍,一般是由于大小写的问题找不到,换为编译器提示的那个就行。
2)头文件需要将#include <io.h>替换为 #include <sys/io.h>否则可能报错
2.3.编译代码
需要在代码文件所在的同级目录新建一个CMakeLists.txt,将下面的内容加入:
cmake_minimum_required(VERSION 3.12) # 自己设定编译这个文件最低需要的cmake版本
project(Linux_cpp_to_python) # 这里一般填你的上一级文件名称,也就是cpp代码所在的文件夹
# 设置编译标准
set(CMAKE_CXX_STANDARD 14)
# 查找 ITK 库的路径
set(ITK_DIR "安装的ITK路径") # 这里我安装在"home/user_name/ITK"
# 查找 ITK 库
find_package(ITK REQUIRED)
include(${ITK_USE_FILE})
# 源文件列表
set(SOURCES gendrr.cpp) # cpp的文件名
# 生成共享库
add_library(itk_drr SHARED ${SOURCES}) # 最终生成的.so库名字,最后会生成前面带有lib的.so文件
# 链接 ITK 库到共享库
target_link_libraries(itk_drr ${ITK_LIBRARIES}) # 这里写前面的.so库名字
保存好这个文件后,我们在cpp文件同级目录下,新建build文件夹,接下来在vscode打开终端,输入以下命令:
cd build
cmake ..
make
就会发现在build文件下生成了共享库文件,我这里是libitk_drr.so文件。
2.4.python调用cpp
有了上面生成.so库,我们可以复制它放到和.cpp同级的目录下面,再新建一个py文件,来调用。
代码如下:
from ctypes import cdll, c_int, c_char_p, c_float
def ITK_gen_drr(rx, ry, rz, tx, ty, tz, cx, cy, cz, sid, sx, sy, dx, dy, o2Dx, o2Dy, threshold, ct_file_path, drr_save_path):
rx = rx
ry = ry
rz = rz
tx = tx
ty = ty
tz = tz
cx = cx
cy = cy
cz = cz
sid = sid
sx = sx
sy = sy
dx = dx
dy = dy
o2Dx = o2Dx
o2Dy = o2Dy
threshold = threshold
ct_file_path = ct_file_path
drr_save_path = drr_save_path
#加载cpp的itk生成drr共享库
lib_itk = cdll.LoadLibrary("./libitk_drr.so")
# 输入参数
lib_itk.Generate_drr.argtypes = [c_float, c_float, c_float,
c_float, c_float, c_float,
c_float, c_float, c_float,
c_float, c_float, c_float,
c_int, c_int, c_float,
c_float,c_float, c_char_p, c_char_p]
# 输出参数
lib_itk.Generate_drr.restype = c_int
lib_itk.Generate_drr(rx,ry, rz, tx, ty, tz, cx, cy, cz, sid, sx, sy, dx, dy, o2Dx, o2Dy, threshold, ct_file_path.encode('utf-8'), drr_save_path.encode('utf-8'))
if __name__ == "__main__":
rx = -90
ry = 0
rz = 0
tx = 0
ty = 0
tz = 0
cx = 0
cy = 0
cz = 0
sid = 1000
sx = 0.25
sy = 0.25
dx = 1000
dy = 1000
o2Dx = 0
o2Dy = 0
threshold = 0
ct_file_path = ".nii.gz文件路径"
drr_save_path = "保存图片路径"
ITK_gen_drr(rx,ry, rz, tx, ty, tz, cx, cy, cz, sid, sx, sy, dx, dy, o2Dx, o2Dy, threshold, ct_file_path, drr_save_path)
注意:
1)输入参数,输出参数那两行代码里面的Generate_drr为cpp代码的函数名;
2)路径需要用utf-8来编码;
三、总结
如上,现在应该可以生成drr了,批量生成我想就不用写了,这个比较简单,写个循环不停的传参即可。示例:
上个礼拜花了一天在linux配好ITK,花了一天实现python来调用cpp,总算挤点时间写下来了,下一篇写如何用python生成drr的coco数据格式。
四、参考博客
1.win10+visual studio 2022+itk+生成drr
2.ITK的安装与测试(Ubuntu系统)
3.Linux 下报错没有 io.h 等文件解决方法
4.Python调用C++
5.Ubuntu下使用cmake运行c++程序
更多的可以到我的个人博客查看