or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

aruco.mdcamera-calibration.mdcomputational-photography.mdcontours-shapes.mdcore-operations.mddnn.mdfeature-detection.mdgui-drawing.mdimage-processing.mdimage-video-io.mdindex.mdmachine-learning.mdobject-detection.mdtask-log.mdvideo-analysis.md

gui-drawing.mddocs/

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