| import cv2 |
| import mediapipe as mp |
| import numpy as np |
|
|
|
|
| def list_connected_cameras(): |
| """ |
| Lists all connected cameras by attempting to open camera indexes sequentially. |
| |
| Returns: |
| list[int]: A list of valid camera indexes. |
| """ |
| index = 0 |
| valid_cameras = [] |
| while True: |
| cap = cv2.VideoCapture(index) |
| if cap.isOpened(): |
| ret, _ = cap.read() |
| if ret: |
| valid_cameras.append(index) |
| cap.release() |
| else: |
| break |
| index += 1 |
| return valid_cameras |
|
|
|
|
| def main(): |
| """ |
| Main function for real-time background removal. It allows the user to: |
| - Select a camera index. |
| - Perform segmentation on the video feed. |
| - Replace the background with a solid green screen. |
| - View the processed output in real-time. |
| """ |
| |
| cameras = list_connected_cameras() |
| if not cameras: |
| print("No cameras found!") |
| return |
|
|
| print("Available camera indexes:", cameras) |
|
|
| |
| cam_index = None |
| while cam_index not in cameras: |
| try: |
| cam_index = int(input(f"Select a camera index from the above list: ")) |
| except ValueError: |
| print("Invalid input. Please enter a valid camera index.") |
|
|
| |
| cap = cv2.VideoCapture(cam_index) |
| if not cap.isOpened(): |
| print(f"Failed to open camera with index {cam_index}") |
| return |
|
|
| |
| mp_selfie_segmentation = mp.solutions.selfie_segmentation |
| selfie_segmentation = mp_selfie_segmentation.SelfieSegmentation(model_selection=1) |
|
|
| |
| bg_color = (0, 255, 0) |
|
|
| |
| prev_blurred_mask = None |
| alpha = 0.6 |
|
|
| |
| erosion_kernel_size = 5 |
| erosion_iterations = 1 |
| erosion_kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (erosion_kernel_size, erosion_kernel_size)) |
|
|
| print("Press 'q' to exit.") |
|
|
| while True: |
| |
| ret, frame = cap.read() |
| if not ret: |
| print("Failed to read from camera. Exiting...") |
| break |
|
|
| |
| rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) |
|
|
| |
| results = selfie_segmentation.process(rgb_frame) |
| mask = results.segmentation_mask |
|
|
| |
| blurred_mask = cv2.GaussianBlur(mask, (15, 15), 0) |
|
|
| |
| if prev_blurred_mask is not None: |
| blurred_mask = alpha * prev_blurred_mask + (1 - alpha) * blurred_mask |
| prev_blurred_mask = blurred_mask |
|
|
| |
| threshold_value = 0.5 |
| condition = blurred_mask > threshold_value |
|
|
| |
| mask_uint8 = (condition.astype(np.uint8)) * 255 |
| eroded_mask = cv2.erode(mask_uint8, erosion_kernel, iterations=erosion_iterations) |
| final_condition = eroded_mask > 128 |
|
|
| |
| bg_frame = np.zeros(frame.shape, dtype=np.uint8) |
| bg_frame[:] = bg_color |
|
|
| |
| output_frame = np.where(final_condition[..., None], frame, bg_frame) |
|
|
| |
| cv2.imshow("Green Background - Eroded Mask", output_frame) |
|
|
| |
| if cv2.waitKey(1) & 0xFF == ord('q'): |
| break |
|
|
| |
| cap.release() |
| cv2.destroyAllWindows() |
|
|
|
|
| if __name__ == "__main__": |
| main() |
|
|