Skip to content

Commit 7344ded

Browse files
committed
Add series, line and scatter plots and new example plot
1 parent 157ea45 commit 7344ded

File tree

5 files changed

+342
-16
lines changed

5 files changed

+342
-16
lines changed

CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,10 @@ TARGET_LINK_LIBRARIES(example ${OpenCV_LIBS} opencvgui ${EXTRA_LIBS} ${GLEW_LIBR
147147
ADD_EXECUTABLE(example1 src/example1.cpp )
148148
TARGET_LINK_LIBRARIES(example1 ${OpenCV_LIBS} opencvgui ${EXTRA_LIBS} ${GLEW_LIBRARIES} ${EXTRA_LIBS_EXE})
149149

150+
ADD_EXECUTABLE(example_2dplot src/example_2dplot.cpp )
151+
TARGET_LINK_LIBRARIES(example_2dplot ${OpenCV_LIBS} opencvgui ${EXTRA_LIBS} ${GLEW_LIBRARIES} ${EXTRA_LIBS_EXE})
152+
153+
150154
ADD_EXECUTABLE(basic_sample src/basic_sample.cpp )
151155
TARGET_LINK_LIBRARIES(basic_sample ${OpenCV_LIBS} opencvgui ${EXTRA_LIBS} ${GLEW_LIBRARIES} ${EXTRA_LIBS_EXE})
152156

include/OpenCVGUI/OGUIPlotArea.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@ using namespace cv;
99
namespace OpenCVGUI {
1010

1111
enum PlotTypes{
12+
PLOT_SERIES,
1213
PLOT_LINE,
13-
PLOT_SCATTER
14+
PLOT_SCATTER,
15+
PLOT_BARS
1416
};
1517

1618
class OGUIPlotArea : public OGUIArea {
@@ -37,6 +39,7 @@ class OGUIPlotArea : public OGUIArea {
3739
void setYScale(bool auto_scale, double min_value, double max_value);
3840
private:
3941
void drawLinePlot();
42+
void drawSeriesPlot();
4043
void drawScatterPlot();
4144
void drawPlot();
4245
Mat data;

src/OpenCVGUI/OGUIPlotArea.cpp

Lines changed: 192 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ namespace OpenCVGUI {
7676
}
7777
}
7878

79-
void OGUIPlotArea::drawLinePlot(){
79+
void OGUIPlotArea::drawSeriesPlot(){
8080
float margin= 120;
8181
float start_x= x+margin/2.0f;
8282
float x_length= data.cols;
@@ -249,6 +249,194 @@ namespace OpenCVGUI {
249249
}
250250
}
251251

252+
void OGUIPlotArea::drawLinePlot(){
253+
float margin= 120;
254+
float start_x= x+margin/2.0f;
255+
float start_y= y+height-margin/2.0f;
256+
257+
float x_length= data.cols;
258+
float dx= (width-margin);
259+
260+
// Extract X and Y separatly
261+
vector<Mat> plot_channels;
262+
split(data, plot_channels);
263+
double min_x=0.0;
264+
double max_x=1.0;
265+
double mx=0;
266+
double min_y=0.0;
267+
double max_y=1.0;
268+
double my=0;
269+
270+
minMaxLoc(plot_channels[0], &min_x, &max_x, NULL, NULL);
271+
mx= (max_x-min_x);
272+
273+
minMaxLoc(plot_channels[1], &min_y, &max_y, NULL, NULL);
274+
my= (max_y-min_y);
275+
276+
float dy= (height-margin);
277+
278+
279+
NVGcontext* vg= (NVGcontext*)(window->vg);
280+
281+
// Plot each graph
282+
for(int p=0; p<data.rows; p++) {
283+
int c=p*3;
284+
NVGcolor color= nvgRGBA(color_scheme.at(c), color_scheme.at(c+1), color_scheme.at(c+2), 255);
285+
nvgBeginPath(vg);
286+
for (int i = 0; i < data.cols; i++) {
287+
Vec2f values= data.at<Vec2f>(p,i);
288+
float p_x=start_x + dx * ((values[0]-min_x) / mx);
289+
float p_y=start_y - dy * ((values[1]-min_y) / my);
290+
if(i==0)
291+
nvgMoveTo(vg, p_x, p_y);
292+
else
293+
nvgLineTo(vg, p_x, p_y);
294+
}
295+
nvgStrokeColor(vg, color);
296+
nvgStrokeWidth(vg, 2.0f);
297+
nvgStroke(vg);
298+
299+
300+
// Dots
301+
for (int i = 0; i < data.cols; i++) {
302+
Vec2f values= data.at<Vec2f>(p,i);
303+
float dot_x=start_x + dx * ((values[0]-min_x) / mx);
304+
float dot_y=start_y - dy * ((values[1]-min_y) / my);
305+
306+
nvgBeginPath(vg);
307+
nvgCircle(vg, dot_x, dot_y, 3.0f);
308+
nvgFillColor(vg, nvgRGBA(220, 220, 220, 255));
309+
nvgFill(vg);
310+
311+
nvgBeginPath(vg);
312+
nvgCircle(vg, dot_x, dot_y, 2.0f);
313+
nvgFillColor(vg, color);
314+
nvgFill(vg);
315+
316+
}
317+
}
318+
319+
nvgResetScissor(vg);
320+
// Plot hover labels
321+
for(int p=0; p<data.rows; p++) {
322+
int c=p*3;
323+
NVGcolor color= nvgRGBA(color_scheme.at(c), color_scheme.at(c+1), color_scheme.at(c+2), 255);
324+
// Dots
325+
for (int i = 0; i < data.cols; i++) {
326+
Vec2f values= data.at<Vec2f>(p,i);
327+
float dot_x=start_x + dx * ((values[0]-min_x) / mx);
328+
float dot_y=start_y - dy * ((values[1]-min_y) / my);
329+
// Draw hover label
330+
if(isMouseIn()) {
331+
if( dot_y-4<= window->mouse_y && window->mouse_y <= dot_y+4 &&
332+
dot_x-4<= window->mouse_x && window->mouse_x <= dot_x+4 ){
333+
334+
// Calculate text width for box
335+
nvgFontSize(vg, 16.0f);
336+
nvgFontFace(vg, "sans");
337+
nvgTextAlign(vg, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE);
338+
stringstream ss_value;
339+
ss_value.precision(4);
340+
ss_value << _labels.at(p) <<": "<< values[0] << ", " << values[1];
341+
float tw = nvgTextBounds(vg, 0, 0, ss_value.str().c_str(), NULL, NULL);
342+
343+
nvgBeginPath(vg);
344+
nvgRect(vg, dot_x-tw-20, dot_y-32, tw+20, 32);
345+
nvgFillColor(vg, nvgRGBA(0, 0, 0, 200));
346+
nvgFill(vg);
347+
348+
// Draw text
349+
nvgFillColor(vg, nvgRGBA(255, 255, 255, 255));
350+
nvgText(vg, dot_x - tw - 10, dot_y - 16, ss_value.str().c_str(), NULL);
351+
}
352+
}
353+
}
354+
}
355+
nvgScissor(vg, x, y, width, height);
356+
357+
///Plot labels box
358+
nvgBeginPath(vg);
359+
nvgRect(vg, x + width - 100-20, y + 40, 120, 15 + data.rows*20);
360+
nvgFillColor(vg, nvgRGBA(0, 0, 0, 100));
361+
nvgFill(vg);
362+
for(int p=0; p<data.rows; p++) {
363+
int c = p * 3;
364+
NVGcolor color = nvgRGBA(color_scheme.at(c), color_scheme.at(c + 1), color_scheme.at(c + 2), 255);
365+
float dot_x=x + width - 100;
366+
float dot_y=y + 60 + p*20;
367+
nvgBeginPath(vg);
368+
nvgCircle(vg, dot_x, dot_y, 4.0f);
369+
nvgFillColor(vg, color);
370+
nvgFill(vg);
371+
372+
// Calculate text width for box
373+
nvgFontSize(vg, 16.0f);
374+
nvgFontFace(vg, "sans");
375+
nvgTextAlign(vg, NVG_ALIGN_LEFT);
376+
// Draw text
377+
nvgFillColor(vg, nvgRGBA(255, 255, 255, 255));
378+
nvgText(vg, dot_x + 10, dot_y+3, _labels.at(p).c_str(), NULL);
379+
}
380+
381+
// X axis
382+
nvgBeginPath(vg);
383+
nvgMoveTo(vg, start_x, start_y);
384+
nvgLineTo(vg, start_x+width-margin, start_y);
385+
nvgStrokeColor(vg, nvgRGBA(255,255,255,255));
386+
nvgStrokeWidth(vg, 1.0f);
387+
nvgStroke(vg);
388+
389+
// Lines x axis coord
390+
for(int i=1; i<=10; i++){
391+
nvgBeginPath(vg);
392+
nvgMoveTo(vg, start_x + (i/10.0f) * dx, start_y);
393+
nvgLineTo(vg, start_x + (i/10.0f) * dx, start_y + 5);
394+
nvgStrokeColor(vg, nvgRGBA(255, 255, 255, 255));
395+
nvgStrokeWidth(vg, 1.0f);
396+
nvgStroke(vg);
397+
398+
// Text label
399+
stringstream ss;
400+
ss << (min_x + i*mx/10);
401+
nvgFontSize(vg, 12.0f);
402+
nvgFontFace(vg, "sans");
403+
float tw = nvgTextBounds(vg, 0, 0, ss.str().c_str(), NULL, NULL);
404+
nvgTextAlign(vg, NVG_ALIGN_CENTER | NVG_ALIGN_MIDDLE);
405+
nvgFillColor(vg, nvgRGBA(255, 255, 255, 255));
406+
nvgText(vg, start_x + (i/10.0f) * dx, start_y + 10, ss.str().c_str(), NULL);
407+
}
408+
409+
// Y axis
410+
nvgBeginPath(vg);
411+
nvgMoveTo(vg, start_x, start_y);
412+
nvgLineTo(vg, start_x, start_y-dy);
413+
nvgStrokeColor(vg, nvgRGBA(255,255,255,255));
414+
nvgStrokeWidth(vg, 1.0f);
415+
nvgStroke(vg);
416+
417+
// Lines y axis coord
418+
for(int i=1; i<=10; i++){
419+
nvgBeginPath(vg);
420+
nvgMoveTo(vg, start_x, start_y-(i/10.0f)*dy);
421+
nvgLineTo(vg, start_x-5, start_y-(i/10.0f)*dy);
422+
nvgStrokeColor(vg, nvgRGBA(255,255,255,255));
423+
nvgStrokeWidth(vg, 1.0f);
424+
nvgStroke(vg);
425+
426+
// Text label
427+
stringstream ss;
428+
ss.precision(2);
429+
ss << (min_y + i*my/10);
430+
nvgFontSize(vg, 12.0f);
431+
nvgFontFace(vg, "sans");
432+
float tw = nvgTextBounds(vg, 0, 0, ss.str().c_str(), NULL, NULL);
433+
nvgTextAlign(vg, NVG_ALIGN_RIGHT | NVG_ALIGN_MIDDLE);
434+
nvgFillColor(vg, nvgRGBA(255, 255, 255, 255));
435+
nvgText(vg, start_x-10, start_y-(i/10.0f)*dy, ss.str().c_str(), NULL);
436+
}
437+
438+
}
439+
252440
void OGUIPlotArea::drawScatterPlot(){
253441
float margin= 120;
254442
float start_x= x+margin/2.0f;
@@ -426,6 +614,9 @@ namespace OpenCVGUI {
426614
void OGUIPlotArea::drawPlot() {
427615

428616
switch (_plot_type){
617+
case PLOT_SERIES:
618+
drawSeriesPlot();
619+
break;
429620
case PLOT_LINE:
430621
drawLinePlot();
431622
break;

src/example1.cpp

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,6 @@ void hello_btn_click(){
3939

4040
void cv_process() {
4141

42-
Mat scatter_data(4,20,CV_32FC2);
43-
for(int s=0; s<4; s++){
44-
float x_mean= 0.5-(rand()%100)/100.0f;
45-
float y_mean= 0.5-(rand()%100)/100.0f;
46-
for(int p=0; p<20; p++){
47-
scatter_data.at<Vec2f>(s,p)[0]= x_mean + (50-(rand()%100))/1000.0f;
48-
scatter_data.at<Vec2f>(s,p)[1]= y_mean + (50-(rand()%100))/1000.0f;
49-
}
50-
}
51-
5242
while(app_is_running) {
5343
cap >> frame;
5444
window->imshow("camera", &frame);
@@ -57,10 +47,7 @@ void cv_process() {
5747
cvtColor(frame, g_data, CV_BGR2GRAY);
5848
g_data.convertTo(data, CV_32F, 1/255.0);
5949
resize(data, data, Size(50,10));
60-
window->plot2D("2D plot", &data, {"g1","g2","g3","g4","g5","g6","g7","g8","g9", "g10"}, 1, OpenCVGUI::PLOT_LINE);
61-
62-
// 20 data 4 series (each channel is x and y)
63-
window->plot2D("2D plot Scatter", &scatter_data, {"g1","g2","g3","g4"}, 1, OpenCVGUI::PLOT_SCATTER);
50+
window->plot2D("2D plot Series", &data, {"g1","g2","g3","g4","g5","g6","g7","g8","g9", "g10"}, 1, OpenCVGUI::PLOT_SERIES);
6451

6552
if(sayHello) {
6653
window->popup("Hello World", "Hello to OpenCV GUI Sample", POPUP_ALERT);

0 commit comments

Comments
 (0)