Skip to content

Commit

Permalink
add seupt scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
MateoLostanlen committed Nov 10, 2024
1 parent cb2f13b commit 0240259
Show file tree
Hide file tree
Showing 3 changed files with 292 additions and 1 deletion.
2 changes: 1 addition & 1 deletion pyroengine/sensors.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ def move_in_seconds(self, s: float, operation: str = "Right", speed: int = 20, s
self.move_camera("Stop")
time.sleep(1)
im = self.capture()
if im is not None:
if im is not None and save_path is not None:
im.save(save_path)

def get_ptz_preset(self):
Expand Down
197 changes: 197 additions & 0 deletions src/capture_all_positions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
import argparse
import os
import time

import cv2
import matplotlib.pyplot as plt
import numpy as np
from dotenv import load_dotenv

from pyroengine.sensors import ReolinkCamera


def calculate_shift_time(fov, overlap, cam_speed_1, cam_stop_time, shift_angle=0):
"""
Calculates the shift time based on FOV, overlap, camera speed, stop time, and shift angle.
"""
shift_time = (fov / 2 - (4 * fov - 3 * overlap - 180 + shift_angle) + overlap / 2) / cam_speed_1 - cam_stop_time
return shift_time


def draw_axes_on_image(image, fov):
"""Draws central axes and graduation marks for left and right rotation on the image."""
height, width, _ = image.shape

# Define line positions centrally
line_y_top = height // 3 # Upper third of the image
line_y_bottom = 2 * height // 3 # Lower third of the image

# Draw main lines
cv2.line(image, (0, line_y_top), (width, line_y_top), (255, 255, 255), 3)
cv2.line(image, (0, line_y_bottom), (width, line_y_bottom), (255, 255, 255), 3)

# Font settings for text
font = cv2.FONT_HERSHEY_SIMPLEX
font_scale = 1.5
font_thickness = 2
text_color = (255, 0, 255)

# Add legends
cv2.putText(
image,
"Right Rotation",
(10, line_y_top - 40),
font,
font_scale,
text_color,
font_thickness,
lineType=cv2.LINE_AA,
)
cv2.putText(
image,
"Left Rotation",
(10, line_y_bottom + 60),
font,
font_scale,
text_color,
font_thickness,
lineType=cv2.LINE_AA,
)

# Draw graduation marks for the top line (0 to fov for right rotation)
num_graduations = 10
for i in range(num_graduations + 1):
x_pos = int(i * width / num_graduations)
angle_right = i * (fov / num_graduations)

# Graduation mark
cv2.line(image, (x_pos, line_y_top - 20), (x_pos, line_y_top + 20), (255, 255, 255), 2)

# Label
text = f"{angle_right:.1f}"
(text_width, text_height), _ = cv2.getTextSize(text, font, font_scale, font_thickness)
cv2.putText(
image,
text,
(x_pos - text_width // 2, line_y_top + 40 + text_height),
font,
font_scale,
text_color,
font_thickness,
lineType=cv2.LINE_AA,
)

# Draw graduation marks for the bottom line (from -fov to 0 for left rotation)
for i in range(num_graduations + 1):
x_pos = int(i * width / num_graduations)
angle_left = -fov + i * (fov / num_graduations)

# Graduation mark
cv2.line(image, (x_pos, line_y_bottom - 20), (x_pos, line_y_bottom + 20), (255, 255, 255), 2)

# Label
text = f"{angle_left:.1f}"
(text_width, text_height), _ = cv2.getTextSize(text, font, font_scale, font_thickness)
cv2.putText(
image,
text,
(x_pos - text_width // 2, line_y_bottom - 30),
font,
font_scale,
text_color,
font_thickness,
lineType=cv2.LINE_AA,
)

return image


def main():
"""
Script to control a Reolink camera for specific movements and capture images.
"""
# Load environment variables
load_dotenv()
cam_user = os.getenv("CAM_USER")
cam_pwd = os.getenv("CAM_PWD")

# Argument parsing
parser = argparse.ArgumentParser(
description="Script to control Reolink camera for specific movements and capture images."
)
parser.add_argument("--ip", required=True, help="IP address of the Reolink camera")
parser.add_argument("--username", help="Username for camera access", default=cam_user)
parser.add_argument("--password", help="Password for camera access", default=cam_pwd)
parser.add_argument("--protocol", help="Protocol (http or https)", default="http")
parser.add_argument("--output_folder", help="Folder to save captured images", default="captured_images")
parser.add_argument("--fov", type=float, default=54.2, help="Field of View of the camera")
parser.add_argument("--overlap", type=float, default=6, help="Overlap angle between positions")
parser.add_argument("--cam_speed_1", type=float, default=1.4, help="Camera speed for PTZ operation")
parser.add_argument("--cam_stop_time", type=float, default=0.5, help="Camera stop time after movement")
parser.add_argument(
"--move_duration", type=float, default=34, help="Duration in seconds for the rightward move in each loop"
)
parser.add_argument("--shift_angle", type=float, default=0, help="Shift angle for time calculation adjustment")

args = parser.parse_args()

# Calculate shift time using the provided shift_angle parameter
shift_time = calculate_shift_time(args.fov, args.overlap, args.cam_speed_1, args.cam_stop_time, args.shift_angle)

# Create output directory if it doesn't exist
os.makedirs(args.output_folder, exist_ok=True)

# Initialize camera
camera = ReolinkCamera(ip_address=args.ip, username=args.username, password=args.password, protocol=args.protocol)

try:
# Move to position 10 at speed 64
print("Moving to position 10 at speed 64.")
camera.move_camera(operation="ToPos", speed=64, idx=10)
time.sleep(1)

# Move down for 10 seconds at speed 64
print("Moving down for 10 seconds at speed 64.")
camera.move_in_seconds(s=10, operation="Down", speed=64)

# Move right for calculated shift time at speed 1
print(f"Moving right for {shift_time:.2f} seconds at speed 1.")
camera.move_in_seconds(s=shift_time, operation="Right", speed=1)

# Loop to capture, register PTZ positions, and move right
for i in range(8):
# Capture image
print(f"Loop {i+1}/8: Capturing image.")
image = camera.capture()
if image:
# Convert the image to an OpenCV-compatible format
image_np = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR)

# Draw axes on the image
image_np = draw_axes_on_image(image_np, args.fov)

# Save the modified image
filename = f"im_{args.ip.split('.')[-1]}_{i}.jpg"
image_path = os.path.join(args.output_folder, filename)
cv2.imwrite(image_path, image_np)
print(f"Image saved at {image_path}")
else:
print("Failed to capture image.")

# Register PTZ position from 20 to 27
ptz_position = 20 + i
print(f"Registering PTZ position {ptz_position}.")
camera.set_ptz_preset(idx=ptz_position)

# Move right for specified duration at speed 1
print(f"Moving right for {args.move_duration} seconds at speed 1.")
camera.move_in_seconds(s=args.move_duration, operation="Right", speed=1)

time.sleep(1)

except Exception as e:
print(f"An error occurred: {e}")


if __name__ == "__main__":
main()
94 changes: 94 additions & 0 deletions src/setup_positions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import argparse
import os
import time

import cv2
import numpy as np
from dotenv import load_dotenv

from pyroengine.sensors import ReolinkCamera


def main():
"""
Script to set up camera positions by moving to specific poses, capturing images,
and saving them with new pose IDs.
Mapping:
- Move to pose 22 and save as pose_id 0
- Move to pose 23 and save as pose_id 1
- Move to pose 24 and save as pose_id 2
- Move to pose 25 and save as pose_id 3
After saving, if demo mode is enabled, moves to each pose in sequence at speed 64 with a 2-second pause, repeating 3 times.
"""
# Load environment variables
load_dotenv()
cam_user = os.getenv("CAM_USER")
cam_pwd = os.getenv("CAM_PWD")

# Argument parsing
parser = argparse.ArgumentParser(
description="Set up camera positions by saving specific poses to new pose IDs and capturing images."
)
parser.add_argument("--ip", required=True, help="IP address of the Reolink camera")
parser.add_argument("--username", help="Username for camera access", default=cam_user)
parser.add_argument("--password", help="Password for camera access", default=cam_pwd)
parser.add_argument("--protocol", help="Protocol (http or https)", default="http")
parser.add_argument("--output_folder", help="Folder to save captured images", default="captured_positions")
parser.add_argument("--demo", action="store_true", help="If set, demo mode is activated")

args = parser.parse_args()

output_folder = f"{args.output_folder}/{args.ip.split('.')[-1]}"

# Create output directory if it doesn't exist
os.makedirs(output_folder, exist_ok=True)

# Initialize camera
camera = ReolinkCamera(ip_address=args.ip, username=args.username, password=args.password, protocol=args.protocol)

# Mapping of original poses to new pose IDs
pose_mapping = {22: 0, 23: 1, 24: 2, 25: 3}

try:
# First, move to each pose, capture an image, and save it as a new pose ID
for original_pose, new_pose_id in pose_mapping.items():
print(f"Moving to original pose {original_pose} at speed 64...")
camera.move_camera(operation="ToPos", speed=64, idx=original_pose)
time.sleep(2) # Allow time for the camera to move

# Capture an image at the position
print(f"Capturing image for new pose ID {new_pose_id}...")
image = camera.capture()
if image:
# Convert image to OpenCV-compatible format and save it
image_np = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR)
filename = f"pose_{new_pose_id}.jpg"
image_path = os.path.join(output_folder, filename)
cv2.imwrite(image_path, image_np)
print(f"Image saved at {image_path}")
else:
print(f"Failed to capture image for pose ID {new_pose_id}.")

# Save the position as a new pose ID
print(f"Saving current position as new pose ID {new_pose_id}...")
camera.set_ptz_preset(idx=new_pose_id)
print(f"Position saved with new pose ID {new_pose_id}.")
time.sleep(1)

# If demo mode is enabled, go through each pose three times with a 2-second pause
if args.demo:
print("Running in demo mode...")
for _ in range(3): # Loop three times
for original_pose in pose_mapping.keys():
print(f"Moving to pose {original_pose} at speed 64 for demo...")
camera.move_camera(operation="ToPos", speed=64, idx=original_pose)
time.sleep(2) # Pause for 2 seconds at each pose

except Exception as e:
print(f"An error occurred: {e}")


if __name__ == "__main__":
main()

0 comments on commit 0240259

Please sign in to comment.