1 /*M/////////////////////////////////////////////////////////////////////////////////////// 2 // 3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. 4 // 5 // By downloading, copying, installing or using the software you agree to this license. 6 // If you do not agree to this license, do not download, install, 7 // copy or use the software. 8 // 9 // 10 // License Agreement 11 // For Open Source Computer Vision Library 12 // 13 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved. 14 // Copyright (C) 2009, Willow Garage Inc., all rights reserved. 15 // Third party copyrights are property of their respective owners. 16 // 17 // Redistribution and use in source and binary forms, with or without modification, 18 // are permitted provided that the following conditions are met: 19 // 20 // * Redistribution's of source code must retain the above copyright notice, 21 // this list of conditions and the following disclaimer. 22 // 23 // * Redistribution's in binary form must reproduce the above copyright notice, 24 // this list of conditions and the following disclaimer in the documentation 25 // and/or other materials provided with the distribution. 26 // 27 // * The name of the copyright holders may not be used to endorse or promote products 28 // derived from this software without specific prior written permission. 29 // 30 // This software is provided by the copyright holders and contributors "as is" and 31 // any express or implied warranties, including, but not limited to, the implied 32 // warranties of merchantability and fitness for a particular purpose are disclaimed. 33 // In no event shall the Intel Corporation or contributors be liable for any direct, 34 // indirect, incidental, special, exemplary, or consequential damages 35 // (including, but not limited to, procurement of substitute goods or services; 36 // loss of use, data, or profits; or business interruption) however caused 37 // and on any theory of liability, whether in contract, strict liability, 38 // or tort (including negligence or otherwise) arising in any way out of 39 // the use of this software, even if advised of the possibility of such damage. 40 // 41 //M*/ 42 //################################################################################ 43 // 44 // Created by Nuno Moutinho 45 // 46 //################################################################################ 47 48 #include "precomp.hpp" 49 50 namespace cv 51 { 52 namespace plot 53 { 54 using namespace std; 55 56 class Plot2dImpl CV_FINAL : public Plot2d 57 { 58 public: 59 Plot2dImpl(InputArray plotData)60 Plot2dImpl(InputArray plotData) 61 { 62 Mat _plotData = plotData.getMat(); 63 //if the matrix is not Nx1 or 1xN 64 if(_plotData.cols > 1 && _plotData.rows > 1) 65 CV_Error(Error::StsBadArg, "ERROR: Plot data must be a 1xN or Nx1 matrix.\n"); 66 67 CV_Assert(_plotData.type() == CV_64F); 68 69 //in case we have a row matrix than needs to be transposed 70 if(_plotData.cols > _plotData.rows) 71 { 72 _plotData = _plotData.t(); 73 } 74 75 plotDataY=_plotData; 76 plotDataX = plotDataY*0; 77 for (int i=0; i<plotDataY.rows; i++) 78 { 79 plotDataX.at<double>(i,0) = i; 80 } 81 82 //calling the main constructor 83 plotHelper(plotDataX, plotDataY); 84 85 } 86 Plot2dImpl(InputArray plotDataX_,InputArray plotDataY_)87 Plot2dImpl(InputArray plotDataX_, InputArray plotDataY_) 88 { 89 Mat _plotDataX = plotDataX_.getMat(); 90 Mat _plotDataY = plotDataY_.getMat(); 91 //f the matrix is not Nx1 or 1xN 92 if((_plotDataX.cols > 1 && _plotDataX.rows > 1) || (_plotDataY.cols > 1 && _plotDataY.rows > 1)) 93 CV_Error(Error::StsBadArg, "ERROR: Plot data must be a 1xN or Nx1 matrix.\n"); 94 95 CV_Assert(_plotDataX.type() == CV_64F && _plotDataY.type() == CV_64F); 96 97 //in case we have a row matrix than needs to be transposed 98 if(_plotDataX.cols > _plotDataX.rows) 99 { 100 _plotDataX = _plotDataX.t(); 101 } 102 if(_plotDataY.cols > _plotDataY.rows) 103 { 104 _plotDataY = _plotDataY.t(); 105 } 106 107 plotHelper(_plotDataX, _plotDataY); 108 } 109 110 //set functions setMinX(double _plotMinX)111 void setMinX(double _plotMinX) CV_OVERRIDE 112 { 113 plotMinX = _plotMinX; 114 plotMinX_plusZero = _plotMinX; 115 } setMaxX(double _plotMaxX)116 void setMaxX(double _plotMaxX) CV_OVERRIDE 117 { 118 plotMaxX = _plotMaxX; 119 plotMaxX_plusZero = _plotMaxX; 120 } setMinY(double _plotMinY)121 void setMinY(double _plotMinY) CV_OVERRIDE 122 { 123 plotMinY = _plotMinY; 124 plotMinY_plusZero = _plotMinY; 125 } setMaxY(double _plotMaxY)126 void setMaxY(double _plotMaxY) CV_OVERRIDE 127 { 128 plotMaxY = _plotMaxY; 129 plotMaxY_plusZero = _plotMaxY; 130 } setPlotLineWidth(int _plotLineWidth)131 void setPlotLineWidth(int _plotLineWidth) CV_OVERRIDE 132 { 133 plotLineWidth = _plotLineWidth; 134 } setInvertOrientation(bool _invertOrientation)135 void setInvertOrientation(bool _invertOrientation) CV_OVERRIDE 136 { 137 invertOrientation = _invertOrientation; 138 } setNeedPlotLine(bool _needPlotLine)139 void setNeedPlotLine(bool _needPlotLine) CV_OVERRIDE 140 { 141 needPlotLine = _needPlotLine; 142 } setPlotLineColor(Scalar _plotLineColor)143 void setPlotLineColor(Scalar _plotLineColor) CV_OVERRIDE 144 { 145 plotLineColor=_plotLineColor; 146 } setPlotBackgroundColor(Scalar _plotBackgroundColor)147 void setPlotBackgroundColor(Scalar _plotBackgroundColor) CV_OVERRIDE 148 { 149 plotBackgroundColor=_plotBackgroundColor; 150 } setPlotAxisColor(Scalar _plotAxisColor)151 void setPlotAxisColor(Scalar _plotAxisColor) CV_OVERRIDE 152 { 153 plotAxisColor=_plotAxisColor; 154 } setPlotGridColor(Scalar _plotGridColor)155 void setPlotGridColor(Scalar _plotGridColor) CV_OVERRIDE 156 { 157 plotGridColor=_plotGridColor; 158 } setPlotTextColor(Scalar _plotTextColor)159 void setPlotTextColor(Scalar _plotTextColor) CV_OVERRIDE 160 { 161 plotTextColor=_plotTextColor; 162 } setPlotSize(int _plotSizeWidth,int _plotSizeHeight)163 void setPlotSize(int _plotSizeWidth, int _plotSizeHeight) CV_OVERRIDE 164 { 165 if(_plotSizeWidth > 400) 166 plotSizeWidth = _plotSizeWidth; 167 else 168 plotSizeWidth = 400; 169 170 if(_plotSizeHeight > 300) 171 plotSizeHeight = _plotSizeHeight; 172 else 173 plotSizeHeight = 300; 174 } setShowGrid(bool _needShowGrid)175 void setShowGrid(bool _needShowGrid) CV_OVERRIDE 176 { 177 needShowGrid = _needShowGrid; 178 } setShowText(bool _needShowText)179 void setShowText(bool _needShowText) CV_OVERRIDE 180 { 181 needShowText = _needShowText; 182 } setGridLinesNumber(int _gridLinesNumber)183 void setGridLinesNumber(int _gridLinesNumber) CV_OVERRIDE 184 { 185 if(_gridLinesNumber <= 0) 186 _gridLinesNumber = 1; 187 gridLinesNumber = _gridLinesNumber; 188 } setPointIdxToPrint(int _cursorPos)189 void setPointIdxToPrint(int _cursorPos) CV_OVERRIDE 190 { 191 if(_cursorPos >= plotDataX.rows || _cursorPos < 0) 192 _cursorPos = plotDataX.rows - 1; 193 cursorPos = _cursorPos; 194 } 195 //render the plotResult to a Mat render(OutputArray _plotResult)196 void render(OutputArray _plotResult) CV_OVERRIDE 197 { 198 //create the plot result 199 _plotResult.create(plotSizeHeight, plotSizeWidth, CV_8UC3); 200 plotResult = _plotResult.getMat(); 201 plotResult.setTo(plotBackgroundColor); 202 203 int NumVecElements = plotDataX.rows; 204 205 Mat InterpXdata = linearInterpolation(plotMinX, plotMaxX, 0, plotSizeWidth, plotDataX); 206 Mat InterpYdata = invertOrientation ? 207 linearInterpolation(plotMaxY, plotMinY, 0, plotSizeHeight, plotDataY) : 208 linearInterpolation(plotMinY, plotMaxY, 0, plotSizeHeight, plotDataY); 209 210 //Find the zeros in image coordinates 211 Mat InterpXdataFindZero = linearInterpolation(plotMinX_plusZero, plotMaxX_plusZero, 0, plotSizeWidth, plotDataX_plusZero); 212 Mat InterpYdataFindZero = invertOrientation ? 213 linearInterpolation(plotMaxY_plusZero, plotMinY_plusZero, 0, plotSizeHeight, plotDataY_plusZero) : 214 linearInterpolation(plotMinY_plusZero, plotMaxY_plusZero, 0, plotSizeHeight, plotDataY_plusZero); 215 216 int ImageXzero = (int)InterpXdataFindZero.at<double>(NumVecElements,0); 217 int ImageYzero = (int)InterpYdataFindZero.at<double>(NumVecElements,0); 218 219 double CurrentX = plotDataX.at<double>(cursorPos,0); 220 double CurrentY = plotDataY.at<double>(cursorPos,0); 221 222 drawAxis(ImageXzero,ImageYzero, CurrentX, CurrentY, plotAxisColor, plotGridColor); 223 224 if(needPlotLine) 225 { 226 //Draw the plot by connecting lines between the points 227 Point p1; 228 p1.x = (int)InterpXdata.at<double>(0,0); 229 p1.y = (int)InterpYdata.at<double>(0,0); 230 231 for (int r=1; r<InterpXdata.rows; r++) 232 { 233 Point p2; 234 p2.x = (int)InterpXdata.at<double>(r,0); 235 p2.y = (int)InterpYdata.at<double>(r,0); 236 237 line(plotResult, p1, p2, plotLineColor, plotLineWidth, 8, 0); 238 239 p1 = p2; 240 } 241 } 242 else 243 { 244 for (int r=0; r<InterpXdata.rows; r++) 245 { 246 Point p; 247 p.x = (int)InterpXdata.at<double>(r,0); 248 p.y = (int)InterpYdata.at<double>(r,0); 249 250 circle(plotResult, p, 1, plotLineColor, plotLineWidth, 8, 0); 251 } 252 } 253 } 254 255 protected: 256 257 Mat plotDataX; 258 Mat plotDataY; 259 Mat plotDataX_plusZero; 260 Mat plotDataY_plusZero; 261 const char * plotName; 262 263 //dimensions and limits of the plot 264 int plotSizeWidth; 265 int plotSizeHeight; 266 double plotMinX; 267 double plotMaxX; 268 double plotMinY; 269 double plotMaxY; 270 double plotMinX_plusZero; 271 double plotMaxX_plusZero; 272 double plotMinY_plusZero; 273 double plotMaxY_plusZero; 274 int plotLineWidth; 275 bool invertOrientation; 276 bool needShowGrid; 277 bool needShowText; 278 int gridLinesNumber; 279 int cursorPos; 280 281 //colors of each plot element 282 Scalar plotLineColor; 283 Scalar plotBackgroundColor; 284 Scalar plotAxisColor; 285 Scalar plotGridColor; 286 Scalar plotTextColor; 287 288 //the final plot result 289 Mat plotResult; 290 291 //flag which enables/disables connection of plotted points by lines 292 bool needPlotLine; 293 plotHelper(Mat _plotDataX,Mat _plotDataY)294 void plotHelper(Mat _plotDataX, Mat _plotDataY) 295 { 296 plotDataX=_plotDataX; 297 plotDataY=_plotDataY; 298 299 int NumVecElements = plotDataX.rows; 300 301 plotDataX_plusZero = Mat::zeros(NumVecElements+1,1,CV_64F); 302 plotDataY_plusZero = Mat::zeros(NumVecElements+1,1,CV_64F); 303 304 for(int i=0; i<NumVecElements; i++){ 305 plotDataX_plusZero.at<double>(i,0) = plotDataX.at<double>(i,0); 306 plotDataY_plusZero.at<double>(i,0) = plotDataY.at<double>(i,0); 307 } 308 309 double MinX; 310 double MaxX; 311 double MinY; 312 double MaxY; 313 double MinX_plusZero; 314 double MaxX_plusZero; 315 double MinY_plusZero; 316 double MaxY_plusZero; 317 318 needPlotLine = true; 319 invertOrientation = false; 320 321 //Obtain the minimum and maximum values of Xdata 322 minMaxLoc(plotDataX,&MinX,&MaxX); 323 324 //Obtain the minimum and maximum values of Ydata 325 minMaxLoc(plotDataY,&MinY,&MaxY); 326 327 //Obtain the minimum and maximum values of Xdata plus zero 328 minMaxLoc(plotDataX_plusZero,&MinX_plusZero,&MaxX_plusZero); 329 330 //Obtain the minimum and maximum values of Ydata plus zero 331 minMaxLoc(plotDataY_plusZero,&MinY_plusZero,&MaxY_plusZero); 332 333 //setting the min and max values for each axis 334 plotMinX = MinX; 335 plotMaxX = MaxX; 336 plotMinY = MinY; 337 plotMaxY = MaxY; 338 plotMinX_plusZero = MinX_plusZero; 339 plotMaxX_plusZero = MaxX_plusZero; 340 plotMinY_plusZero = MinY_plusZero; 341 plotMaxY_plusZero = MaxY_plusZero; 342 343 //setting the default size of a plot figure 344 setPlotSize(600, 400); 345 346 //setting the default plot line size 347 setPlotLineWidth(1); 348 349 //setting default colors for the different elements of the plot 350 setPlotAxisColor(Scalar(0, 0, 255)); 351 setPlotGridColor(Scalar(255, 255, 255)); 352 setPlotBackgroundColor(Scalar(0, 0, 0)); 353 setPlotLineColor(Scalar(0, 255, 255)); 354 setPlotTextColor(Scalar(255, 255, 255)); 355 setShowGrid(true); 356 setShowText(true); 357 setGridLinesNumber(10); 358 setPointIdxToPrint(-1); 359 } 360 drawAxis(int ImageXzero,int ImageYzero,double CurrentX,double CurrentY,Scalar axisColor,Scalar gridColor)361 void drawAxis(int ImageXzero, int ImageYzero, double CurrentX, double CurrentY, Scalar axisColor, Scalar gridColor) 362 { 363 if(needShowText) 364 { 365 drawValuesAsText(0, ImageXzero, ImageYzero, 10, 20); 366 drawValuesAsText(0, ImageXzero, ImageYzero, -20, 20); 367 drawValuesAsText(0, ImageXzero, ImageYzero, 10, -10); 368 drawValuesAsText(0, ImageXzero, ImageYzero, -20, -10); 369 drawValuesAsText((format("X_%d = ", cursorPos) + "%g").c_str(), CurrentX, 0, 0, 40, 20); 370 drawValuesAsText((format("Y_%d = ", cursorPos) + "%g").c_str(), CurrentY, 0, 20, 40, 20); 371 } 372 373 //Horizontal X axis and equispaced horizontal lines 374 int LineSpace = cvRound(plotSizeHeight / (float)gridLinesNumber); 375 int TraceSize = 5; 376 drawLine(0, plotSizeWidth, ImageYzero, ImageYzero, axisColor); 377 378 if(needShowGrid) 379 for(int i=-plotSizeHeight; i<plotSizeHeight; i=i+LineSpace){ 380 381 if(i!=0){ 382 int Trace=0; 383 while(Trace<plotSizeWidth){ 384 drawLine(Trace, Trace+TraceSize, ImageYzero+i, ImageYzero+i, gridColor); 385 Trace = Trace+2*TraceSize; 386 } 387 } 388 } 389 390 //Vertical Y axis 391 drawLine(ImageXzero, ImageXzero, 0, plotSizeHeight, axisColor); 392 LineSpace = cvRound(LineSpace * (float)plotSizeWidth / plotSizeHeight ); 393 394 if(needShowGrid) 395 for(int i=-plotSizeWidth; i<plotSizeWidth; i=i+LineSpace){ 396 397 if(i!=0){ 398 int Trace=0; 399 while(Trace<plotSizeHeight){ 400 drawLine(ImageXzero+i, ImageXzero+i, Trace, Trace+TraceSize, gridColor); 401 Trace = Trace+2*TraceSize; 402 } 403 } 404 } 405 } 406 linearInterpolation(double Xa,double Xb,double Ya,double Yb,Mat Xdata)407 Mat linearInterpolation(double Xa, double Xb, double Ya, double Yb, Mat Xdata){ 408 409 Mat Ydata = Xdata*0; 410 411 for (int i=0; i<Xdata.rows; i++){ 412 413 double X = Xdata.at<double>(i,0); 414 Ydata.at<double>(i,0) = int(Ya + (Yb-Ya)*(X-Xa)/(Xb-Xa)); 415 416 if(Ydata.at<double>(i,0)<0) 417 Ydata.at<double>(i,0)=0; 418 } 419 420 return Ydata; 421 } 422 drawValuesAsText(double Value,int Xloc,int Yloc,int XMargin,int YMargin)423 void drawValuesAsText(double Value, int Xloc, int Yloc, int XMargin, int YMargin){ 424 425 char AxisX_Min_Text[20]; 426 double TextSize = 1; 427 428 sprintf(AxisX_Min_Text, "%g", Value); 429 Point AxisX_Min_Loc; 430 AxisX_Min_Loc.x = Xloc+XMargin; 431 AxisX_Min_Loc.y = Yloc+YMargin; 432 433 putText(plotResult,AxisX_Min_Text, AxisX_Min_Loc, FONT_HERSHEY_COMPLEX_SMALL, TextSize, plotTextColor, 1, 8); 434 } 435 drawValuesAsText(const char * Text,double Value,int Xloc,int Yloc,int XMargin,int YMargin)436 void drawValuesAsText(const char *Text, double Value, int Xloc, int Yloc, int XMargin, int YMargin){ 437 438 char AxisX_Min_Text[20]; 439 int TextSize = 1; 440 441 sprintf(AxisX_Min_Text, Text, Value); 442 Point AxisX_Min_Loc; 443 AxisX_Min_Loc.x = Xloc+XMargin; 444 AxisX_Min_Loc.y = Yloc+YMargin; 445 446 putText(plotResult,AxisX_Min_Text, AxisX_Min_Loc, FONT_HERSHEY_COMPLEX_SMALL, TextSize, plotTextColor, 1, 8); 447 } 448 449 drawLine(int Xstart,int Xend,int Ystart,int Yend,Scalar lineColor)450 void drawLine(int Xstart, int Xend, int Ystart, int Yend, Scalar lineColor){ 451 452 Point Axis_start; 453 Point Axis_end; 454 Axis_start.x = Xstart; 455 Axis_start.y = Ystart; 456 Axis_end.x = Xend; 457 Axis_end.y = Yend; 458 459 line(plotResult, Axis_start, Axis_end, lineColor, plotLineWidth, 8, 0); 460 } 461 }; 462 create(InputArray _plotData)463 Ptr<Plot2d> Plot2d::create(InputArray _plotData) 464 { 465 return Ptr<Plot2dImpl> (new Plot2dImpl (_plotData)); 466 } 467 create(InputArray _plotDataX,InputArray _plotDataY)468 Ptr<Plot2d> Plot2d::create(InputArray _plotDataX, InputArray _plotDataY) 469 { 470 return Ptr<Plot2dImpl> (new Plot2dImpl (_plotDataX, _plotDataY)); 471 } 472 } 473 } 474