13

Does OpenCV provide a function on how to draw and plot a graph?

I found this link by Shervin Emami http://www.shervinemami.info/graphs.html which was created by himself.

Mzk
  • 1,102
  • 3
  • 17
  • 40

5 Answers5

11

you can try this: https://code.google.com/p/cvplot/

Matlab style plot functions for OpenCV, based on highgui. By the way, it's for C++ only.

It's open source.

bobov
  • 111
  • 3
  • I'm not sure how to use the cvplot. but thanks. The program I tried on Shervin works perfectly as well. It just that I can view the x and y axis values. – Mzk Mar 11 '12 at 02:57
8

From what I can see OpenCV doesn't provide a function as part of its API to draw and plot graphs, in the form of cvDrawPlot(cvMat* data, other args...).

Most plotting samples seen using only OpenCV function calls involving making a plot as if were any other image with cvCreateImage.

Then they iterate through data and fill the image with OpenCV primites like cvRectangle, cvLine, cvCircle and cvPoint.

Then they call cvShowImage to display the created plot image.

If the library you found does what you want then you can use it.

You can also write the data to a file and call an external plotting tool like gnuplot or call functions that draw and plot graphs using other visualisation or plotting libraries like VTK or plplot.

Another library other than the one you have found is cvplot.

Appleman1234
  • 15,946
  • 45
  • 67
  • It may also be easiest to output the data to a .csv file an import it into Excel then plot the graph. –  Apr 19 '18 at 00:53
4

A rather crude but do-it-yourself approach, would be entail plotting the line graph on cv::Mat image:

template <typename T>
cv::Mat plotGraph(std::vector<T>& vals, int YRange[2])
{

    auto it = minmax_element(vals.begin(), vals.end());
    float scale = 1./ceil(*it.second - *it.first); 
    float bias = *it.first;
    int rows = YRange[1] - YRange[0] + 1;
    cv::Mat image = Mat::zeros( rows, vals.size(), CV_8UC3 );
    image.setTo(0);
    for (int i = 0; i < (int)vals.size()-1; i++)
    {
        cv::line(image, cv::Point(i, rows - 1 - (vals[i] - bias)*scale*YRange[1]), cv::Point(i+1, rows - 1 - (vals[i+1] - bias)*scale*YRange[1]), Scalar(255, 0, 0), 1);
    }

    return image;
}

Usage example:

vector<int> numbers(100);
std::iota (numbers.begin(), numbers.end(), 0);

int range[2] = {0, 100};
cv::Mat lineGraph = plotGraph(numbers, range);

One can then use imshow or Image Watch to view the graph

Yonatan Simson
  • 2,395
  • 1
  • 24
  • 35
3

No. It does not. There is a plot contrib module, but it is very basic.

You could try Profactor CvPlot https://github.com/Profactor/cv-plot. (I am the developer). It is very easy to integrate, purely opencv based and can be extended with custom controls. This is how you can plot to a cv::Mat or show a diagram with an interactive viewer:

#include <CvPlot/cvplot.h>
std::vector<double> x(20*1000), y1(x.size()), y2(x.size()), y3(x.size());
for (size_t i = 0; i < x.size(); i++) {
    x[i] = i * CV_2PI / x.size();
    y1[i] = std::sin(x[i]);
    y2[i] = y1[i] * std::sin(x[i]*50);
    y3[i] = y2[i] * std::sin(x[i]*500);
}
auto axes = CvPlot::makePlotAxes();
axes.create<CvPlot::Series>(x, y3, "-g");
axes.create<CvPlot::Series>(x, y2, "-b");
axes.create<CvPlot::Series>(x, y1, "-r");

//plot to a cv::Mat
cv::Mat mat = axes.render(300, 400);

//or show with interactive viewer
CvPlot::show("mywindow", axes);

CvPlot

You may also want to try Leonardvandriel's cvplot. It works similar but cannot be extended with custom drawables.

palfi
  • 288
  • 2
  • 6
  • Do not post a link to a tool or library as an answer. Demonstrate [how it solves the problem](http://meta.stackoverflow.com/a/251605) in the answer itself. Do [edit] the answer, and flag for undeletion once you have added the demonstration. – Bhargav Rao Mar 15 '20 at 09:24
2

Take a look at https://github.com/leonardvandriel/cvplot. You can plot graphs with little configuration and it supports multiple graphs in a single window. (Note: blatant self-promotion).

leo
  • 7,518
  • 1
  • 24
  • 25