-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcamera.py
More file actions
133 lines (112 loc) · 4.86 KB
/
camera.py
File metadata and controls
133 lines (112 loc) · 4.86 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
from datetime import datetime
from pathlib import Path
from typing import Optional, Union
import cv2
import numpy as np
class CameraInterface:
def __init__(self, camera_address: Union[int, str] = 1) -> None:
self.camera_address = self._validate_camera_address(camera_address)
@staticmethod
def _validate_camera_address(camera_address: Union[int, str]) -> Union[int, str]:
try:
return int(camera_address)
except (ValueError, TypeError):
return camera_address
def _open_camera(self) -> cv2.VideoCapture:
camera = cv2.VideoCapture(self.camera_address, cv2.CAP_DSHOW)
#camera.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc(*"MJPG"))
if not camera.isOpened():
raise Exception("Unable to connect to camera")
return camera
def _close_camera(self, camera: cv2.VideoCapture) -> None:
if camera is not None and camera.isOpened():
camera.release()
def test_connection(self) -> bool:
try:
camera = self._open_camera()
self._close_camera(camera)
return True
except Exception:
return False
def take_picture(self, focus: Optional[int] = None, autofocus: Optional[bool] = None) -> Path:
camera = None
try:
camera = self._open_camera()
if focus is not None or autofocus is not None:
self._adjust_focus_settings_unlocked(camera, focus, autofocus)
success, frame = camera.read()
if not success:
raise Exception("Unable to read from camera")
filename = datetime.now().strftime("microscope_%Y%m%d_%H%M%S.jpg")
image_path = Path(filename)
cv2.imwrite(str(image_path), frame)
return image_path
finally:
if camera is not None:
self._close_camera(camera)
def get_average_color_from_rectangle(
self, x: int, y: int, width: int, height: int,
focus: Optional[int] = None, autofocus: Optional[bool] = None,
) -> dict:
camera = None
try:
camera = self._open_camera()
if focus is not None or autofocus is not None:
self._adjust_focus_settings_unlocked(camera, focus, autofocus)
success, frame = camera.read()
if not success:
raise Exception("Unable to read from camera")
roi = frame[y:y + height, x:x + width]
if roi.size == 0:
raise ValueError("Rectangle is outside the image area")
avg_bgr = np.mean(roi, axis=(0, 1))
b, g, r = avg_bgr.astype(int)
hex_color = "#{:02x}{:02x}{:02x}".format(r, g, b)
return {"rgb": (r, g, b), "bgr": (b, g, r), "hex": hex_color}
finally:
if camera is not None:
self._close_camera(camera)
def _adjust_focus_settings_unlocked(
self, camera: cv2.VideoCapture,
focus: Optional[int] = None, autofocus: Optional[bool] = None,
) -> None:
if camera is None or not camera.isOpened():
raise Exception("Camera is not connected")
focus_changed = False
if autofocus is not None:
current_autofocus = camera.get(cv2.CAP_PROP_AUTOFOCUS)
if current_autofocus != (1 if autofocus else 0):
camera.set(cv2.CAP_PROP_AUTOFOCUS, 1 if autofocus else 0)
focus_changed = True
if not autofocus and focus is not None:
if focus < 0 or focus > 255:
raise ValueError("Focus value must be between 0 and 255.")
current_focus = camera.get(cv2.CAP_PROP_FOCUS)
if current_focus != focus:
camera.set(cv2.CAP_PROP_FOCUS, focus)
focus_changed = True
if focus_changed:
for _ in range(30):
camera.read()
else:
for _ in range(5):
camera.read()
if __name__ == "__main__":
print("Starting camera test...")
try:
camera = CameraInterface(camera_address=1)
print("Testing camera connection...")
if camera.test_connection():
print("Camera connected successfully.")
else:
print("Camera connection failed.")
exit()
print("Taking picture...")
image_path = camera.take_picture()
print(f"Picture saved to: {image_path}")
color_result = camera.get_average_color_from_rectangle(x=200, y=150, width=100, height=100)
print(f"Average RGB color: {color_result['rgb']}")
print(f"Average BGR color: {color_result['bgr']}")
print(f"HEX color: {color_result['hex']}")
except Exception as e:
print(f"ERROR: {e}")