Skip to content

Commit 083edd1

Browse files
committed
Optimize camera properties, add camera warm up and verification, optimized quality settings
1 parent 3a5dcb2 commit 083edd1

File tree

1 file changed

+76
-27
lines changed

1 file changed

+76
-27
lines changed

coffee_ws/src/coffee_head/coffee_head/camera_node.py

Lines changed: 76 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -31,17 +31,32 @@ class FrameGrabber(QObject):
3131
def __init__(self, node=None):
3232
super().__init__()
3333
self.node = node
34+
# Camera properties
3435
self.camera = None
3536
self.camera_index = 0
37+
self.frame_width = 640
38+
self.frame_height = 480
39+
self.backend = cv2.CAP_ANY
40+
41+
# Camera optimization settings
42+
self.target_fps = 30
43+
self.target_exposure = 100 # Auto exposure target (0-255)
44+
self.camera_props = {
45+
cv2.CAP_PROP_FRAME_WIDTH: self.frame_width,
46+
cv2.CAP_PROP_FRAME_HEIGHT: self.frame_height,
47+
cv2.CAP_PROP_FPS: self.target_fps,
48+
cv2.CAP_PROP_BUFFERSIZE: 1, # Minimal latency
49+
cv2.CAP_PROP_AUTOFOCUS: 0, # Disable autofocus
50+
cv2.CAP_PROP_AUTO_EXPOSURE: 1, # Enable auto exposure
51+
cv2.CAP_PROP_AUTO_WB: 1, # Enable auto white balance
52+
cv2.CAP_PROP_EXPOSURE: self.target_exposure,
53+
}
3654
self.running = False
3755
self.lock = threading.Lock()
3856
self.capture_thread = None
3957
self.process_thread = None
4058
self.publish_thread = None
41-
self.frame_width = 1280 # Default to 720p (16:9)
42-
self.frame_height = 720
4359
self.high_quality = False
44-
self.backend = cv2.CAP_ANY # Default backend
4560

4661
# Initialize shared frame buffer
4762
self.current_frame = None
@@ -324,21 +339,40 @@ def stop(self):
324339
self.camera = None
325340

326341
def set_quality(self, high_quality):
327-
"""Toggle between low resolution and high resolution"""
328-
with self.lock:
329-
if high_quality:
330-
self.frame_width = 1920
331-
self.frame_height = 1080
332-
else:
333-
# Keep these values low to reduce latency
334-
self.frame_width = 1280
335-
self.frame_height = 720
336-
self.high_quality = high_quality
342+
"""Toggle between low resolution and high resolution with optimal settings"""
343+
if high_quality:
344+
self.frame_width = 1280
345+
self.frame_height = 720
346+
self.target_fps = 24 # Lower FPS for higher resolution
347+
else:
348+
self.frame_width = 640
349+
self.frame_height = 480
350+
self.target_fps = 30 # Higher FPS for lower resolution
351+
352+
# Update camera properties
353+
self.camera_props.update({
354+
cv2.CAP_PROP_FRAME_WIDTH: self.frame_width,
355+
cv2.CAP_PROP_FRAME_HEIGHT: self.frame_height,
356+
cv2.CAP_PROP_FPS: self.target_fps
357+
})
358+
359+
if self.camera and self.camera.isOpened():
360+
# Apply new settings
361+
for prop, value in self.camera_props.items():
362+
try:
363+
self.camera.set(prop, value)
364+
except:
365+
pass
337366

338-
# Re-initialize the camera with the new settings
339-
if self.camera and self.camera.isOpened():
340-
self.camera.set(cv2.CAP_PROP_FRAME_WIDTH, self.frame_width)
341-
self.camera.set(cv2.CAP_PROP_FRAME_HEIGHT, self.frame_height)
367+
# Verify new settings
368+
actual_width = int(self.camera.get(cv2.CAP_PROP_FRAME_WIDTH))
369+
actual_height = int(self.camera.get(cv2.CAP_PROP_FRAME_HEIGHT))
370+
actual_fps = self.camera.get(cv2.CAP_PROP_FPS)
371+
372+
print(f"Quality changed to: {actual_width}x{actual_height} @ {actual_fps:.1f} FPS")
373+
374+
# Update UI with blank frame of new size
375+
self.frame_ready.emit(np.zeros((self.frame_height, self.frame_width, 3), dtype=np.uint8))
342376

343377
def toggle_face_detection(self, enable):
344378
"""Enable or disable face detection"""
@@ -568,17 +602,32 @@ def _capture_loop(self):
568602
self.error.emit(f"Failed to open camera: {error_msg}")
569603
return
570604

571-
# Configure camera
572-
self.camera.set(cv2.CAP_PROP_FRAME_WIDTH, self.frame_width)
573-
self.camera.set(cv2.CAP_PROP_FRAME_HEIGHT, self.frame_height)
574-
self.camera.set(cv2.CAP_PROP_BUFFERSIZE, 1) # Minimal latency
605+
# Configure camera with optimal settings
606+
for prop, value in self.camera_props.items():
607+
try:
608+
self.camera.set(prop, value)
609+
except:
610+
pass # Skip unsupported properties
611+
612+
# Verify and adjust settings
613+
actual_width = int(self.camera.get(cv2.CAP_PROP_FRAME_WIDTH))
614+
actual_height = int(self.camera.get(cv2.CAP_PROP_FRAME_HEIGHT))
615+
actual_fps = self.camera.get(cv2.CAP_PROP_FPS)
575616

576-
# Optional camera properties
577-
try:
578-
self.camera.set(cv2.CAP_PROP_AUTOFOCUS, 0) # Disable autofocus
579-
self.camera.set(cv2.CAP_PROP_FPS, 30) # Request 30 FPS
580-
except:
581-
pass # Some cameras don't support these
617+
print(f"Camera configured with: {actual_width}x{actual_height} @ {actual_fps:.1f} FPS")
618+
619+
# Warm up the camera
620+
for _ in range(5):
621+
self.camera.read()
622+
623+
# Read a test frame to check actual size
624+
ret, frame = self.camera.read()
625+
if ret:
626+
frame_h, frame_w = frame.shape[:2]
627+
if frame_w != actual_width or frame_h != actual_height:
628+
print(f"Warning: Actual frame size ({frame_w}x{frame_h}) differs from requested ({actual_width}x{actual_height})")
629+
self.frame_width = frame_w
630+
self.frame_height = frame_h
582631

583632
# Main capture loop
584633
while self.running:

0 commit comments

Comments
 (0)