0
# GUI and Drawing
1
2
OpenCV provides high-level GUI capabilities for displaying images, creating interactive windows, and drawing shapes on images. These features are essential for debugging, visualization, and creating interactive computer vision applications.
3
4
**Important Note**: GUI functions are not available in headless packages (`opencv-python-headless`). If you're running OpenCV in a server environment or headless system, these functions will not work. Use the standard `opencv-python` package if you need GUI functionality.
5
6
## Capabilities
7
8
### Window Management
9
10
OpenCV provides a complete set of functions for creating and managing display windows.
11
12
```python { .api }
13
# Display image in a window
14
cv2.imshow(winname, mat) -> None
15
```
16
17
Shows an image in the specified window. If the window doesn't exist, it will be created with `WINDOW_AUTOSIZE` flag. The window will automatically fit the image size.
18
19
**Parameters**:
20
- `winname` (str): Name of the window
21
- `mat` (np.ndarray): Image to display
22
23
**Example**:
24
```python
25
import cv2
26
import numpy as np
27
28
img = cv2.imread('image.jpg')
29
cv2.imshow('My Image', img)
30
cv2.waitKey(0) # Wait for key press
31
cv2.destroyAllWindows()
32
```
33
34
---
35
36
```python { .api }
37
# Create a named window
38
cv2.namedWindow(winname, flags=cv2.WINDOW_AUTOSIZE) -> None
39
```
40
41
Creates a window that can be used as a placeholder for images and trackbars. Created windows are referred to by their names.
42
43
**Parameters**:
44
- `winname` (str): Name of the window
45
- `flags` (int): Window flags (see Window Flags section)
46
47
**Example**:
48
```python
49
# Create a resizable window
50
cv2.namedWindow('My Window', cv2.WINDOW_NORMAL)
51
cv2.imshow('My Window', img)
52
```
53
54
---
55
56
```python { .api }
57
# Destroy specific window
58
cv2.destroyWindow(winname) -> None
59
```
60
61
Destroys the specified window.
62
63
**Parameters**:
64
- `winname` (str): Name of the window to destroy
65
66
---
67
68
```python { .api }
69
# Destroy all windows
70
cv2.destroyAllWindows() -> None
71
```
72
73
Destroys all HighGUI windows. Should be called at the end of GUI applications.
74
75
---
76
77
```python { .api }
78
# Wait for key press
79
cv2.waitKey(delay=0) -> int
80
```
81
82
Waits for a key press for a specified number of milliseconds. This function is essential for GUI event processing.
83
84
**Parameters**:
85
- `delay` (int): Delay in milliseconds. 0 means wait indefinitely
86
87
**Returns**:
88
- Key code of the pressed key, or -1 if no key was pressed
89
90
**Example**:
91
```python
92
# Wait indefinitely for key press
93
key = cv2.waitKey(0)
94
if key == ord('q'):
95
print("Q was pressed")
96
elif key == 27: # ESC key
97
print("ESC was pressed")
98
99
# Wait 30ms (useful for video playback)
100
key = cv2.waitKey(30)
101
```
102
103
---
104
105
```python { .api }
106
# Poll for key press (non-blocking)
107
cv2.pollKey() -> int
108
```
109
110
Polls for a key press without blocking. Similar to `waitKey(0)` but non-blocking.
111
112
**Returns**:
113
- Key code of the pressed key, or -1 if no key was pressed
114
115
---
116
117
```python { .api }
118
# Resize window
119
cv2.resizeWindow(winname, width, height) -> None
120
```
121
122
Resizes the window to the specified size. The window must have been created with `WINDOW_NORMAL` flag.
123
124
**Parameters**:
125
- `winname` (str): Name of the window
126
- `width` (int): New window width
127
- `height` (int): New window height
128
129
---
130
131
```python { .api }
132
# Move window
133
cv2.moveWindow(winname, x, y) -> None
134
```
135
136
Moves the window to the specified position.
137
138
**Parameters**:
139
- `winname` (str): Name of the window
140
- `x` (int): New x-coordinate of the top-left corner
141
- `y` (int): New y-coordinate of the top-left corner
142
143
---
144
145
```python { .api }
146
# Get window property
147
cv2.getWindowProperty(winname, prop_id) -> float
148
```
149
150
Gets a property of the window.
151
152
**Parameters**:
153
- `winname` (str): Name of the window
154
- `prop_id` (int): Property identifier
155
156
**Returns**:
157
- Property value
158
159
---
160
161
```python { .api }
162
# Set window property
163
cv2.setWindowProperty(winname, prop_id, prop_value) -> None
164
```
165
166
Sets a property of the window.
167
168
**Parameters**:
169
- `winname` (str): Name of the window
170
- `prop_id` (int): Property identifier
171
- `prop_value` (float): New property value
172
173
---
174
175
```python { .api }
176
# Set window title
177
cv2.setWindowTitle(winname, title) -> None
178
```
179
180
Updates the window title.
181
182
**Parameters**:
183
- `winname` (str): Name of the window
184
- `title` (str): New window title
185
186
---
187
188
#### Window Flags
189
190
Constants for window creation:
191
192
```python { .api }
193
cv2.WINDOW_NORMAL # User can resize the window
194
cv2.WINDOW_AUTOSIZE # Window size automatically adjusted to fit image
195
cv2.WINDOW_FULLSCREEN # Window is in fullscreen mode
196
cv2.WINDOW_FREERATIO # Window can be resized without maintaining aspect ratio
197
cv2.WINDOW_KEEPRATIO # Window maintains aspect ratio when resized
198
cv2.WINDOW_GUI_EXPANDED # Window with extended GUI features
199
cv2.WINDOW_GUI_NORMAL # Window with basic GUI features
200
```
201
202
### Trackbars
203
204
Trackbars provide an interactive way to adjust parameters in real-time. They are useful for tuning algorithms and exploring parameter spaces.
205
206
```python { .api }
207
# Create trackbar
208
cv2.createTrackbar(trackbarname, winname, value, count, onChange) -> None
209
```
210
211
Creates a trackbar and attaches it to the specified window.
212
213
**Parameters**:
214
- `trackbarname` (str): Name of the trackbar
215
- `winname` (str): Name of the window that will be the parent of the trackbar
216
- `value` (int): Initial trackbar position
217
- `count` (int): Maximum trackbar position (minimum is always 0)
218
- `onChange` (callable): Callback function called when trackbar value changes. Signature: `onChange(value: int) -> None`
219
220
**Example**:
221
```python
222
def on_threshold_change(value):
223
_, thresh = cv2.threshold(gray, value, 255, cv2.THRESH_BINARY)
224
cv2.imshow('Threshold', thresh)
225
226
cv2.namedWindow('Threshold')
227
cv2.createTrackbar('Threshold', 'Threshold', 127, 255, on_threshold_change)
228
```
229
230
---
231
232
```python { .api }
233
# Get trackbar position
234
cv2.getTrackbarPos(trackbarname, winname) -> int
235
```
236
237
Gets the current position of the trackbar.
238
239
**Parameters**:
240
- `trackbarname` (str): Name of the trackbar
241
- `winname` (str): Name of the parent window
242
243
**Returns**:
244
- Current trackbar position
245
246
---
247
248
```python { .api }
249
# Set trackbar position
250
cv2.setTrackbarPos(trackbarname, winname, pos) -> None
251
```
252
253
Sets the trackbar position.
254
255
**Parameters**:
256
- `trackbarname` (str): Name of the trackbar
257
- `winname` (str): Name of the parent window
258
- `pos` (int): New trackbar position
259
260
---
261
262
```python { .api }
263
# Set trackbar minimum value
264
cv2.setTrackbarMin(trackbarname, winname, minval) -> None
265
```
266
267
Sets the minimum value of the trackbar.
268
269
**Parameters**:
270
- `trackbarname` (str): Name of the trackbar
271
- `winname` (str): Name of the parent window
272
- `minval` (int): New minimum value
273
274
---
275
276
```python { .api }
277
# Set trackbar maximum value
278
cv2.setTrackbarMax(trackbarname, winname, maxval) -> None
279
```
280
281
Sets the maximum value of the trackbar.
282
283
**Parameters**:
284
- `trackbarname` (str): Name of the trackbar
285
- `winname` (str): Name of the parent window
286
- `maxval` (int): New maximum value
287
288
**Example - Multiple Trackbars**:
289
```python
290
import cv2
291
import numpy as np
292
293
def nothing(x):
294
pass
295
296
# Create window and trackbars
297
cv2.namedWindow('Color Picker')
298
cv2.createTrackbar('R', 'Color Picker', 0, 255, nothing)
299
cv2.createTrackbar('G', 'Color Picker', 0, 255, nothing)
300
cv2.createTrackbar('B', 'Color Picker', 0, 255, nothing)
301
302
while True:
303
# Get current trackbar positions
304
r = cv2.getTrackbarPos('R', 'Color Picker')
305
g = cv2.getTrackbarPos('G', 'Color Picker')
306
b = cv2.getTrackbarPos('B', 'Color Picker')
307
308
# Create image with selected color
309
img = np.zeros((300, 512, 3), np.uint8)
310
img[:] = [b, g, r]
311
312
cv2.imshow('Color Picker', img)
313
314
if cv2.waitKey(1) & 0xFF == 27: # ESC to exit
315
break
316
317
cv2.destroyAllWindows()
318
```
319
320
### Mouse Events
321
322
OpenCV allows you to capture and handle mouse events in windows, enabling interactive applications.
323
324
```python { .api }
325
# Set mouse callback function
326
cv2.setMouseCallback(windowName, onMouse, param=None) -> None
327
```
328
329
Sets a mouse event callback function for the specified window.
330
331
**Parameters**:
332
- `windowName` (str): Name of the window
333
- `onMouse` (callable): Callback function with signature: `onMouse(event, x, y, flags, param)`
334
- `event` (int): Mouse event type (see Mouse Event Constants)
335
- `x` (int): X-coordinate of the mouse event
336
- `y` (int): Y-coordinate of the mouse event
337
- `flags` (int): Event flags (see Mouse Event Flags)
338
- `param`: User data passed to the callback
339
- `param`: Optional user data to pass to the callback
340
341
**Example**:
342
```python
343
def mouse_callback(event, x, y, flags, param):
344
if event == cv2.EVENT_LBUTTONDOWN:
345
print(f"Left button clicked at ({x}, {y})")
346
elif event == cv2.EVENT_MOUSEMOVE:
347
if flags & cv2.EVENT_FLAG_LBUTTON:
348
print(f"Drawing at ({x}, {y})")
349
elif event == cv2.EVENT_RBUTTONDOWN:
350
print(f"Right button clicked at ({x}, {y})")
351
352
img = np.zeros((512, 512, 3), np.uint8)
353
cv2.namedWindow('Mouse Events')
354
cv2.setMouseCallback('Mouse Events', mouse_callback)
355
356
while True:
357
cv2.imshow('Mouse Events', img)
358
if cv2.waitKey(20) & 0xFF == 27:
359
break
360
361
cv2.destroyAllWindows()
362
```
363
364
---
365
366
#### Mouse Event Constants
367
368
Constants representing different mouse events:
369
370
```python { .api }
371
cv2.EVENT_MOUSEMOVE # Mouse moved
372
cv2.EVENT_LBUTTONDOWN # Left button pressed
373
cv2.EVENT_RBUTTONDOWN # Right button pressed
374
cv2.EVENT_MBUTTONDOWN # Middle button pressed
375
cv2.EVENT_LBUTTONUP # Left button released
376
cv2.EVENT_RBUTTONUP # Right button released
377
cv2.EVENT_MBUTTONUP # Middle button released
378
cv2.EVENT_LBUTTONDBLCLK # Left button double-clicked
379
cv2.EVENT_RBUTTONDBLCLK # Right button double-clicked
380
cv2.EVENT_MBUTTONDBLCLK # Middle button double-clicked
381
cv2.EVENT_MOUSEWHEEL # Mouse wheel scrolled (vertical)
382
cv2.EVENT_MOUSEHWHEEL # Mouse wheel scrolled (horizontal)
383
```
384
385
---
386
387
#### Mouse Event Flags
388
389
Constants representing modifier keys and button states during mouse events:
390
391
```python { .api }
392
cv2.EVENT_FLAG_LBUTTON # Left button is pressed
393
cv2.EVENT_FLAG_RBUTTON # Right button is pressed
394
cv2.EVENT_FLAG_MBUTTON # Middle button is pressed
395
cv2.EVENT_FLAG_CTRLKEY # Ctrl key is pressed
396
cv2.EVENT_FLAG_SHIFTKEY # Shift key is pressed
397
cv2.EVENT_FLAG_ALTKEY # Alt key is pressed
398
```
399
400
**Example - Drawing Application**:
401
```python
402
import cv2
403
import numpy as np
404
405
drawing = False # True if mouse is pressed
406
mode = True # True for rectangle, False for circle
407
ix, iy = -1, -1
408
409
def draw_shape(event, x, y, flags, param):
410
global ix, iy, drawing, mode
411
412
if event == cv2.EVENT_LBUTTONDOWN:
413
drawing = True
414
ix, iy = x, y
415
416
elif event == cv2.EVENT_MOUSEMOVE:
417
if drawing:
418
if mode:
419
cv2.rectangle(img, (ix, iy), (x, y), (0, 255, 0), -1)
420
else:
421
cv2.circle(img, (x, y), 5, (0, 0, 255), -1)
422
423
elif event == cv2.EVENT_LBUTTONUP:
424
drawing = False
425
if mode:
426
cv2.rectangle(img, (ix, iy), (x, y), (0, 255, 0), -1)
427
else:
428
cv2.circle(img, (x, y), 5, (0, 0, 255), -1)
429
430
img = np.zeros((512, 512, 3), np.uint8)
431
cv2.namedWindow('Drawing')
432
cv2.setMouseCallback('Drawing', draw_shape)
433
434
while True:
435
cv2.imshow('Drawing', img)
436
k = cv2.waitKey(1) & 0xFF
437
if k == ord('m'):
438
mode = not mode # Toggle mode
439
elif k == 27:
440
break
441
442
cv2.destroyAllWindows()
443
```
444
445
### ROI Selection
446
447
OpenCV provides built-in functions for selecting regions of interest interactively.
448
449
```python { .api }
450
# Select single ROI
451
cv2.selectROI(windowName, img, showCrosshair=True, fromCenter=False) -> tuple
452
```
453
454
Allows the user to select a region of interest in the image.
455
456
**Parameters**:
457
- `windowName` (str): Name of the window where selection is performed
458
- `img` (np.ndarray): Image to select ROI from
459
- `showCrosshair` (bool): If True, show crosshair in the center of selection
460
- `fromCenter` (bool): If True, selection starts from center
461
462
**Returns**:
463
- Tuple `(x, y, w, h)` representing the selected rectangle, or `(0, 0, 0, 0)` if cancelled
464
465
**Controls**:
466
- Click and drag to select ROI
467
- Press SPACE or ENTER to confirm selection
468
- Press C to cancel
469
470
**Example**:
471
```python
472
import cv2
473
474
img = cv2.imread('image.jpg')
475
roi = cv2.selectROI('Select ROI', img, showCrosshair=True)
476
x, y, w, h = roi
477
478
if w > 0 and h > 0:
479
# Crop selected region
480
cropped = img[y:y+h, x:x+w]
481
cv2.imshow('Cropped', cropped)
482
cv2.waitKey(0)
483
484
cv2.destroyAllWindows()
485
```
486
487
---
488
489
```python { .api }
490
# Select multiple ROIs
491
cv2.selectROIs(windowName, img, showCrosshair=True, fromCenter=False) -> tuple
492
```
493
494
Allows the user to select multiple regions of interest in the image.
495
496
**Parameters**:
497
- `windowName` (str): Name of the window where selection is performed
498
- `img` (np.ndarray): Image to select ROIs from
499
- `showCrosshair` (bool): If True, show crosshair in the center of selection
500
- `fromCenter` (bool): If True, selection starts from center
501
502
**Returns**:
503
- Tuple of rectangles, each in format `(x, y, w, h)`
504
505
**Controls**:
506
- Click and drag to select each ROI
507
- Press SPACE or ENTER after each selection
508
- Press ESC to finish selecting
509
510
**Example**:
511
```python
512
import cv2
513
514
img = cv2.imread('image.jpg')
515
rois = cv2.selectROIs('Select Multiple ROIs', img, showCrosshair=True)
516
517
# Process each selected ROI
518
for i, roi in enumerate(rois):
519
x, y, w, h = roi
520
if w > 0 and h > 0:
521
cropped = img[y:y+h, x:x+w]
522
cv2.imshow(f'ROI {i+1}', cropped)
523
524
cv2.waitKey(0)
525
cv2.destroyAllWindows()
526
```
527
528
### Drawing Functions
529
530
OpenCV provides comprehensive drawing functions for visualizing results and creating graphics.
531
532
```python { .api }
533
# Draw line
534
cv2.line(img, pt1, pt2, color, thickness=1, lineType=cv2.LINE_8, shift=0) -> img
535
```
536
537
Draws a line segment connecting two points.
538
539
**Parameters**:
540
- `img` (np.ndarray): Image to draw on (modified in-place)
541
- `pt1` (tuple): First point (x, y)
542
- `pt2` (tuple): Second point (x, y)
543
- `color` (tuple): Line color (B, G, R) for color images or intensity for grayscale
544
- `thickness` (int): Line thickness in pixels
545
- `lineType` (int): Line type (see Line Types)
546
- `shift` (int): Number of fractional bits in point coordinates
547
548
**Returns**:
549
- Modified image
550
551
**Example**:
552
```python
553
import cv2
554
import numpy as np
555
556
img = np.zeros((512, 512, 3), np.uint8)
557
# Draw red line from (0,0) to (511,511)
558
cv2.line(img, (0, 0), (511, 511), (0, 0, 255), 5)
559
```
560
561
---
562
563
```python { .api }
564
# Draw arrowed line
565
cv2.arrowedLine(img, pt1, pt2, color, thickness=1, lineType=cv2.LINE_8, shift=0, tipLength=0.1) -> img
566
```
567
568
Draws an arrow segment pointing from the first point to the second.
569
570
**Parameters**:
571
- `img` (np.ndarray): Image to draw on
572
- `pt1` (tuple): Starting point (x, y)
573
- `pt2` (tuple): End point (x, y) - arrow points here
574
- `color` (tuple): Line color
575
- `thickness` (int): Line thickness
576
- `lineType` (int): Line type
577
- `shift` (int): Number of fractional bits
578
- `tipLength` (float): Length of arrow tip relative to arrow length
579
580
**Example**:
581
```python
582
cv2.arrowedLine(img, (50, 50), (200, 200), (255, 0, 0), 3, tipLength=0.3)
583
```
584
585
---
586
587
```python { .api }
588
# Draw rectangle
589
cv2.rectangle(img, pt1, pt2, color, thickness=1, lineType=cv2.LINE_8, shift=0) -> img
590
```
591
592
Draws a rectangle.
593
594
**Parameters**:
595
- `img` (np.ndarray): Image to draw on
596
- `pt1` (tuple): Top-left corner (x, y)
597
- `pt2` (tuple): Bottom-right corner (x, y)
598
- `color` (tuple): Rectangle color
599
- `thickness` (int): Line thickness. Use -1 for filled rectangle
600
- `lineType` (int): Line type
601
- `shift` (int): Number of fractional bits
602
603
**Alternative signature**:
604
```python
605
cv2.rectangle(img, rec, color, thickness=1, lineType=cv2.LINE_8, shift=0) -> img
606
```
607
Where `rec` is a tuple `(x, y, w, h)`.
608
609
**Example**:
610
```python
611
# Outline rectangle
612
cv2.rectangle(img, (50, 50), (200, 200), (0, 255, 0), 3)
613
614
# Filled rectangle
615
cv2.rectangle(img, (250, 50), (400, 200), (255, 0, 0), -1)
616
```
617
618
---
619
620
```python { .api }
621
# Draw circle
622
cv2.circle(img, center, radius, color, thickness=1, lineType=cv2.LINE_8, shift=0) -> img
623
```
624
625
Draws a circle.
626
627
**Parameters**:
628
- `img` (np.ndarray): Image to draw on
629
- `center` (tuple): Center of the circle (x, y)
630
- `radius` (int): Radius of the circle
631
- `color` (tuple): Circle color
632
- `thickness` (int): Circle outline thickness. Use -1 for filled circle
633
- `lineType` (int): Line type
634
- `shift` (int): Number of fractional bits
635
636
**Example**:
637
```python
638
# Outline circle
639
cv2.circle(img, (256, 256), 50, (0, 255, 255), 2)
640
641
# Filled circle
642
cv2.circle(img, (400, 400), 30, (255, 255, 0), -1)
643
```
644
645
---
646
647
```python { .api }
648
# Draw ellipse
649
cv2.ellipse(img, center, axes, angle, startAngle, endAngle, color, thickness=1, lineType=cv2.LINE_8, shift=0) -> img
650
```
651
652
Draws an ellipse or elliptic arc.
653
654
**Parameters**:
655
- `img` (np.ndarray): Image to draw on
656
- `center` (tuple): Center of the ellipse (x, y)
657
- `axes` (tuple): Half of the size of the ellipse main axes (width, height)
658
- `angle` (float): Ellipse rotation angle in degrees
659
- `startAngle` (float): Starting angle of the elliptic arc in degrees
660
- `endAngle` (float): Ending angle of the elliptic arc in degrees
661
- `color` (tuple): Ellipse color
662
- `thickness` (int): Line thickness. Use -1 for filled ellipse
663
- `lineType` (int): Line type
664
- `shift` (int): Number of fractional bits
665
666
**Alternative signature using RotatedRect**:
667
```python
668
cv2.ellipse(img, box, color, thickness=1, lineType=cv2.LINE_8) -> img
669
```
670
671
**Example**:
672
```python
673
# Full ellipse
674
cv2.ellipse(img, (256, 256), (100, 50), 0, 0, 360, (255, 0, 255), 2)
675
676
# Elliptic arc (quarter circle)
677
cv2.ellipse(img, (256, 256), (100, 50), 45, 0, 90, (0, 255, 0), 3)
678
679
# Filled ellipse
680
cv2.ellipse(img, (400, 100), (80, 40), 30, 0, 360, (128, 128, 255), -1)
681
```
682
683
---
684
685
```python { .api }
686
# Draw polylines
687
cv2.polylines(img, pts, isClosed, color, thickness=1, lineType=cv2.LINE_8, shift=0) -> img
688
```
689
690
Draws one or more polygonal curves.
691
692
**Parameters**:
693
- `img` (np.ndarray): Image to draw on
694
- `pts` (list): Array of polygonal curves. Each curve is represented by an array of points
695
- `isClosed` (bool): If True, draw closed polylines (connect last point to first)
696
- `color` (tuple): Polyline color
697
- `thickness` (int): Line thickness
698
- `lineType` (int): Line type
699
- `shift` (int): Number of fractional bits
700
701
**Example**:
702
```python
703
import numpy as np
704
705
# Triangle
706
pts = np.array([[100, 50], [50, 150], [150, 150]], np.int32)
707
pts = pts.reshape((-1, 1, 2))
708
cv2.polylines(img, [pts], True, (0, 255, 0), 3)
709
710
# Multiple polylines
711
pts1 = np.array([[200, 200], [250, 250], [300, 200]], np.int32).reshape((-1, 1, 2))
712
pts2 = np.array([[350, 200], [400, 250], [450, 200]], np.int32).reshape((-1, 1, 2))
713
cv2.polylines(img, [pts1, pts2], False, (255, 255, 0), 2)
714
```
715
716
---
717
718
```python { .api }
719
# Fill polygon
720
cv2.fillPoly(img, pts, color, lineType=cv2.LINE_8, shift=0, offset=(0, 0)) -> img
721
```
722
723
Fills the area bounded by one or more polygons.
724
725
**Parameters**:
726
- `img` (np.ndarray): Image to draw on
727
- `pts` (list): Array of polygons. Each polygon is represented by an array of points
728
- `color` (tuple): Polygon fill color
729
- `lineType` (int): Line type
730
- `shift` (int): Number of fractional bits
731
- `offset` (tuple): Optional offset for all points
732
733
**Example**:
734
```python
735
import numpy as np
736
737
# Filled triangle
738
pts = np.array([[100, 50], [50, 150], [150, 150]], np.int32)
739
pts = pts.reshape((-1, 1, 2))
740
cv2.fillPoly(img, [pts], (0, 255, 0))
741
742
# Multiple filled polygons
743
pts1 = np.array([[200, 200], [250, 250], [300, 200]], np.int32).reshape((-1, 1, 2))
744
pts2 = np.array([[350, 200], [400, 250], [450, 200], [425, 150]], np.int32).reshape((-1, 1, 2))
745
cv2.fillPoly(img, [pts1, pts2], (255, 0, 255))
746
```
747
748
---
749
750
```python { .api }
751
# Fill convex polygon (faster alternative for convex polygons)
752
cv2.fillConvexPoly(img, points, color, lineType=cv2.LINE_8, shift=0) -> img
753
```
754
755
Fills a convex polygon. This function is faster than `fillPoly` but only works with convex polygons.
756
757
**Parameters**:
758
- `img` (np.ndarray): Image to draw on
759
- `points` (np.ndarray): Array of polygon vertices
760
- `color` (tuple): Polygon fill color
761
- `lineType` (int): Line type
762
- `shift` (int): Number of fractional bits
763
764
---
765
766
```python { .api }
767
# Draw text
768
cv2.putText(img, text, org, fontFace, fontScale, color, thickness=1, lineType=cv2.LINE_8, bottomLeftOrigin=False) -> img
769
```
770
771
Draws a text string on the image.
772
773
**Parameters**:
774
- `img` (np.ndarray): Image to draw on
775
- `text` (str): Text string to draw
776
- `org` (tuple): Bottom-left corner of the text string in the image (x, y)
777
- `fontFace` (int): Font type (see Font Types)
778
- `fontScale` (float): Font scale factor (multiplied by font-specific base size)
779
- `color` (tuple): Text color
780
- `thickness` (int): Thickness of the lines used to draw text
781
- `lineType` (int): Line type
782
- `bottomLeftOrigin` (bool): If True, image data origin is at bottom-left corner
783
784
**Example**:
785
```python
786
# Simple text
787
cv2.putText(img, 'OpenCV', (50, 50), cv2.FONT_HERSHEY_SIMPLEX,
788
1, (255, 255, 255), 2)
789
790
# Larger, thicker text
791
cv2.putText(img, 'Hello World!', (100, 150), cv2.FONT_HERSHEY_DUPLEX,
792
2, (0, 255, 0), 3)
793
794
# Italic text
795
cv2.putText(img, 'Italic', (50, 250),
796
cv2.FONT_HERSHEY_SIMPLEX | cv2.FONT_ITALIC,
797
1.5, (255, 0, 255), 2)
798
```
799
800
---
801
802
```python { .api }
803
# Get text size
804
cv2.getTextSize(text, fontFace, fontScale, thickness) -> (text_size, baseline)
805
```
806
807
Calculates the width and height of a text string. Useful for positioning text.
808
809
**Parameters**:
810
- `text` (str): Text string
811
- `fontFace` (int): Font type
812
- `fontScale` (float): Font scale factor
813
- `thickness` (int): Text thickness
814
815
**Returns**:
816
- `text_size` (tuple): Size of text box (width, height)
817
- `baseline` (int): y-coordinate of baseline relative to bottom-most text point
818
819
**Example**:
820
```python
821
text = 'OpenCV'
822
font = cv2.FONT_HERSHEY_SIMPLEX
823
scale = 1
824
thickness = 2
825
826
(text_width, text_height), baseline = cv2.getTextSize(text, font, scale, thickness)
827
828
# Center text in image
829
x = (img.shape[1] - text_width) // 2
830
y = (img.shape[0] + text_height) // 2
831
cv2.putText(img, text, (x, y), font, scale, (255, 255, 255), thickness)
832
```
833
834
---
835
836
```python { .api }
837
# Draw marker
838
cv2.drawMarker(img, position, color, markerType=cv2.MARKER_CROSS, markerSize=20, thickness=1, lineType=cv2.LINE_8) -> img
839
```
840
841
Draws a marker at the specified position.
842
843
**Parameters**:
844
- `img` (np.ndarray): Image to draw on
845
- `position` (tuple): Marker position (x, y)
846
- `color` (tuple): Marker color
847
- `markerType` (int): Marker type (see Marker Types)
848
- `markerSize` (int): Marker size
849
- `thickness` (int): Line thickness
850
- `lineType` (int): Line type
851
852
**Example**:
853
```python
854
# Different marker types
855
cv2.drawMarker(img, (100, 100), (255, 0, 0), cv2.MARKER_CROSS, 20, 2)
856
cv2.drawMarker(img, (200, 100), (0, 255, 0), cv2.MARKER_TILTED_CROSS, 20, 2)
857
cv2.drawMarker(img, (300, 100), (0, 0, 255), cv2.MARKER_STAR, 20, 2)
858
cv2.drawMarker(img, (400, 100), (255, 255, 0), cv2.MARKER_DIAMOND, 20, 2)
859
```
860
861
---
862
863
#### Marker Types
864
865
Constants for marker shapes:
866
867
```python { .api }
868
cv2.MARKER_CROSS # Cross marker (+)
869
cv2.MARKER_TILTED_CROSS # Tilted cross marker (x)
870
cv2.MARKER_STAR # Star marker (*)
871
cv2.MARKER_DIAMOND # Diamond marker (◇)
872
cv2.MARKER_SQUARE # Square marker (□)
873
cv2.MARKER_TRIANGLE_UP # Upward triangle marker (△)
874
cv2.MARKER_TRIANGLE_DOWN # Downward triangle marker (▽)
875
```
876
877
---
878
879
#### Line Types
880
881
Constants for line rendering:
882
883
```python { .api }
884
cv2.LINE_4 # 4-connected line
885
cv2.LINE_8 # 8-connected line (default)
886
cv2.LINE_AA # Anti-aliased line (smooth)
887
```
888
889
**Note**: `LINE_AA` produces smooth, anti-aliased lines but is computationally more expensive.
890
891
---
892
893
#### Font Types
894
895
Constants for text rendering:
896
897
```python { .api }
898
cv2.FONT_HERSHEY_SIMPLEX # Normal sans-serif font
899
cv2.FONT_HERSHEY_PLAIN # Small sans-serif font
900
cv2.FONT_HERSHEY_DUPLEX # Normal sans-serif font (more complex than SIMPLEX)
901
cv2.FONT_HERSHEY_COMPLEX # Normal serif font
902
cv2.FONT_HERSHEY_TRIPLEX # Normal serif font (more complex than COMPLEX)
903
cv2.FONT_HERSHEY_COMPLEX_SMALL # Smaller version of COMPLEX
904
cv2.FONT_HERSHEY_SCRIPT_SIMPLEX # Hand-writing style font
905
cv2.FONT_HERSHEY_SCRIPT_COMPLEX # More complex hand-writing style font
906
cv2.FONT_ITALIC # Flag for italic font (combine with OR)
907
```
908
909
**Example - Font Comparison**:
910
```python
911
import cv2
912
import numpy as np
913
914
img = np.zeros((600, 800, 3), np.uint8)
915
fonts = [
916
cv2.FONT_HERSHEY_SIMPLEX,
917
cv2.FONT_HERSHEY_PLAIN,
918
cv2.FONT_HERSHEY_DUPLEX,
919
cv2.FONT_HERSHEY_COMPLEX,
920
cv2.FONT_HERSHEY_TRIPLEX,
921
cv2.FONT_HERSHEY_SCRIPT_SIMPLEX,
922
cv2.FONT_HERSHEY_SCRIPT_COMPLEX
923
]
924
font_names = [
925
'HERSHEY_SIMPLEX',
926
'HERSHEY_PLAIN',
927
'HERSHEY_DUPLEX',
928
'HERSHEY_COMPLEX',
929
'HERSHEY_TRIPLEX',
930
'SCRIPT_SIMPLEX',
931
'SCRIPT_COMPLEX'
932
]
933
934
for i, (font, name) in enumerate(zip(fonts, font_names)):
935
y = 50 + i * 70
936
cv2.putText(img, name, (50, y), font, 1, (255, 255, 255), 2)
937
938
cv2.imshow('Font Comparison', img)
939
cv2.waitKey(0)
940
cv2.destroyAllWindows()
941
```
942
943
---
944
945
**Complete Drawing Example**:
946
```python
947
import cv2
948
import numpy as np
949
950
# Create blank image
951
img = np.zeros((512, 512, 3), np.uint8)
952
953
# Draw various shapes
954
cv2.line(img, (0, 0), (511, 511), (255, 0, 0), 5)
955
cv2.rectangle(img, (384, 0), (510, 128), (0, 255, 0), 3)
956
cv2.circle(img, (447, 63), 63, (0, 0, 255), -1)
957
cv2.ellipse(img, (256, 256), (100, 50), 0, 0, 180, (255, 255, 0), -1)
958
959
# Draw polygon
960
pts = np.array([[10, 5], [20, 30], [70, 20], [50, 10]], np.int32)
961
pts = pts.reshape((-1, 1, 2))
962
cv2.polylines(img, [pts], True, (0, 255, 255), 3)
963
964
# Draw text
965
font = cv2.FONT_HERSHEY_SIMPLEX
966
cv2.putText(img, 'OpenCV Drawing', (10, 450), font, 1, (255, 255, 255), 2, cv2.LINE_AA)
967
968
# Draw markers
969
cv2.drawMarker(img, (100, 100), (255, 0, 255), cv2.MARKER_CROSS, 20, 2)
970
cv2.drawMarker(img, (150, 100), (255, 0, 255), cv2.MARKER_STAR, 20, 2)
971
972
# Display
973
cv2.imshow('Drawing Demo', img)
974
cv2.waitKey(0)
975
cv2.destroyAllWindows()
976
```
977
978
## Best Practices
979
980
### Window Management
981
- Always call `cv2.waitKey()` after `cv2.imshow()` to allow the window to render
982
- Use `cv2.destroyAllWindows()` at the end of your program to clean up
983
- Create windows with `cv2.WINDOW_NORMAL` flag if you need to resize them
984
985
### Interactive Applications
986
- Use trackbars for real-time parameter adjustment
987
- Implement mouse callbacks for interactive selection and drawing
988
- Consider using `cv2.selectROI()` for user-friendly region selection
989
990
### Performance
991
- Drawing operations modify images in-place
992
- Use `img.copy()` if you need to preserve the original image
993
- Anti-aliased lines (`LINE_AA`) are slower than standard lines
994
- Filled shapes are faster than equivalent polylines
995
996
### Color Considerations
997
- Remember OpenCV uses BGR color order, not RGB
998
- For grayscale images, use single-value tuples: `(intensity,)` or just `intensity`
999
- Color values range from 0-255 for 8-bit images
1000
1001
### Text Rendering
1002
- Use `cv2.getTextSize()` to calculate text dimensions for proper positioning
1003
- Consider background rectangles for better text visibility
1004
- Combine font types with `cv2.FONT_ITALIC` using bitwise OR: `cv2.FONT_HERSHEY_SIMPLEX | cv2.FONT_ITALIC`
1005
1006
### Debugging and Visualization
1007
- Use `cv2.imshow()` liberally during development for debugging
1008
- Add text annotations to display algorithm parameters and results
1009
- Use different colors for different types of features (e.g., green for correct, red for errors)
1010
- Draw markers or circles to highlight key points
1011