0
# Video Processing
1
2
Threaded video capture classes and utilities for efficient real-time video processing. These classes provide consistent APIs across different video sources (webcams, files, Pi cameras) and include performance monitoring capabilities.
3
4
## Capabilities
5
6
### Unified Video Stream Interface
7
8
The VideoStream class provides a unified interface that automatically selects the appropriate camera type based on the platform and parameters.
9
10
```python { .api }
11
class VideoStream:
12
def __init__(self, src=0, usePiCamera=False, resolution=(320, 240), framerate=32, **kwargs):
13
"""
14
Unified video stream interface.
15
16
Args:
17
src (int): Camera index for webcam (default: 0)
18
usePiCamera (bool): Use Raspberry Pi camera (default: False)
19
resolution (tuple): Camera resolution (width, height) (default: (320, 240))
20
framerate (int): Target framerate (default: 32)
21
**kwargs: Additional camera-specific parameters
22
"""
23
24
def start(self):
25
"""
26
Start the video stream thread.
27
28
Returns:
29
VideoStream: Self for method chaining
30
"""
31
32
def update(self):
33
"""Update the video stream (grab next frame)."""
34
35
def read(self):
36
"""
37
Read the current frame.
38
39
Returns:
40
np.ndarray: Current frame
41
"""
42
43
def stop(self):
44
"""Stop the video stream and release resources."""
45
```
46
47
**Usage Example:**
48
```python
49
from imutils.video import VideoStream
50
import cv2
51
import time
52
53
# Initialize video stream (automatically detects platform)
54
vs = VideoStream(src=0).start()
55
time.sleep(2.0) # Allow camera to warm up
56
57
while True:
58
frame = vs.read()
59
60
if frame is None:
61
break
62
63
# Process frame here
64
cv2.imshow("Frame", frame)
65
66
if cv2.waitKey(1) & 0xFF == ord('q'):
67
break
68
69
vs.stop()
70
cv2.destroyAllWindows()
71
```
72
73
### Webcam Video Stream
74
75
Threaded webcam video capture using OpenCV's VideoCapture.
76
77
```python { .api }
78
class WebcamVideoStream:
79
def __init__(self, src=0, name="WebcamVideoStream"):
80
"""
81
Threaded webcam video stream.
82
83
Args:
84
src (int): Camera index (default: 0)
85
name (str): Thread name (default: "WebcamVideoStream")
86
"""
87
88
def start(self):
89
"""
90
Start the threaded video capture.
91
92
Returns:
93
WebcamVideoStream: Self for method chaining
94
"""
95
96
def update(self):
97
"""Internal method that continuously reads frames."""
98
99
def read(self):
100
"""
101
Get the most recently captured frame.
102
103
Returns:
104
np.ndarray: Current frame
105
"""
106
107
def stop(self):
108
"""Stop the video capture thread."""
109
```
110
111
**Usage Example:**
112
```python
113
from imutils.video import WebcamVideoStream
114
import cv2
115
import time
116
117
# Start webcam stream
118
webcam = WebcamVideoStream(src=0).start()
119
time.sleep(2.0)
120
121
while True:
122
frame = webcam.read()
123
124
# Show frame
125
cv2.imshow("Webcam", frame)
126
127
if cv2.waitKey(1) & 0xFF == ord('q'):
128
break
129
130
webcam.stop()
131
cv2.destroyAllWindows()
132
```
133
134
### File Video Stream
135
136
Threaded video file reader with frame queuing for smooth playback.
137
138
```python { .api }
139
class FileVideoStream:
140
def __init__(self, path, transform=None, queue_size=128):
141
"""
142
Threaded video file reader.
143
144
Args:
145
path (str): Path to video file
146
transform (callable, optional): Function to transform frames
147
queue_size (int): Maximum frame queue size (default: 128)
148
"""
149
150
def start(self):
151
"""
152
Start the threaded video file reading.
153
154
Returns:
155
FileVideoStream: Self for method chaining
156
"""
157
158
def update(self):
159
"""Internal method that continuously reads frames into queue."""
160
161
def read(self):
162
"""
163
Get next frame from the queue.
164
165
Returns:
166
np.ndarray: Next frame from queue
167
"""
168
169
def running(self):
170
"""
171
Check if stream is still running.
172
173
Returns:
174
bool: True if stream has frames or is not stopped
175
"""
176
177
def more(self):
178
"""
179
Check if more frames are available in queue.
180
181
Returns:
182
bool: True if frames are available in queue
183
"""
184
185
def stop(self):
186
"""Stop the video stream and wait for thread to join."""
187
```
188
189
**Usage Example:**
190
```python
191
from imutils.video import FileVideoStream
192
import cv2
193
import time
194
195
# Start file stream
196
fvs = FileVideoStream("example_video.mp4").start()
197
time.sleep(1.0)
198
199
while fvs.more():
200
frame = fvs.read()
201
202
if frame is None:
203
break
204
205
cv2.imshow("Video", frame)
206
207
if cv2.waitKey(25) & 0xFF == ord('q'):
208
break
209
210
fvs.stop()
211
cv2.destroyAllWindows()
212
```
213
214
### Raspberry Pi Camera Stream
215
216
Threaded Raspberry Pi camera capture using the picamera library.
217
218
```python { .api }
219
class PiVideoStream:
220
def __init__(self, resolution=(320, 240), framerate=32, **kwargs):
221
"""
222
Threaded Raspberry Pi camera stream.
223
224
Args:
225
resolution (tuple): Camera resolution (width, height) (default: (320, 240))
226
framerate (int): Target framerate (default: 32)
227
**kwargs: Additional PiCamera parameters
228
"""
229
230
def start(self):
231
"""
232
Start the threaded Pi camera capture.
233
234
Returns:
235
PiVideoStream: Self for method chaining
236
"""
237
238
def update(self):
239
"""Internal method that continuously captures frames."""
240
241
def read(self):
242
"""
243
Get the most recently captured frame.
244
245
Returns:
246
np.ndarray: Current frame
247
"""
248
249
def stop(self):
250
"""Stop the camera capture and release resources."""
251
```
252
253
**Usage Example:**
254
```python
255
from imutils.video import PiVideoStream
256
import cv2
257
import time
258
259
# Start Pi camera stream (requires picamera library)
260
pi_camera = PiVideoStream(resolution=(640, 480), framerate=30).start()
261
time.sleep(2.0)
262
263
while True:
264
frame = pi_camera.read()
265
266
cv2.imshow("Pi Camera", frame)
267
268
if cv2.waitKey(1) & 0xFF == ord('q'):
269
break
270
271
pi_camera.stop()
272
cv2.destroyAllWindows()
273
```
274
275
### FPS Monitoring
276
277
Frame rate monitoring utility for performance measurement.
278
279
```python { .api }
280
class FPS:
281
def __init__(self):
282
"""Initialize FPS counter."""
283
284
def start(self):
285
"""
286
Start the FPS timer.
287
288
Returns:
289
FPS: Self for method chaining
290
"""
291
292
def stop(self):
293
"""Stop the FPS timer."""
294
295
def update(self):
296
"""Increment the frame counter."""
297
298
def elapsed(self):
299
"""
300
Get elapsed time between start and stop.
301
302
Returns:
303
float: Elapsed time in seconds
304
"""
305
306
def fps(self):
307
"""
308
Calculate and return FPS.
309
310
Returns:
311
float: Frames per second
312
"""
313
```
314
315
**Usage Example:**
316
```python
317
from imutils.video import VideoStream, FPS
318
import cv2
319
import time
320
321
# Initialize video stream and FPS counter
322
vs = VideoStream(src=0).start()
323
fps = FPS().start()
324
time.sleep(2.0)
325
326
while True:
327
frame = vs.read()
328
329
if frame is None:
330
break
331
332
# Process frame (add your processing here)
333
processed = cv2.flip(frame, 1)
334
335
cv2.imshow("Frame", processed)
336
fps.update()
337
338
if cv2.waitKey(1) & 0xFF == ord('q'):
339
break
340
341
# Cleanup and show results
342
fps.stop()
343
vs.stop()
344
cv2.destroyAllWindows()
345
346
print(f"Elapsed time: {fps.elapsed():.2f} seconds")
347
print(f"Approx. FPS: {fps.fps():.2f}")
348
```
349
350
### Frame Counting Utilities
351
352
Utilities for counting frames in video files.
353
354
```python { .api }
355
def count_frames(path, override=False):
356
"""
357
Count total frames in video file.
358
359
Args:
360
path (str): Path to video file
361
override (bool): Force manual counting (default: False)
362
363
Returns:
364
int: Total number of frames
365
366
Note:
367
First attempts to use OpenCV's CAP_PROP_FRAME_COUNT property.
368
If override=True or property is unreliable, uses manual counting.
369
"""
370
371
def count_frames_manual(video):
372
"""
373
Manually count frames by iterating through video.
374
375
Args:
376
video (cv2.VideoCapture): OpenCV VideoCapture object
377
378
Returns:
379
int: Total number of frames
380
"""
381
```
382
383
**Usage Example:**
384
```python
385
from imutils.video import count_frames
386
import cv2
387
388
# Count frames using OpenCV property (fast)
389
total_frames = count_frames("example_video.mp4")
390
print(f"Video has {total_frames} frames")
391
392
# Force manual counting (slower but more reliable)
393
total_frames_manual = count_frames("example_video.mp4", override=True)
394
print(f"Manual count: {total_frames_manual} frames")
395
396
# Manual counting with VideoCapture object
397
cap = cv2.VideoCapture("example_video.mp4")
398
frame_count = count_frames_manual(cap)
399
cap.release()
400
print(f"Frame count: {frame_count}")
401
```
402
403
### Complete Video Processing Example
404
405
Here's a comprehensive example combining multiple video processing capabilities:
406
407
```python
408
from imutils.video import VideoStream, FPS
409
import imutils
410
import cv2
411
import time
412
413
def process_video_stream():
414
# Initialize video stream with higher resolution
415
print("Starting video stream...")
416
vs = VideoStream(src=0, resolution=(640, 480), framerate=30).start()
417
fps = FPS().start()
418
time.sleep(2.0) # Allow camera to warm up
419
420
while True:
421
# Read frame from stream
422
frame = vs.read()
423
424
if frame is None:
425
print("Failed to read frame")
426
break
427
428
# Resize frame for faster processing
429
frame = imutils.resize(frame, width=400)
430
431
# Convert to grayscale for edge detection
432
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
433
edges = imutils.auto_canny(gray)
434
435
# Stack original and edge images
436
output = np.hstack([frame, cv2.cvtColor(edges, cv2.COLOR_GRAY2BGR)])
437
438
# Display the output
439
cv2.imshow("Original vs Edges", output)
440
441
# Update FPS counter
442
fps.update()
443
444
# Break on 'q' key press
445
if cv2.waitKey(1) & 0xFF == ord('q'):
446
break
447
448
# Cleanup
449
fps.stop()
450
vs.stop()
451
cv2.destroyAllWindows()
452
453
# Display performance info
454
print(f"Elapsed time: {fps.elapsed():.2f} seconds")
455
print(f"Approx. FPS: {fps.fps():.2f}")
456
457
if __name__ == "__main__":
458
process_video_stream()
459
```