一、前言

在写代码的过程中,我们有时候需要对数据进行可视化,但是对于C++来说,并没有一个像python中matplotlib一样方便使用且功能强大的绘图包。但是,我在github发现了一个名为matplotlib-cpp的绘图开源包,第一眼看到我以为这可能时matplotlib的C++版本,但后来仔细一看是C++调用python。将matplotlib进行了封装。但是,这对一般的数据可视化来说并不是大问题,即便运行速度会降低。

matplotlib-cpp项目地址

二、使用

首先,克隆项目之后,我们来看看代码的目录结构

  • contrib
  • examples
  • matplotlibcpp.h
  • ....(not important)

contrib目录下有作者提供的编译方法。 examples目录下有一些代码示例。 matplotlibcpp.h只需要在代码中包含这个头文件就可以使用matplotlibcpp提供的API画图。

对于我来说,我平常使用windows10+ubuntu16.04的开发环境,因此最简单的方法就是使用cmake来构建项目。以下代码为contrib/CMakeLists.txt提供的示例。

cmake_minimum_required(VERSION 3.7)
project (MatplotlibCPP_Test)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

include_directories(${PYTHONHOME}/include)
include_directories(${PYTHONHOME}/Lib/site-packages/numpy/core/include)
link_directories(${PYTHONHOME}/libs)

add_definitions(-DMATPLOTLIBCPP_PYTHON_HEADER=Python.h)

add_executable(minimal ${CMAKE_CURRENT_SOURCE_DIR}/../examples/minimal.cpp)
add_executable(basic ${CMAKE_CURRENT_SOURCE_DIR}/../examples/basic.cpp)
add_executable(modern ${CMAKE_CURRENT_SOURCE_DIR}/../examples/modern.cpp)
add_executable(animation ${CMAKE_CURRENT_SOURCE_DIR}/../examples/animation.cpp)
add_executable(nonblock ${CMAKE_CURRENT_SOURCE_DIR}/../examples/nonblock.cpp)
add_executable(xkcd ${CMAKE_CURRENT_SOURCE_DIR}/../examples/xkcd.cpp)
add_executable(bar ${CMAKE_CURRENT_SOURCE_DIR}/../examples/bar.cpp)

需要注意PYTHONHOME这个变量,在ubuntu和windows10上,这个变量应该设置为你本地的python根目录。

在windows10下,需要使用set命令,将PYTHONHOME变量值设置为你python的安装目录。

set(PYTHONHOME C:/Users/%username%/AppData/Local/Programs/Python/Python36)

在ubuntu下,

find_package(PythonLibs 2.7)
target_include_directories(yourproject PRIVATE ${PYTHON_INCLUDE_DIRS})
target_link_libraries(yourproject ${PYTHON_LIBRARIES})

下面是我改的CMakeLists.txt,作为参考

cmake_minimum_required(VERSION 3.5)
project (matplitlib_cpp_test)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
IF (WIN32)
    MESSAGE(STATUS "Now is windows")
    # 改为你的python路径
    set(PYTHONHOME C:/Users/%username%/AppData/Local/Programs/Python/Python36)
    add_executable(simple_test src/simple_test.cpp)
    include_directories(${PYTHONHOME}/include)
    include_directories(${PYTHONHOME}/Lib/site-packages/numpy/core/include)
    link_directories(${PYTHONHOME}/libs)

ELSEIF (UNIX)
    MESSAGE(STATUS "Now is UNIX-like OS's.")

    find_package(PythonLibs 2.7)
    add_executable(simple_test src/simple_test.cpp)
    target_include_directories(simple_test PRIVATE ${PYTHON_INCLUDE_DIRS})
    target_link_libraries(simple_test ${PYTHON_LIBRARIES})
    include_directories(/usr/local/lib/python2.7/dist-packages/numpy/core/include)

ENDIF ()

include_directories(include)

add_definitions(-DMATPLOTLIBCPP_PYTHON_HEADER=Python.h)

另外,你也可以直接访问我的github项目,我会将我的测试示例放在上面:matplotlibcpp-test

编写完CMakeLists.txt之后,怎么编译呢?很简单,新建在CMakeLists.txt当前目录下新建一个名为build的目录,然后使用命令cmake ..,即可编译。

在win10下,默认生成Visual studio项目,你直接打开.sln文件编译运行即可。需要注意的是,在按下绿色三角编译运行之前,你需要看你的python是不是支持Debug,即安装python时有没有安装Debug模块,可以在你的python路径下的libs文件夹内看是否有pythonxx_d.lib 类似文件。如果你没有安装Debug功能,那么需要在Visual studio将Debug模式改为Release模式再编译。其次,你需要看你安装的python版本是32位还是64位的,同样,如果是64位,Visual studio默认生成64位的可执行文件不用修改,但是如果你的python是32位,那么需要将Visual studio生成可执行文件的配置改为32位。最后,如果编译报错不能打开pythonxx.lib文件,那么你需要将python路径下libs文件夹下的pythonxx.lib复制到build目录下,然后再编译。如果还遇到其他问题,就自行google吧。

在ubuntu下,cmake之后会生成Makefile文件,使用make命令进行编译即可。

三、测试结果

3.1 简单曲线

#include "matplotlibcpp.h"

namespace plt = matplotlibcpp;

int main() {
    plt::plot({1,3,2,4});
    plt::show();
}

3.3 动态曲线

#define _USE_MATH_DEFINES
#include <cmath>
#include "matplotlibcpp.h"

namespace plt = matplotlibcpp;

int main()
{
    int n = 1000;
    std::vector<double> x, y, z;

    for(int i=0; i<n; i++) {
        x.push_back(i*i);
        y.push_back(sin(2*M_PI*i/360.0));
        z.push_back(log(i));

        if (i % 10 == 0) {
            // Clear previous plot
            plt::clf();
            // Plot line from given x and y data. Color is selected automatically.
            plt::plot(x, y);
            // Plot a line whose name will show up as "log(x)" in the legend.
            plt::named_plot("log(x)", x, z);

            // Set x-axis to interval [0,1000000]
            plt::xlim(0, n*n);

            // Add graph title
            plt::title("Sample figure");
            // Enable legend.
            plt::legend();
            // Display plot continuously
            plt::pause(0.01);

            plt::save("./dynamic_curve.png");
        }
    }
}

更多示例可以访问该github项目。

四、参考资料

[1] matplotlib-cpp

[2] C++调用matplotlib

Last modification:October 21st, 2020 at 08:08 am
如果觉得我的文章对你有用,请随意赞赏