Skip to content
9 changes: 6 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
examples: minimal basic modern animation nonblock xkcd quiver bar surface fill_inbetween fill update
examples: minimal basic modern animation nonblock xkcd quiver bar surface fill_inbetween fill update imshow

minimal: examples/minimal.cpp matplotlibcpp.h
cd examples && g++ -DWITHOUT_NUMPY minimal.cpp -I/usr/include/python2.7 -lpython2.7 -o minimal -std=c++11
Expand Down Expand Up @@ -32,9 +32,12 @@ fill_inbetween: examples/fill_inbetween.cpp matplotlibcpp.h

fill: examples/fill.cpp matplotlibcpp.h
cd examples && g++ fill.cpp -I/usr/include/python2.7 -lpython2.7 -o fill -std=c++11

update: examples/update.cpp matplotlibcpp.h
cd examples && g++ update.cpp -I/usr/include/python2.7 -lpython2.7 -o update -std=c++11

imshow: examples/imshow.cpp matplotlibcpp.h
cd examples && g++ imshow.cpp -I/usr/include/python2.7 -lpython2.7 -o imshow -std=c++11

clean:
rm -f examples/{minimal,basic,modern,animation,nonblock,xkcd,quiver,bar,surface,fill_inbetween,fill,update}
rm -f examples/{minimal,basic,modern,animation,nonblock,xkcd,quiver,bar,surface,fill_inbetween,fill,update,imshow}
27 changes: 27 additions & 0 deletions examples/imshow.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#define _USE_MATH_DEFINES
#include <cmath>
#include "../matplotlibcpp.h"

using namespace std;
namespace plt = matplotlibcpp;

int main()
{
// Prepare data
int ncols = 500, nrows = 300;
std::vector<float> z(ncols * nrows);
for (int j=0; j<nrows; ++j) {
for (int i=0; i<ncols; ++i) {
z.at(ncols * j + i) = std::sin(std::hypot(i - ncols/2, j - nrows/2));
}
}

const float* zptr = &(z[0]);
const int colors = 1;

plt::title("My matrix");
plt::imshow(zptr, nrows, ncols, colors);

// Show plots
plt::save("imshow.png");
}
86 changes: 86 additions & 0 deletions matplotlibcpp.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
#ifndef WITHOUT_NUMPY
# define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
# include <numpy/arrayobject.h>

# ifdef WITH_OPENCV
# include <opencv2/opencv.hpp>
# endif // WITH_OPENCV
#endif // WITHOUT_NUMPY

#if PY_MAJOR_VERSION >= 3
Expand Down Expand Up @@ -45,6 +49,7 @@ struct _interpreter {
PyObject *s_python_function_fill;
PyObject *s_python_function_fill_between;
PyObject *s_python_function_hist;
PyObject *s_python_function_imshow;
PyObject *s_python_function_scatter;
PyObject *s_python_function_subplot;
PyObject *s_python_function_legend;
Expand Down Expand Up @@ -165,6 +170,9 @@ struct _interpreter {
s_python_function_fill = PyObject_GetAttrString(pymod, "fill");
s_python_function_fill_between = PyObject_GetAttrString(pymod, "fill_between");
s_python_function_hist = PyObject_GetAttrString(pymod,"hist");
#ifndef WITHOUT_NUMPY
s_python_function_imshow = PyObject_GetAttrString(pymod, "imshow");
#endif
s_python_function_scatter = PyObject_GetAttrString(pymod,"scatter");
s_python_function_subplot = PyObject_GetAttrString(pymod, "subplot");
s_python_function_legend = PyObject_GetAttrString(pymod, "legend");
Expand Down Expand Up @@ -211,6 +219,9 @@ struct _interpreter {
|| !s_python_function_axis
|| !s_python_function_xlabel
|| !s_python_function_ylabel
#ifndef WITHOUT_NUMPY
|| !s_python_function_imshow
#endif
|| !s_python_function_grid
|| !s_python_function_xlim
|| !s_python_function_ion
Expand Down Expand Up @@ -246,6 +257,9 @@ struct _interpreter {
|| !PyFunction_Check(s_python_function_legend)
|| !PyFunction_Check(s_python_function_annotate)
|| !PyFunction_Check(s_python_function_ylim)
#ifndef WITHOUT_NUMPY
|| !PyFunction_Check(s_python_function_imshow)
#endif
|| !PyFunction_Check(s_python_function_title)
|| !PyFunction_Check(s_python_function_axis)
|| !PyFunction_Check(s_python_function_xlabel)
Expand Down Expand Up @@ -623,6 +637,78 @@ bool hist(const std::vector<Numeric>& y, long bins=10,std::string color="b",
return res;
}

#ifndef WITHOUT_NUMPY
namespace internal {
void imshow(void *ptr, const NPY_TYPES type, const int rows, const int columns, const int colors, const std::map<std::string, std::string> &keywords)
{
assert(type == NPY_UINT8 || type == NPY_FLOAT);
assert(colors == 1 || colors == 3 || colors == 4);

detail::_interpreter::get(); //interpreter needs to be initialized for the numpy commands to work

// construct args
npy_intp dims[3] = { rows, columns, colors };
PyObject *args = PyTuple_New(1);
PyTuple_SetItem(args, 0, PyArray_SimpleNewFromData(colors == 1 ? 2 : 3, dims, type, ptr));

// construct keyword args
PyObject* kwargs = PyDict_New();
for(std::map<std::string, std::string>::const_iterator it = keywords.begin(); it != keywords.end(); ++it)
{
PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
}

PyObject *res = PyObject_Call(detail::_interpreter::get().s_python_function_imshow, args, kwargs);
Py_DECREF(args);
Py_DECREF(kwargs);
if (!res)
throw std::runtime_error("Call to imshow() failed");
Py_DECREF(res);
}
}

void imshow(const unsigned char *ptr, const int rows, const int columns, const int colors, const std::map<std::string, std::string> &keywords = {})
{
internal::imshow((void *) ptr, NPY_UINT8, rows, columns, colors, keywords);
}

void imshow(const float *ptr, const int rows, const int columns, const int colors, const std::map<std::string, std::string> &keywords = {})
{
internal::imshow((void *) ptr, NPY_FLOAT, rows, columns, colors, keywords);
}

#ifdef WITH_OPENCV
void imshow(const cv::Mat &image, const std::map<std::string, std::string> &keywords = {})
{
// Convert underlying type of matrix, if needed
cv::Mat image2;
NPY_TYPES npy_type = NPY_UINT8;
switch (image.type() & CV_MAT_DEPTH_MASK) {
case CV_8U:
image2 = image;
break;
case CV_32F:
image2 = image;
npy_type = NPY_FLOAT;
break;
default:
image.convertTo(image2, CV_MAKETYPE(CV_8U, image.channels()));
}

// If color image, convert from BGR to RGB
switch (image2.channels()) {
case 3:
cv::cvtColor(image2, image2, CV_BGR2RGB);
break;
case 4:
cv::cvtColor(image2, image2, CV_BGRA2RGBA);
}

internal::imshow(image2.data, npy_type, image2.rows, image2.cols, image2.channels(), keywords);
}
#endif
#endif

template<typename NumericX, typename NumericY>
bool scatter(const std::vector<NumericX>& x,
const std::vector<NumericY>& y,
Expand Down