Skip to content

Easy-to-use library for accessing to a camera streaming from Python. Internally, it acts as a wrapper of cv2.VideoCapture, that include several out-of-the-box utilities that are commonly needed in production Computer Vision projects

License

Notifications You must be signed in to change notification settings

Eric-Canas/webcam

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

56 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Webcam

webcam Webcam is a simple, yet powerful Python library that brings advanced webcam handling to your projects. Implemented under the same interface than cv2.VideoCapture, it heavily simplifies high-level frame manipulation, providing an intuitive and versatile way to handle video input from a range of sources like webcams, IP cameras, and video files.

With Webcam, you can easily control the frame size, adjust the aspect ratio, and apply Perspective Transforms to the video stream, all while preserving crucial information about pixel origin and magnification.

Furthermore, it includes a unique aspect that allows users to authentically mirror webcam input using video files. It ensures that the frame accessed at any particular moment matches the exact frame you'd encounter in a real-time webcam stream, making it a valuable tool for testing and development.

Designed for simplicity and user-friendliness, Webcam provides advanced features without compromising ease of use. This allows you to channel your efforts into developing your application, instead of wrestling with webcam control and frame manipulation details..

Advanced Functionality

Webcam showcases a rich set of features, advancing beyond fundamental webcam manipulation to offer a higher degree of control and flexibility:

  • Enhanced Input Sources: Webcam seamlessly handles all input types that OpenCV accepts, but with added versatility. Including webcams, IP cameras (using RTSP URLs), and video files.

  • Customizable Frame Configuration: With Webcam, you can define the specific frame size and manage aspect ratio changes when the camera's native resolution differs. Keep the widest field of view by setting just one dimension, or set both and decide between center cropping or resizing (sacrificing aspect ratio).

  • Perspective Transform: Initialize the Webcam object with a Homography Matrix to maintain consistent perspective correction in every frame, while keeping the specified frame size. If the perspective is deformed, you have the choice to crop the frame, removing black borders, or display the entire trapezoid to avoid losing any information.

  • Reversibility: Webcam can easily retrieve original coordinates and pixel magnification for any point or section of the image. This is a valuable feature for Computer Vision Engineers needing to perform calculations based on the raw camera sensor data.

  • Background Reading: Enhances performance by reading frames in a background thread, with an option to limit the frame rate.

  • Webcam Input Emulation: You can use video files to accurately emulate webcam input. The frame you access at any instant will match the one from a real-time webcam stream at the same time. Especially handy for testing and development scenarios.

  • Iterator and Batch Processing: Webcam offers an iterator for simplified camera frame reading, with optional batch yielding for efficient data handling.

Balancing simplicity and advanced functionality, Webcam is an efficient, flexible tool for webcam integration.

Installation

You can install Webcam with

pip install webcam

Usage

Reading a video stream is as simple as iterating over the defined webcam object.

from webcam import Webcam

# Define a simple webcam object that will get video stream from webcam (src=0),
#  with a frame width of 640 (auto setting heigth to keep original aspect ratio)
webcam = Webcam(src=0, w=640)
print(f"Frame size: {webcam.w} x {webcam.h}")


for frame in webcam:
    # Show the frames in a cv2 window
    cv2.imshow('Webcam Frame', cv2.cvtColor(frame, cv2.COLOR_RGB2BGR))
    # Break the loop if the user presses the 'q' key
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
>>> Frame size: 360 x 640

Fitting to a strict frame size

Sometimes, your Apps or Computer Vision Models might need specific frame sizes that don't align with your video source's resolution. Webcam frees the user of having to deal with these frame resize details, especially when there's a discrepancy in the aspect ratio between the input and output.

import os
from webcam import Webcam

# Let's use a video as a source instead of webcam
video_source = os.path.join('resources', 'test_video.mp4')

# Set an expected width and height, defining that "if aspect ratio differs", center crop the image.
no_deformation = Webcam(src=video_source, w=640, h=640, on_aspect_ratio_lost='crop')

# Replicate the situation, but defining that, "if aspect ratio differs", resize it, accepting the produced deformation.
deformation = Webcam(src=video_source, w=640, h=640, on_aspect_ratio_lost='resize')

# ---------------------------------------------------------------------------------------------------

# Print the original video resolution (output resolution will be 640 x 640 as specified)
print(f"Original WxH: {no_deformation.raw_w} x {no_deformation.raw_h}\n")

# Print the magnification in both cases (Cropped one will have a higher magnification on the input's shortest axis)
print(f"Resize WxH Magnification: {deformation.pixel_magnification_w} x {deformation.pixel_magnification_h}")
print(f"Center Crop WxH Magnification: {no_deformation.pixel_magnification_w} x {no_deformation.pixel_magnification_h}")

# Read the frames just as you would do it on OpenCV
grabbed, non_deformed_frame = no_deformation.read()
grabbed, deformed_frame = deformation.read()
Original WxH: 1280 x 720

Resize WxH Magnification: 0.50 x 0.89
Center Crop WxH Magnification: 0.89 x 0.89
Input Frame (1280x720) Resized (640x640) Center Crop (640x640)

Applying Perspective Corrections

You can setup Homography Matrices to automatically apply perspective transforms. Wether if you apply them or not, you can keep the track of the origin of every coordinate in the raw sensor image.

from webcam import Webcam

# Build an homography matrix that modifies the image perspective
homography_matrix = [[1., 0.1, 0.],
                     [0.1, 1., 0.],
                     [0.0002, -0.0001, 1.]]

# Build a webcam object passing this homography matrix (let's set a fixed height and let it decide width).
full_perspective = Webcam(src=video_source, h=640, homography_matrix=homography_matrix, crop_on_warping=False)
no_borders = Webcam(src=video_source, h=640, homography_matrix=homography_matrix, crop_on_warping=True)

# ---------------------------------------------------------------------------------------------------

# Let's calculate the origin of some coordinates in the raw input resolution (Note it expects a batch).
full_pers_x, full_pers_y = full_perspective.output_space_points_to_input_space(points_xy=((150, 225),))[0]
no_borders_x, no_borders_y = no_borders.output_space_points_to_input_space(points_xy=((625, 200), ))[0]

# Let's calculate the precise pixel magnification of two coords in an image. As perspective deformations
#  does not produce homogeneus magnifications as would happen when only resizes and/or crops are applied
no_borders_h_left, no_borders_w_left = no_borders.get_magnification_hw(x=150, y=225)
no_borders_h_right, no_borders_w_right = no_borders.get_magnification_hw(x=600, y=225)

print(f"Maginfication WxH at (150, 225): {no_borders_w_left} x {no_borders_h_left}")
print(f"Maginfication WxH at (600, 225): {no_borders_w_right} x {no_borders_h_right}\n")

print(f"Full Perspective: (150, 225) came from ({full_pers_x}, {full_pers_y})")
print(f"Cropped Perspective: (625, 200) came from ({no_borders_x}, {no_borders_y})")
>>> Maginfication WxH at (150, 225): 1.064 x 0.999
>>> Maginfication WxH at (600, 225): 0.984 x 0.842

>>> Full Perspective: (150, 225) came from (156.63, 258.30)
>>> Cropped Perspective: (625, 200) came from (733.69, 255.35)
Input Frame (1280x720) Full Perspective (943x640) Hidding Borders (980x640)

Limiting maximum frame rate

Sometimes, you'll need to simulate a fixed frame rate (for example, when you want to write video files). For these cases, you can limit the maximum frame rate. It will transform the frame retrieval in a blockant operation, making sure that you don't surpass the specified frame rate.

from webcam import Webcam

# Build a webcam object that will limit frame rate to a maximum of 12 fps (get it as BGR).
webcam_12_fps = Webcam(src=video_source, max_frame_rate=12, as_bgr=True, simulate_webcam=True)

# ---------------------------------------------------------------------------------------------------

# Write the video on a .mp4 file that requires a fixed pre-known frame rate
video_writer = cv2.VideoWriter(filename='test.mp4', fourcc=cv2.VideoWriter_fourcc(*'mp4v'),
                               fps=12, frameSize=(webcam_12_fps.w, webcam_12_fps.h))

for frame in webcam_12_fps:
    video_writer.write(frame)
video_writer.release()
5 FPS (1280x720) 12 FPS (1280x720)

About

Easy-to-use library for accessing to a camera streaming from Python. Internally, it acts as a wrapper of cv2.VideoCapture, that include several out-of-the-box utilities that are commonly needed in production Computer Vision projects

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages