-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfcamera.py
More file actions
140 lines (112 loc) · 4 KB
/
fcamera.py
File metadata and controls
140 lines (112 loc) · 4 KB
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
import cv2
import numpy as np
class Camera:
"""
A simple wrapper around OpenCV's VideoCapture for camera operations.
Provides methods for initialization, frame acquisition, exposure/gain control,
and resource cleanup.
"""
def __init__(self, cam_num: int = 0):
"""
Initialize the Camera object.
Parameters
----------
cam_num : int
Index of the camera device (default is 0).
"""
self.cam_num = cam_num
self.cap = None
self.frame = np.zeros((1, 1), dtype=np.uint8)
self.first_frame = None
self.first_shape = None
self.shape = None
def initialize(self) -> bool:
"""
Initialize the camera and capture the first frame.
Returns
-------
bool
True if initialization succeeded, False otherwise.
"""
self.cap = cv2.VideoCapture(self.cam_num)
if not self.cap.isOpened():
raise RuntimeError(f"Unable to open camera {self.cam_num}")
ret, self.first_frame = self.cap.read()
if not ret or self.first_frame is None:
raise RuntimeError("Failed to read initial frame from camera")
self.first_shape = self.first_frame.shape
# print(f"Camera {self.cam_num} initialized with frame shape: {self.first_shape}")
return True
def get_frame(self) -> np.ndarray:
"""
Capture a single frame from the camera.
Returns
-------
np.ndarray
The captured frame.
"""
if self.cap is None:
raise RuntimeError("Camera not initialized. Call initialize() first.")
ret, self.frame = self.cap.read()
if ret and self.frame is not None:
self.shape = self.frame.shape
# Ensure frame shape matches the first frame
if np.array_equal(self.shape, self.first_shape):
return self.frame
# Fallback to first frame if capture fails
return self.first_frame
def acquire_movie(self, num_frames: int = 10) -> list[np.ndarray]:
"""
Capture a sequence of frames.
Parameters
----------
num_frames : int
Number of frames to capture.
Returns
-------
list[np.ndarray]
List of captured frames.
"""
return [self.get_frame() for _ in range(num_frames)]
def set_exposure(self, value: float) -> None:
"""Set camera exposure (mapped to brightness in OpenCV)."""
if self.cap:
self.cap.set(cv2.CAP_PROP_BRIGHTNESS, value)
def get_exposure(self) -> float:
"""Get current camera exposure (mapped to brightness in OpenCV)."""
if self.cap:
return self.cap.get(cv2.CAP_PROP_BRIGHTNESS)
return -1.0
def set_gain(self, value: float) -> None:
"""Set camera gain."""
if self.cap:
self.cap.set(cv2.CAP_PROP_GAIN, value)
def get_gain(self) -> float:
"""Get current camera gain."""
if self.cap:
return self.cap.get(cv2.CAP_PROP_GAIN)
return -1.0
def release(self) -> None:
"""Release the camera resource."""
if self.cap:
self.cap.release()
self.cap = None
def __str__(self) -> str:
return f"OpenCV Camera {self.cam_num}"
if __name__ == "__main__":
cam = Camera(0)
try:
print("Initializing camera...")
cam.initialize()
print(cam)
frame = cam.get_frame()
print("Captured frame shape:", frame.shape)
cam.set_exposure(0.5)
print("Exposure set to:", cam.get_exposure())
cam.set_gain(1.0)
print("Gain set to:", cam.get_gain())
movie = cam.acquire_movie(5)
print("Captured movie with", len(movie), "frames")
finally:
cam.release()
print("Camera released.")