一、Plot2d类
模块位于opencv_contrib内。在附属模块中提供了与python/matlab相似的plot绘制折线图的功能。
此绘图模块允许您轻松绘制一维或二维数据。您可以更改窗口的大小、轴的范围和每个元素的颜色。 您还可以实时显示正在构建的绘图或将绘图保存为图像 (png)。
虽然功能感觉没有python或者matlab强大,不过用惯了opencv的话,绘制一般的1d、2d图形/图像的要求还是完全可以满足的。
1、函数原型
数据渲染
virtual void render (OutputArray _plotResult)=0
设置网格数量
virtual void setGridLinesNumber (int gridLinesNumber)=0
是否反转方向
virtual void setInvertOrientation (bool _invertOrientation)=0
设置坐标系最大最小
virtual void setMaxX (double _plotMaxX)=0
virtual void setMaxY (double _plotMaxY)=0
virtual void setMinX (double _plotMinX)=0
virtual void setMinY (double _plotMinY)=0
如果为真,则相邻的绘图点将通过线连接。 在其他情况下,数据将被绘制为一组独立点。
virtual void setNeedPlotLine (bool _needPlotLine)=0
/设置相关颜色、线条粗细、文字大小、颜色等
virtual void setPlotAxisColor (Scalar _plotAxisColor)=0
virtual void setPlotBackgroundColor (Scalar _plotBackgroundColor)=0
virtual void setPlotGridColor (Scalar _plotGridColor)=0
virtual void setPlotLineColor (Scalar _plotLineColor)=0
virtual void setPlotLineWidth (int _plotLineWidth)=0
virtual void setPlotSize (int _plotSizeWidth, int _plotSizeHeight)=0
virtual void setPlotTextColor (Scalar _plotTextColor)=0
设置将在绘图左上角打印坐标的点的索引(如果 ShowText 标志为真)。
virtual void setPointIdxToPrint (int pointIdx)=0
//网格显示标志
virtual void setShowGrid (bool needShowGrid)=0
//文字显示标志
virtual void setShowText (bool needShowText)=0
创建对象方法:输入是Mat对象,可以是一个或者两个,都是mat结构的。
static Ptr< Plot2d > create (InputArray data);
static Ptr< Plot2d > create (InputArray dataX, InputArray dataY);
二、OpenCV源码
1、源码路径
opencv_contrib\modules\plot\src\plot.cpp
2、部分源码代码
render方法的源码参考。
//render the plotResult to a Mat
void render(OutputArray _plotResult) CV_OVERRIDE
{
//create the plot result
_plotResult.create(plotSizeHeight, plotSizeWidth, CV_8UC3);
plotResult = _plotResult.getMat();
plotResult.setTo(plotBackgroundColor);
int NumVecElements = plotDataX.rows;
Mat InterpXdata = linearInterpolation(plotMinX, plotMaxX, 0, plotSizeWidth, plotDataX);
Mat InterpYdata = invertOrientation ?
linearInterpolation(plotMaxY, plotMinY, 0, plotSizeHeight, plotDataY) :
linearInterpolation(plotMinY, plotMaxY, 0, plotSizeHeight, plotDataY);
//Find the zeros in image coordinates
Mat InterpXdataFindZero = linearInterpolation(plotMinX_plusZero, plotMaxX_plusZero, 0, plotSizeWidth, plotDataX_plusZero);
Mat InterpYdataFindZero = invertOrientation ?
linearInterpolation(plotMaxY_plusZero, plotMinY_plusZero, 0, plotSizeHeight, plotDataY_plusZero) :
linearInterpolation(plotMinY_plusZero, plotMaxY_plusZero, 0, plotSizeHeight, plotDataY_plusZero);
int ImageXzero = (int)InterpXdataFindZero.at<double>(NumVecElements,0);
int ImageYzero = (int)InterpYdataFindZero.at<double>(NumVecElements,0);
double CurrentX = plotDataX.at<double>(cursorPos,0);
double CurrentY = plotDataY.at<double>(cursorPos,0);
drawAxis(ImageXzero,ImageYzero, CurrentX, CurrentY, plotAxisColor, plotGridColor);
if(needPlotLine)
{
//Draw the plot by connecting lines between the points
Point p1;
p1.x = (int)InterpXdata.at<double>(0,0);
p1.y = (int)InterpYdata.at<double>(0,0);
for (int r=1; r<InterpXdata.rows; r++)
{
Point p2;
p2.x = (int)InterpXdata.at<double>(r,0);
p2.y = (int)InterpYdata.at<double>(r,0);
line(plotResult, p1, p2, plotLineColor, plotLineWidth, 8, 0);
p1 = p2;
}
}
else
{
for (int r=0; r<InterpXdata.rows; r++)
{
Point p;
p.x = (int)InterpXdata.at<double>(r,0);
p.y = (int)InterpYdata.at<double>(r,0);
circle(plotResult, p, 1, plotLineColor, plotLineWidth, 8, 0);
}
}
}
三、简单示例
1、示例1:循环绘制正弦曲线
参考代码
// Initialize Data
std::vector<double> sine;
for( int t = 0; t < 360; t++ ){
sine.push_back( std::sin( t * CV_PI / 180.0 ) );
}
// Create Ploter
cv::Mat data( sine );
cv::Ptr<cv::plot::Plot2d> plot = cv::plot::Plot2d::create(data);
while( true )
{
// Rotation Data
double value = *sine.begin();
sine.erase( sine.begin() );
sine.push_back( value );
// Render Plot Image
cv::Mat image;
plot->render( image );
// Show Image
cv::imshow( "sine", image );
if( cv::waitKey( 33 ) >= 0 ){
break;
}
}
示例图像,因为是while循环,所以会一致绘制。
2、示例2:官方示例
std::vector<double> data_x;
std::vector<double> data_y;
data_x.push_back(0);
data_y.push_back(0);
std::cout << "data_x : " << data_x[0] << std::endl;
std::cout << "data_y : " << data_y[0] << std::endl;
for(int i =1; i < 1000; i++) {
data_x.push_back(i*0.01);
data_y.push_back(std::sin(data_x.back()));
cv::Mat plot_result;
cv::Ptr<cv::plot::Plot2d> plot = cv::plot::Plot2d::create(data_x, data_y);
plot->render(plot_result);
imshow("The plot rendered with default visualization options", plot_result);
plot->setShowText(false);
plot->setShowGrid(false);
plot->setPlotBackgroundColor(cv::Scalar(255, 200, 200));
plot->setPlotLineColor(cv::Scalar(255, 0, 0));
plot->setPlotLineWidth(2);
plot->setInvertOrientation(true);
plot->render(plot_result);
imshow("The plot rendered with some of custom visualization options",
plot_result);
cv::waitKey(3);
}
cv::waitKey();
{
char tmp;
std::cin >> tmp;
}
从平缓的曲线慢慢变成规律的波形。