forked from spmallick/learnopencv
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcvui.h
2001 lines (1579 loc) · 79.4 KB
/
cvui.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
A (very) simple UI lib built on top of OpenCV drawing primitives.
Version: 2.0.0
Copyright (c) 2016 Fernando Bevilacqua <dovyski@gmail.com>
Licensed under the MIT license.
*/
#ifndef _CVUI_H_
#define _CVUI_H_
#include <iostream>
#include <stdarg.h>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>
namespace cvui
{
/**
Initializes the library. You must provide the name of the window where
the components will be added. It is also possible to tell cvui to handle
OpenCV's event queue automatically (by informing a value greater than zero
in the `theDelayWaitKey` parameter of function). In that case, cvui will
automatically call `cv::waitKey()` within `cvui::update()`, so you don't
have to worry about it. The value passed to `theDelayWaitKey` will be
used as the delay for `cv::waitKey()`.
\param theWindowName name of the window where the components will be added
\param theDelayWaitKey delay value passed to `cv::waitKey()`. If a negative value is informed (default is `-1`), cvui will not automatically call `cv::waitKey()` within `cvui::update()`, which will disable keyboard shortcuts for all components. If you want to enable keyboard shortcut for components (e.g. using & in a button label), you must specify a positive value for this param.
*/
void init(const cv::String& theWindowName, int theDelayWaitKey = -1);
/**
Return the last key that was pressed. This function will only
work if a value greater than zero was passed to `cvui::init()`
as the delay waitkey parameter.
\sa init()
*/
int lastKeyPressed();
/**
Display a button. The size of the button will be automatically adjusted to
properly house the label content.
\param theWhere the image/frame where the component should be rendered.
\param theX position X where the component should be placed.
\param theY position Y where the component should be placed.
\param theLabel text displayed inside the button.
\return `true` everytime the user clicks the button.
*/
bool button(cv::Mat& theWhere, int theX, int theY, const cv::String& theLabel);
/**
Display a button. The button size will be defined by the width and height parameters,
no matter the content of the label.
\param theWhere the image/frame where the component should be rendered.
\param theX position X where the component should be placed.
\param theY position Y where the component should be placed.
\param theWidth width of the button.
\param theHeight height of the button.
\param theLabel text displayed inside the button.
\return `true` everytime the user clicks the button.
*/
bool button(cv::Mat& theWhere, int theX, int theY, int theWidth, int theHeight, const cv::String& theLabel);
/**
Display a button whose graphics are images (cv::Mat). The button accepts three images to describe its states,
which are idle (no mouse interaction), over (mouse is over the button) and down (mouse clicked the button).
The button size will be defined by the width and height of the images.
\param theWhere the image/frame where the component should be rendered.
\param theX position X where the component should be placed.
\param theY position Y where the component should be placed.
\param theIdle an image that will be rendered when the button is not interacting with the mouse cursor.
\param theOver an image that will be rendered when the mouse cursor is over the button.
\param theDown an image that will be rendered when the mouse cursor clicked the button (or is clicking).
\return `true` everytime the user clicks the button.
\sa button()
\sa image()
\sa iarea()
*/
bool button(cv::Mat& theWhere, int theX, int theY, cv::Mat& theIdle, cv::Mat& theOver, cv::Mat& theDown);
/**
Display an image (cv::Mat).
\param theWhere the image/frame where the provded image should be rendered.
\param theX position X where the image should be placed.
\param theY position Y where the image should be placed.
\param theImage an image to be rendered in the specified destination.
\sa button()
\sa iarea()
*/
void image(cv::Mat& theWhere, int theX, int theY, cv::Mat& theImage);
/**
Display a checkbox. You can use the state parameter to monitor if the
checkbox is checked or not.
\param theWhere the image/frame where the component should be rendered.
\param theX position X where the component should be placed.
\param theY position Y where the component should be placed.
\param theLabel text displayed besides the clickable checkbox square.
\param theState describes the current state of the checkbox: `true` means the checkbox is checked.
\param theColor color of the label in the format `0xRRGGBB`, e.g. `0xff0000` for red.
\return a boolean value that indicates the current state of the checkbox, `true` if it is checked.
*/
bool checkbox(cv::Mat& theWhere, int theX, int theY, const cv::String& theLabel, bool *theState, unsigned int theColor = 0xCECECE);
/**
Display a piece of text.
\param theWhere the image/frame where the component should be rendered.
\param theX position X where the component should be placed.
\param theY position Y where the component should be placed.
\param theText the text content.
\param theFontScale size of the text.
\param theColor color of the text in the format `0xRRGGBB`, e.g. `0xff0000` for red.
\sa printf()
*/
void text(cv::Mat& theWhere, int theX, int theY, const cv::String& theText, double theFontScale = 0.4, unsigned int theColor = 0xCECECE);
/**
Display a piece of text that can be formated using `stdio's printf()` style. For instance
if you want to display text mixed with numbers, you can use:
```
printf(frame, 10, 15, 0.4, 0xff0000, "Text: %d and %f", 7, 3.1415);
```
\param theWhere the image/frame where the component should be rendered.
\param theX position X where the component should be placed.
\param theY position Y where the component should be placed.
\param theFontScale size of the text.
\param theColor color of the text in the format `0xRRGGBB`, e.g. `0xff0000` for red.
\param theFmt formating string as it would be supplied for `stdio's printf()`, e.g. `"Text: %d and %f", 7, 3.1415`.
\sa text()
*/
void printf(cv::Mat& theWhere, int theX, int theY, double theFontScale, unsigned int theColor, const char *theFmt, ...);
/**
Display a piece of text that can be formated using `stdio's printf()` style. For instance
if you want to display text mixed with numbers, you can use:
```
printf(frame, 10, 15, 0.4, 0xff0000, "Text: %d and %f", 7, 3.1415);
```
The size and color of the text will be based on cvui's default values.
\param theWhere the image/frame where the component should be rendered.
\param theX position X where the component should be placed.
\param theY position Y where the component should be placed.
\param theFmt formating string as it would be supplied for `stdio's printf()`, e.g. `"Text: %d and %f", 7, 3.1415`.
\sa text()
*/
void printf(cv::Mat& theWhere, int theX, int theY, const char *theFmt, ...);
/**
Display a counter for integer values that the user can increase/descrease
by clicking the up and down arrows.
\param theWhere the image/frame where the component should be rendered.
\param theX position X where the component should be placed.
\param theY position Y where the component should be placed.
\param theValue the current value of the counter.
\param theStep the amount that should be increased/decreased when the user interacts with the counter buttons
\param theFormat how the value of the counter should be presented, as it was printed by `stdio's printf()`. E.g. `"%d"` means the value will be displayed as an integer, `"%0d"` integer with one leading zero, etc.
\return an integer that corresponds to the current value of the counter.
*/
int counter(cv::Mat& theWhere, int theX, int theY, int *theValue, int theStep = 1, const char *theFormat = "%d");
/**
Display a counter for float values that the user can increase/descrease
by clicking the up and down arrows.
\param theWhere the image/frame where the component should be rendered.
\param theX position X where the component should be placed.
\param theY position Y where the component should be placed.
\param theValue the current value of the counter.
\param theStep the amount that should be increased/decreased when the user interacts with the counter buttons
\param theFormat how the value of the counter should be presented, as it was printed by `stdio's printf()`. E.g. `"%f"` means the value will be displayed as a regular float, `"%.2f"` float with two digits after the point, etc.
\return a float that corresponds to the current value of the counter.
*/
double counter(cv::Mat& theWhere, int theX, int theY, double *theValue, double theStep = 0.5, const char *theFormat = "%.2f");
/**
Display a trackbar for numeric values that the user can increase/decrease
by clicking and/or dragging the marker right or left. This component uses templates
so it is imperative that you make it very explicit the type of `theValue`, `theMin`, `theMax` and `theStep`,
otherwise you might end up with weird compilation errors.
Example:
```
// using double
trackbar(where, x, y, width, &doubleValue, 0.0, 50.0);
// using float
trackbar(where, x, y, width, &floatValue, 0.0f, 50.0f);
// using char
trackbar(where, x, y, width, &charValue, (char)1, (char)10);
```
\param theWhere the image/frame where the component should be rendered.
\param theX position X where the component should be placed.
\param theY position Y where the component should be placed.
\param theWidth the width of the trackbar.
\param theValue the current value of the trackbar. It will be modified when the user interacts with the trackbar. Any numeric type can be used, e.g. float, double, long double, int, char, uchar.
\param theMin the minimum value allowed for the trackbar.
\param theMax the maximum value allowed for the trackbar.
\param theSegments number of segments the trackbar will have (default is 1). Segments can be seen as groups of numbers in the scale of the trackbar. For example, 1 segment means a single groups of values (no extra labels along the scale), 2 segments mean the trackbar values will be divided in two groups and a label will be placed at the middle of the scale.
\param theLabelFormat formating string that will be used to render the labels, e.g. `%.2Lf` (Lf *not lf). No matter the type of the `theValue` param, internally trackbar stores it as a `long double`, so the formating string will *always* receive a `long double` value to format. If you are using a trackbar with integers values, for instance, you can supress decimals using a formating string such as `%.0Lf` to format your labels.
\param theOptions options to customize the behavior/appearance of the trackbar, expressed as a bitset. Available options are defined as `TRACKBAR_` constants and they can be combined using the bitwise `|` operand. Available options are: `TRACKBAR_HIDE_SEGMENT_LABELS` (do not render segment labels, but do render min/max labels), `TRACKBAR_HIDE_STEP_SCALE` (do not render the small lines indicating values in the scale), `TRACKBAR_DISCRETE` (changes of the trackbar value are multiples of theDiscreteStep param), `TRACKBAR_HIDE_MIN_MAX_LABELS` (do not render min/max labels), `TRACKBAR_HIDE_VALUE_LABEL` (do not render the current value of the trackbar below the moving marker), `TRACKBAR_HIDE_LABELS` (do not render labels at all).
\param theDiscreteStep the amount that the trackbar marker will increase/decrease when the marker is dragged right/left (if option TRACKBAR_DISCRETE is ON)
\return `true` when the value of the trackbar changed.
\sa counter()
*/
template <typename T>
bool trackbar(cv::Mat& theWhere, int theX, int theY, int theWidth, T *theValue, T theMin, T theMax, int theSegments = 1, const char *theLabelFormat = "%.1Lf", unsigned int theOptions = 0, T theDiscreteStep = 1);
/**
Display a window (a block with a title and a body).
\param theWhere the image/frame where the component should be rendered.
\param theX position X where the component should be placed.
\param theY position Y where the component should be placed.
\param theWidth width of the window.
\param theHeight height of the window.
\param theTitle text displayed as the title of the window.
\sa rect()
*/
void window(cv::Mat& theWhere, int theX, int theY, int theWidth, int theHeight, const cv::String& theTitle);
/**
Display a filled rectangle.
\param theWhere the image/frame where the component should be rendered.
\param theX position X where the component should be placed.
\param theY position Y where the component should be placed.
\param theWidth width of the rectangle.
\param theHeight height of the rectangle.
\param theBorderColor color of rectangle's border in the format `0xRRGGBB`, e.g. `0xff0000` for red.
\param theFillingColor color of rectangle's filling in the format `0xAARRGGBB`, e.g. `0x00ff0000` for red, `0xff000000` for transparent filling.
\sa image()
*/
void rect(cv::Mat& theWhere, int theX, int theY, int theWidth, int theHeight, unsigned int theBorderColor, unsigned int theFillingColor = 0xff000000);
/**
Display the values of a vector as a sparkline.
\param theWhere the image/frame where the component should be rendered.
\param theValues a vector containing the values to be used in the sparkline.
\param theX position X where the component should be placed.
\param theY position Y where the component should be placed.
\param theWidth width of the sparkline.
\param theHeight height of the sparkline.
\param theColor color of sparkline in the format `0xRRGGBB`, e.g. `0xff0000` for red.
\sa trackbar()
*/
void sparkline(cv::Mat& theWhere, std::vector<double>& theValues, int theX, int theY, int theWidth, int theHeight, unsigned int theColor = 0x00FF00);
/**
Create an interaction area that reports activity with the mouse cursor.
The tracked interactions are returned by the function and they are:
`OUT` when the cursor is not over the iarea.
`OVER` when the cursor is over the iarea.
`DOWN` when the cursor is pressed over the iarea, but not released yet.
`CLICK` when the cursor clicked (pressed and released) within the iarea.
This function creates no visual output on the screen. It is intended to
be used as an auxiliary tool to create interactions.
\param theX position X where the interactive area should be placed.
\param theY position Y where the interactive area should be placed.
\param theWidth width of the interactive area.
\param theHeight height of the interactive area.
\return an integer value representing the current state of interaction with the mouse cursor. It can be `OUT` (cursor is not over the area), `OVER` (cursor is over the area), `DOWN` (cursor is pressed over the area, but not released yet) and `CLICK` (cursor clicked, i.e. pressed and released, within the area).
\sa button()
\sa image()
*/
int iarea(int theX, int theY, int theWidth, int theHeight);
/**
Start a new row.
One of the most annoying tasks when building UI is to calculate
where each component should be placed on the screen. cvui has
a set of methods that abstract the process of positioning
components, so you don't have to think about assigning a
X and Y coordinate. Instead you just add components and cvui
will place them as you go.
You use `beginRow()` to start a group of elements. After `beginRow()`
has been called, all subsequent component calls don't have to specify
the frame where the component should be rendered nor its position.
The position of the component will be automatically calculated by cvui
based on the components within the group. All components are placed
side by side, from left to right.
E.g.
```
beginRow(frame, x, y, width, height);
text("test");
button("btn");
endRow();
```
Rows and columns can be nested, so you can create columns/rows within
columns/rows as much as you want. It's important to notice that any
component within `beginRow()` and `endRow()` *do not* specify the position
where the component is rendered, which is also true for `beginRow()`.
As a consequence, **be sure you are calling `beginRow(width, height)`
when the call is nested instead of `beginRow(x, y, width, height)`**,
otherwise cvui will throw an error.
E.g.
```
beginRow(frame, x, y, width, height);
text("test");
button("btn");
beginColumn(); // no frame nor x,y parameters here!
text("column1");
text("column2");
endColumn();
endRow();
```
Don't forget to call `endRow()` to finish the row, otherwise cvui will throw an error.
\param theWhere the image/frame where the components within this block should be rendered.
\param theX position X where the row should be placed.
\param theY position Y where the row should be placed.
\param theWidth width of the row. If a negative value is specified, the width of the row will be automatically calculated based on the content of the block.
\param theHeight height of the row. If a negative value is specified, the height of the row will be automatically calculated based on the content of the block.
\param thePadding space, in pixels, among the components of the block.
\sa beginColumn()
\sa endRow()
\sa endColumn()
*/
void beginRow(cv::Mat &theWhere, int theX, int theY, int theWidth = -1, int theHeight = -1, int thePadding = 0);
/**
Ends a row. You must call this function only if you have previously called
its counter part, the `beginRow()` function.
\sa beginRow()
\sa beginColumn()
\sa endColumn()
*/
void endRow();
/**
Start a new column.
One of the most annoying tasks when building UI is to calculate
where each component should be placed on the screen. cvui has
a set of methods that abstract the process of positioning
components, so you don't have to think about assigning a
X and Y coordinate. Instead you just add components and cvui
will place them as you go.
You use `beginColumn()` to start a group of elements. After `beginColumn()`
has been called, all subsequent component calls don't have to specify
the frame where the component should be rendered nor its position.
The position of the component will be automatically calculated by cvui
based on the components within the group. All components are placed
below each other, from the top of the screen towards the bottom.
E.g.
```
beginColumn(frame, x, y, width, height);
text("test");
button("btn");
endColumn();
```
Rows and columns can be nested, so you can create columns/rows within
columns/rows as much as you want. It's important to notice that any
component within `beginColumn()` and `endColumn()` *do not* specify the position
where the component is rendered, which is also true for `beginColumn()`.
As a consequence, **be sure you are calling `beginColumn(width, height)`
when the call is nested instead of `beginColumn(x, y, width, height)`**,
otherwise cvui will throw an error.
E.g.
```
beginColumn(frame, x, y, width, height);
text("test");
button("btn");
beginRow(); // no frame nor x,y parameters here!
text("column1");
text("column2");
endRow();
endColumn();
```
Don't forget to call `endColumn()` to finish the column, otherwise cvui will throw an error.
\param theWhere the image/frame where the components within this block should be rendered.
\param theX position X where the row should be placed.
\param theY position Y where the row should be placed.
\param theWidth width of the column. If a negative value is specified, the width of the column will be automatically calculated based on the content of the block.
\param theHeight height of the column. If a negative value is specified, the height of the column will be automatically calculated based on the content of the block.
\param thePadding space, in pixels, among the components of the block.
\sa beginRow()
\sa endColumn()
\sa endRow()
*/
void beginColumn(cv::Mat &theWhere, int theX, int theY, int theWidth = -1, int theHeight = -1, int thePadding = 0);
/**
Ends a column. You must call this function only if you have previously called
its counter part, the `beginColumn()` function.
\sa beginColumn()
\sa beginRow()
\sa endRow()
*/
void endColumn();
/**
Starts a row. This function behaves in the same way as `beginRow(frame, x, y, width, height)`,
however it is suposed to be used within `begin*()/end*()` blocks since they require components
not to inform frame nor x,y coordinates.
\sa beginColumn()
\sa endRow()
\sa endColumn()
*/
void beginRow(int theWidth = -1, int theHeight = -1, int thePadding = 0);
/**
Starts a column. This function behaves in the same way as `beginColumn(frame, x, y, width, height)`,
however it is suposed to be used within `begin*()/end*()` blocks since they require components
not to inform frame nor x,y coordinates.
\sa beginColumn()
\sa endRow()
\sa endColumn()
*/
void beginColumn(int theWidth = -1, int theHeight = -1, int thePadding = 0);
/**
Adds an arbitrary amount of space between components within a `begin*()` and `end*()` block.
The function is aware of context, so if it is used within a `beginColumn()` and
`endColumn()` block, the space will be vertical. If it is used within a `beginRow()`
and `endRow()` block, space will be horizontal.
IMPORTANT: this function can only be used within a `begin*()/end*()` block, otherwise it does nothing.
\param theValue the amount of space to be added.
\sa beginColumn()
\sa beginRow()
\sa endRow()
\sa endColumn()
*/
void space(int theValue = 5);
/**
Display a piece of text within a `begin*()` and `end*()` block.
IMPORTANT: this function can only be used within a `begin*()/end*()` block, otherwise it does nothing.
\param theText the text content.
\param theFontScale size of the text.
\param theColor color of the text in the format `0xRRGGBB`, e.g. `0xff0000` for red.
\sa printf()
\sa beginColumn()
\sa beginRow()
\sa endRow()
\sa endColumn()
*/
void text(const cv::String& theText, double theFontScale = 0.4, unsigned int theColor = 0xCECECE);
//
/**
Display a button within a `begin*()` and `end*()` block.
The button size will be defined by the width and height parameters,
no matter the content of the label.
IMPORTANT: this function can only be used within a `begin*()/end*()` block, otherwise it does nothing.
\param theWidth width of the button.
\param theHeight height of the button.
\param theLabel text displayed inside the button. You can set shortcuts by pre-pending them with "&"
\return `true` everytime the user clicks the button.
\sa beginColumn()
\sa beginRow()
\sa endRow()
\sa endColumn()
*/
bool button(int theWidth, int theHeight, const cv::String& theLabel);
/**
Display a button within a `begin*()` and `end*()` block. The size of the button will be
automatically adjusted to properly house the label content.
IMPORTANT: this function can only be used within a `begin*()/end*()` block, otherwise it does nothing.
\param theLabel text displayed inside the button. You can set shortcuts by pre-pending them with "&"
\return `true` everytime the user clicks the button.
\sa beginColumn()
\sa beginRow()
\sa endRow()
\sa endColumn()
*/
bool button(const cv::String& theLabel);
/**
Display a button whose graphics are images (cv::Mat).
IMPORTANT: this function can only be used within a `begin*()/end*()` block, otherwise it does nothing.
The button accepts three images to describe its states,
which are idle (no mouse interaction), over (mouse is over the button) and down (mouse clicked the button).
The button size will be defined by the width and height of the images.
\param theIdle an image that will be rendered when the button is not interacting with the mouse cursor.
\param theOver an image that will be rendered when the mouse cursor is over the button.
\param theDown an image that will be rendered when the mouse cursor clicked the button (or is clicking).
\return `true` everytime the user clicks the button.
\sa button()
\sa image()
\sa iarea()
\sa beginColumn()
\sa beginRow()
\sa endRow()
\sa endColumn()
*/
bool button(cv::Mat& theIdle, cv::Mat& theOver, cv::Mat& theDown);
/**
Display an image (cv::Mat) within a `begin*()` and `end*()` block
IMPORTANT: this function can only be used within a `begin*()/end*()` block, otherwise it does nothing.
\param theWhere the image/frame where the provded image should be rendered.
\param theX position X where the image should be placed.
\param theY position Y where the image should be placed.
\param theImage an image to be rendered in the specified destination.
\sa button()
\sa iarea()
\sa beginColumn()
\sa beginRow()
\sa endRow()
\sa endColumn()
*/
void image(cv::Mat& theImage);
/**
Display a checkbox within a `begin*()` and `end*()` block. You can use the state parameter
to monitor if the checkbox is checked or not.
IMPORTANT: this function can only be used within a `begin*()/end*()` block, otherwise it does nothing.
\param theLabel text displayed besides the clickable checkbox square.
\param theState describes the current state of the checkbox: `true` means the checkbox is checked.
\param theColor color of the label in the format `0xRRGGBB`, e.g. `0xff0000` for red.
\return a boolean value that indicates the current state of the checkbox, `true` if it is checked.
\sa beginColumn()
\sa beginRow()
\sa endRow()
\sa endColumn()
*/
bool checkbox(const cv::String& theLabel, bool *theState, unsigned int theColor = 0xCECECE);
/**
Display a piece of text within a `begin*()` and `end*()` block.
IMPORTANT: this function can only be used within a `begin*()/end*()` block, otherwise it does nothing.
The text can be formated using `stdio's printf()` style. For instance if you want to display text mixed
with numbers, you can use:
```
printf(0.4, 0xff0000, "Text: %d and %f", 7, 3.1415);
```
\param theFontScale size of the text.
\param theColor color of the text in the format `0xRRGGBB`, e.g. `0xff0000` for red.
\param theFmt formating string as it would be supplied for `stdio's printf()`, e.g. `"Text: %d and %f", 7, 3.1415`.
\sa text()
\sa beginColumn()
\sa beginRow()
\sa endRow()
\sa endColumn()
*/
void printf(double theFontScale, unsigned int theColor, const char *theFmt, ...);
/**
Display a piece of text that can be formated using `stdio's printf()` style.
IMPORTANT: this function can only be used within a `begin*()/end*()` block, otherwise it does nothing.
For instance if you want to display text mixed with numbers, you can use:
```
printf(frame, 10, 15, 0.4, 0xff0000, "Text: %d and %f", 7, 3.1415);
```
The size and color of the text will be based on cvui's default values.
\param theFmt formating string as it would be supplied for `stdio's printf()`, e.g. `"Text: %d and %f", 7, 3.1415`.
\sa text()
\sa beginColumn()
\sa beginRow()
\sa endRow()
\sa endColumn()
*/
void printf(const char *theFmt, ...);
/**
Display a counter for integer values that the user can increase/descrease
by clicking the up and down arrows.
IMPORTANT: this function can only be used within a `begin*()/end*()` block, otherwise it does nothing.
\param theValue the current value of the counter.
\param theStep the amount that should be increased/decreased when the user interacts with the counter buttons.
\param theFormat how the value of the counter should be presented, as it was printed by `stdio's printf()`. E.g. `"%d"` means the value will be displayed as an integer, `"%0d"` integer with one leading zero, etc.
\return an integer that corresponds to the current value of the counter.
\sa printf()
\sa beginColumn()
\sa beginRow()
\sa endRow()
\sa endColumn()
*/
int counter(int *theValue, int theStep = 1, const char *theFormat = "%d");
/**
Display a counter for float values that the user can increase/descrease
by clicking the up and down arrows.
IMPORTANT: this function can only be used within a `begin*()/end*()` block, otherwise it does nothing.
\param theValue the current value of the counter.
\param theStep the amount that should be increased/decreased when the user interacts with the counter buttons.
\param theFormat how the value of the counter should be presented, as it was printed by `stdio's printf()`. E.g. `"%d"` means the value will be displayed as an integer, `"%0d"` integer with one leading zero, etc.
\return an float that corresponds to the current value of the counter.
\sa printf()
\sa beginColumn()
\sa beginRow()
\sa endRow()
\sa endColumn()
*/
double counter(double *theValue, double theStep = 0.5, const char *theFormat = "%.2f");
/**
Display a trackbar for numeric values that the user can increase/decrease
by clicking and/or dragging the marker right or left.
IMPORTANT: this function can only be used within a `begin*()/end*()` block, otherwise it does nothing.
This component uses templates so it is imperative that you make it very explicit
the type of `theValue`, `theMin`, `theMax` and `theStep`, otherwise you might end up with
weird compilation errors.
Example:
```
// using double
trackbar(width, &doubleValue, 0.0, 50.0);
// using float
trackbar(width, &floatValue, 0.0f, 50.0f);
// using char
trackbar(width, &charValue, (char)1, (char)10);
```
\param theWidth the width of the trackbar.
\param theValue the current value of the trackbar. It will be modified when the user interacts with the trackbar. Any numeric type can be used, e.g. float, double, long double, int, char, uchar.
\param theMin the minimum value allowed for the trackbar.
\param theMax the maximum value allowed for the trackbar.
\param theSegments number of segments the trackbar will have (default is 1). Segments can be seen as groups of numbers in the scale of the trackbar. For example, 1 segment means a single groups of values (no extra labels along the scale), 2 segments mean the trackbar values will be divided in two groups and a label will be placed at the middle of the scale.
\param theLabelFormat formating string that will be used to render the labels, e.g. `%.2Lf`. No matter the type of the `theValue` param, internally trackbar stores it as a `long double`, so the formating string will *always* receive a `long double` value to format. If you are using a trackbar with integers values, for instance, you can supress decimals using a formating string as `%.0Lf` to format your labels.
\param theOptions options to customize the behavior/appearance of the trackbar, expressed as a bitset. Available options are defined as `TRACKBAR_` constants and they can be combined using the bitwise `|` operand. Available options are: `TRACKBAR_HIDE_SEGMENT_LABELS` (do not render segment labels, but do render min/max labels), `TRACKBAR_HIDE_STEP_SCALE` (do not render the small lines indicating values in the scale), `TRACKBAR_DISCRETE` (changes of the trackbar value are multiples of informed step param), `TRACKBAR_HIDE_MIN_MAX_LABELS` (do not render min/max labels), `TRACKBAR_HIDE_VALUE_LABEL` (do not render the current value of the trackbar below the moving marker), `TRACKBAR_HIDE_LABELS` (do not render labels at all).
\param theDiscreteStep the amount that the trackbar marker will increase/decrease when the marker is dragged right/left (if option TRACKBAR_DISCRETE is ON)
\return `true` when the value of the trackbar changed.
\sa counter()
\sa beginColumn()
\sa beginRow()
\sa endRow()
\sa endColumn()
*/
template <typename T> // T can be any float type (float, double, long double)
bool trackbar(int theWidth, T *theValue, T theMin, T theMax, int theSegments = 1, const char *theLabelFormat = "%.1Lf", unsigned int theOptions = 0, T theDiscreteStep = 1);
/**
Display a window (a block with a title and a body) within a `begin*()` and `end*()` block.
IMPORTANT: this function can only be used within a `begin*()/end*()` block, otherwise it does nothing.
\param theWidth width of the window.
\param theHeight height of the window.
\param theTitle text displayed as the title of the window.
\sa rect()
\sa beginColumn()
\sa beginRow()
\sa endRow()
\sa endColumn()
*/
void window(int theWidth, int theHeight, const cv::String& theTitle);
/**
Display a rectangle within a `begin*()` and `end*()` block.
IMPORTANT: this function can only be used within a `begin*()/end*()` block, otherwise it does nothing.
\param theWidth width of the rectangle.
\param theHeight height of the rectangle.
\param theBorderColor color of rectangle's border in the format `0xRRGGBB`, e.g. `0xff0000` for red.
\param theFillingColor color of rectangle's filling in the format `0xAARRGGBB`, e.g. `0x00ff0000` for red, `0xff000000` for transparent filling.
\sa window()
\sa beginColumn()
\sa beginRow()
\sa endRow()
\sa endColumn()
*/
void rect(int theWidth, int theHeight, unsigned int theBorderColor, unsigned int theFillingColor = 0xff000000);
/**
Display the values of a vector as a sparkline within a `begin*()` and `end*()` block.
IMPORTANT: this function can only be used within a `begin*()/end*()` block, otherwise it does nothing.
\param theValues vector with the values that will be rendered as a sparkline.
\param theWidth width of the sparkline.
\param theHeight height of the sparkline.
\param theColor color of sparkline in the format `0xRRGGBB`, e.g. `0xff0000` for red.
\sa beginColumn()
\sa beginRow()
\sa endRow()
\sa endColumn()
*/
void sparkline(std::vector<double>& theValues, int theWidth, int theHeight, unsigned int theColor = 0x00FF00);
/**
Updates the library internal things. You need to call this function **AFTER** you are done adding/manipulating
UI elements in order for them to react to mouse interactions.
*/
void update();
// Internally used to handle mouse events
void handleMouse(int theEvent, int theX, int theY, int theFlags, void* theData);
// Compatibility macros to allow compilation with either OpenCV 2.x or OpenCV 3.x
#if (CV_MAJOR_VERSION < 3)
#define CVUI_ANTIALISED CV_AA
#else
#define CVUI_ANTIALISED cv::LINE_AA
#endif
#define CVUI_FILLED -1
// Check for Windows-specific functions and react accordingly
#if !defined(_MSC_VER)
#define vsprintf_s vsprintf
#define sprintf_s sprintf
#endif
// Check for Unix stuff
#ifdef __GNUC__
// just to remove the warning under gcc that is introduced by the VERSION variable below
// (needed for those who compile with -Werror (make warning as errors)
#pragma GCC diagnostic ignored "-Wunused-variable"
#endif
// Lib version
static const char *VERSION = "2.0.0";
const int ROW = 0;
const int COLUMN = 1;
const int DOWN = 2;
const int CLICK = 3;
const int OVER = 4;
const int OUT = 5;
// Constants regarding components
const unsigned int TRACKBAR_HIDE_SEGMENT_LABELS = 1;
const unsigned int TRACKBAR_HIDE_STEP_SCALE = 2;
const unsigned int TRACKBAR_DISCRETE = 4;
const unsigned int TRACKBAR_HIDE_MIN_MAX_LABELS = 8;
const unsigned int TRACKBAR_HIDE_VALUE_LABEL = 16;
const unsigned int TRACKBAR_HIDE_LABELS = 32;
// Describes the block structure used by the lib to handle `begin*()` and `end*()` calls.
typedef struct {
cv::Mat where; // where the block should be rendered to.
cv::Rect rect; // the size and position of the block.
cv::Rect fill; // the filled area occuppied by the block as it gets modified by its inner components.
cv::Point anchor; // the point where the next component of the block should be rendered.
int padding; // padding among components within this block.
int type; // type of the block, e.g. ROW or COLUMN.
} cvui_block_t;
// Describes a component label, including info about a shortcut.
// If a label contains "Re&start", then:
// - hasShortcut will be true
// - shortcut will be 's'
// - textBeforeShortcut will be "Re"
// - textAfterShortcut will be "tart"
typedef struct {
bool hasShortcut;
char shortcut;
std::string textBeforeShortcut;
std::string textAfterShortcut;
} cvui_label_t;
// Internal namespace with all code that is shared among components/functions.
// You should probably not be using anything from here.
namespace internal
{
// Variables to keep track of mouse events and stuff
static bool gMouseJustReleased = false;
static bool gMousePressed = false;
static cv::Point gMouse;
static char gBuffer[1024];
static int gLastKeyPressed;
static int gDelayWaitKey;
static cvui_block_t gScreen;
struct TrackbarParams {
long double min;
long double max;
long double step;
int segments;
unsigned int options;
std::string labelFormat;
inline TrackbarParams()
: min(0.)
, max(25.)
, step(1.)
, segments(0)
, options(0)
, labelFormat("%.0Lf")
{}
};
static cvui_block_t gStack[100]; // TODO: make it dynamic?
static int gStackCount = -1;
static const int gTrackbarMarginX = 14;
bool bitsetHas(unsigned int theBitset, unsigned int theValue);
void error(int theId, std::string theMessage);
void updateLayoutFlow(cvui_block_t& theBlock, cv::Size theSize);
bool blockStackEmpty();
cvui_block_t& topBlock();
cvui_block_t& pushBlock();
cvui_block_t& popBlock();
void begin(int theType, cv::Mat &theWhere, int theX, int theY, int theWidth, int theHeight, int thePadding);
void end(int theType);
cvui_label_t createLabel(const std::string &theLabel);
int iarea(int theX, int theY, int theWidth, int theHeight);
bool button(cvui_block_t& theBlock, int theX, int theY, int theWidth, int theHeight, const cv::String& theLabel, bool theUpdateLayout);
bool button(cvui_block_t& theBlock, int theX, int theY, const cv::String& theLabel);
bool button(cvui_block_t& theBlock, int theX, int theY, cv::Mat& theIdle, cv::Mat& theOver, cv::Mat& theDown, bool theUpdateLayout);
void image(cvui_block_t& theBlock, int theX, int theY, cv::Mat& theImage);
bool checkbox(cvui_block_t& theBlock, int theX, int theY, const cv::String& theLabel, bool *theState, unsigned int theColor);
void text(cvui_block_t& theBlock, int theX, int theY, const cv::String& theText, double theFontScale, unsigned int theColor, bool theUpdateLayout);
int counter(cvui_block_t& theBlock, int theX, int theY, int *theValue, int theStep, const char *theFormat);
double counter(cvui_block_t& theBlock, int theX, int theY, double *theValue, double theStep, const char *theFormat);
void window(cvui_block_t& theBlock, int theX, int theY, int theWidth, int theHeight, const cv::String& theTitle);
void rect(cvui_block_t& theBlock, int theX, int theY, int theWidth, int theHeight, unsigned int theBorderColor, unsigned int theFillingColor);
void sparkline(cvui_block_t& theBlock, std::vector<double>& theValues, int theX, int theY, int theWidth, int theHeight, unsigned int theColor);
bool trackbar(cvui_block_t &theBlock, int theX, int theY, int theWidth, long double *theValue, const TrackbarParams& theParams);
inline void trackbarForceValuesAsMultiplesOfSmallStep(const TrackbarParams & theParams, long double *theValue);
inline long double trackbarXPixelToValue(const TrackbarParams & theParams, cv::Rect & theBounding, int thePixelX);
inline int trackbarValueToXPixel(const TrackbarParams & theParams, cv::Rect & theBounding, long double theValue);
inline double clamp01(double value);
void findMinMax(std::vector<double>& theValues, double *theMin, double *theMax);
cv::Scalar hexToScalar(unsigned int theColor);
void resetRenderingBuffer(cvui_block_t& theScreen);
template <typename T> // T can be any floating point type (float, double, long double)
TrackbarParams makeTrackbarParams(T min, T max, int theDecimals = 1, int theSegments = 1, T theStep = -1., unsigned int theOptions = 0, const char *theFormat = "%.1Lf");
template<typename T>
bool trackbar(T *theValue, const TrackbarParams& theParams);
template <typename T> // T can be any numeric type (int, double, unsigned int, etc)
bool trackbar(cv::Mat& theWhere, int theX, int theY, int theWidth, T *theValue, const TrackbarParams& theParams);
template<typename num_type>
TrackbarParams makeTrackbarParams(num_type theMin, num_type theMax, num_type theStep, int theSegments, const char *theLabelFormat, unsigned int theOptions) {
TrackbarParams aParams;
aParams.min = (long double)theMin;
aParams.max = (long double)theMax;
aParams.step = (long double)theStep;
aParams.options = theOptions;
aParams.segments = theSegments;
aParams.labelFormat = theLabelFormat;
return aParams;
}
template <typename num_type>
bool trackbar(int theWidth, num_type *theValue, const TrackbarParams& theParams) {
cvui_block_t& aBlock = internal::topBlock();
long double aValueAsDouble = static_cast<long double>(*theValue);
bool aResult = internal::trackbar(aBlock, aBlock.anchor.x, aBlock.anchor.y, theWidth, &aValueAsDouble, theParams);
*theValue = static_cast<num_type>(aValueAsDouble);
return aResult;
}
template <typename num_type>
bool trackbar(cv::Mat& theWhere, int theX, int theY, int theWidth, num_type *theValue, const TrackbarParams& theParams) {
gScreen.where = theWhere;
long double aValueAsDouble = static_cast<long double>(*theValue);
bool aResult = internal::trackbar(gScreen, theX, theY, theWidth, &aValueAsDouble, theParams);
*theValue = static_cast<num_type>(aValueAsDouble);
return aResult;
}
}
// Internal namespace that contains all rendering functions.
namespace render {
void text(cvui_block_t& theBlock, const cv::String& theText, cv::Point& thePos, double theFontScale, unsigned int theColor);
void button(cvui_block_t& theBlock, int theState, cv::Rect& theShape, const cv::String& theLabel);
void buttonLabel(cvui_block_t& theBlock, int theState, cv::Rect theRect, const cv::String& theLabel, cv::Size& theTextSize);
void image(cvui_block_t& theBlock, cv::Rect& theRect, cv::Mat& theImage);
void counter(cvui_block_t& theBlock, cv::Rect& theShape, const cv::String& theValue);
void trackbarHandle(cvui_block_t& theBlock, int theState, cv::Rect& theShape, double theValue, const internal::TrackbarParams &theParams, cv::Rect& theWorkingArea);
void trackbarPath(cvui_block_t& theBlock, int theState, cv::Rect& theShape, double theValue, const internal::TrackbarParams &theParams, cv::Rect& theWorkingArea);
void trackbarSteps(cvui_block_t& theBlock, int theState, cv::Rect& theShape, double theValue, const internal::TrackbarParams &theParams, cv::Rect& theWorkingArea);
void trackbarSegmentLabel(cvui_block_t& theBlock, cv::Rect& theShape, const internal::TrackbarParams &theParams, long double theValue, cv::Rect& theWorkingArea, bool theShowLabel);
void trackbarSegments(cvui_block_t& theBlock, int theState, cv::Rect& theShape, double theValue, const internal::TrackbarParams &theParams, cv::Rect& theWorkingArea);
void trackbar(cvui_block_t& theBlock, int theState, cv::Rect& theShape, double theValue, const internal::TrackbarParams &theParams);
void checkbox(cvui_block_t& theBlock, int theState, cv::Rect& theShape);
void checkboxLabel(cvui_block_t& theBlock, cv::Rect& theRect, const cv::String& theLabel, cv::Size& theTextSize, unsigned int theColor);
void checkboxCheck(cvui_block_t& theBlock, cv::Rect& theShape);
void window(cvui_block_t& theBlock, cv::Rect& theTitleBar, cv::Rect& theContent, const cv::String& theTitle);
void rect(cvui_block_t& theBlock, cv::Rect& thePos, unsigned int theBorderColor, unsigned int theFillingColor);
void sparkline(cvui_block_t& theBlock, std::vector<double>& theValues, cv::Rect &theRect, double theMin, double theMax, unsigned int theColor);
int putText(cvui_block_t& theBlock, int theState, cv::Scalar aColor, const std::string& theText, const cv::Point & thePosition);
int putTextCentered(cvui_block_t& theBlock, const cv::Point & position, const std::string &text);
}
template <typename num_type>
bool trackbar(cv::Mat& theWhere, int theX, int theY, int theWidth, num_type *theValue, num_type theMin, num_type theMax, int theSegments, const char *theLabelFormat, unsigned int theOptions, num_type theDiscreteStep) {
internal::TrackbarParams aParams = internal::makeTrackbarParams(theMin, theMax, theDiscreteStep, theSegments, theLabelFormat, theOptions);
return trackbar<num_type>(theWhere, theX, theY, theWidth, theValue, aParams);
}
template <typename num_type>
bool trackbar(int theWidth, num_type *theValue, num_type theMin, num_type theMax, int theSegments, const char *theLabelFormat, unsigned int theOptions, num_type theDiscreteStep) {
internal::TrackbarParams aParams = internal::makeTrackbarParams(theMin, theMax, theDiscreteStep, theSegments, theLabelFormat, theOptions);
return trackbar<num_type>(theWidth, theValue, aParams);
}
} // namespace cvui
#endif // _CVUI_H_