Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions examples/capture_old_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@

import time

from picamera2 import Picamera2
from picamera2 import Picamera2, Preview

picam2 = Picamera2()
capture_config = picam2.create_still_configuration()
picam2.start(show_preview=True)
picam2.start(preview=Preview.auto())

time.sleep(1)

Expand Down
4 changes: 2 additions & 2 deletions examples/imx500/imx500_classification_demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import cv2
import numpy as np

from picamera2 import CompletedRequest, MappedArray, Picamera2
from picamera2 import CompletedRequest, MappedArray, Picamera2, Preview
from picamera2.devices import IMX500
from picamera2.devices.imx500 import NetworkIntrinsics
from picamera2.devices.imx500.postprocess import softmax
Expand Down Expand Up @@ -146,7 +146,7 @@ def get_args():
config = picam2.create_preview_configuration(controls={"FrameRate": intrinsics.inference_rate}, buffer_count=12)

imx500.show_network_fw_progress_bar()
picam2.start(config, show_preview=True)
picam2.start(config, preview=Preview.auto())
if intrinsics.preserve_aspect_ratio:
imx500.set_auto_aspect_ratio()
# Register the callback to parse and draw classification results
Expand Down
4 changes: 2 additions & 2 deletions examples/imx500/imx500_object_detection_demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import cv2
import numpy as np

from picamera2 import MappedArray, Picamera2
from picamera2 import MappedArray, Picamera2, Preview
from picamera2.devices import IMX500
from picamera2.devices.imx500 import (NetworkIntrinsics,
postprocess_nanodet_detection)
Expand Down Expand Up @@ -168,7 +168,7 @@ def get_args():
config = picam2.create_preview_configuration(controls={"FrameRate": intrinsics.inference_rate}, buffer_count=12)

imx500.show_network_fw_progress_bar()
picam2.start(config, show_preview=True)
picam2.start(config, preview=Preview.auto())

if intrinsics.preserve_aspect_ratio:
imx500.set_auto_aspect_ratio()
Expand Down
2 changes: 1 addition & 1 deletion examples/imx500/imx500_object_detection_demo_mp.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ def get_args():
config = picam2.create_preview_configuration(main, controls={"FrameRate": intrinsics.inference_rate}, buffer_count=12)

imx500.show_network_fw_progress_bar()
picam2.start(config, show_preview=False)
picam2.start(config)
if intrinsics.preserve_aspect_ratio:
imx500.set_auto_aspect_ratio()

Expand Down
4 changes: 2 additions & 2 deletions examples/imx500/imx500_pose_estimation_higherhrnet_demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import numpy as np

from picamera2 import CompletedRequest, MappedArray, Picamera2
from picamera2 import CompletedRequest, MappedArray, Picamera2, Preview
from picamera2.devices.imx500 import IMX500, NetworkIntrinsics
from picamera2.devices.imx500.postprocess import COCODrawer
from picamera2.devices.imx500.postprocess_highernet import \
Expand Down Expand Up @@ -109,7 +109,7 @@ def get_drawer():
config = picam2.create_preview_configuration(controls={'FrameRate': intrinsics.inference_rate}, buffer_count=12)

imx500.show_network_fw_progress_bar()
picam2.start(config, show_preview=True)
picam2.start(config, preview=Preview.auto())
imx500.set_auto_aspect_ratio()
picam2.pre_callback = picamera2_pre_callback

Expand Down
4 changes: 2 additions & 2 deletions examples/imx500/imx500_segmentation_demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import numpy as np

from picamera2 import CompletedRequest, Picamera2
from picamera2 import CompletedRequest, Picamera2, Preview
from picamera2.devices import IMX500
from picamera2.devices.imx500 import NetworkIntrinsics

Expand Down Expand Up @@ -94,7 +94,7 @@ def get_args():
picam2 = Picamera2(imx500.camera_num)
config = picam2.create_preview_configuration(controls={'FrameRate': intrinsics.inference_rate}, buffer_count=12)
imx500.show_network_fw_progress_bar()
picam2.start(config, show_preview=True)
picam2.start(config, preview=Preview.auto())
picam2.pre_callback = create_and_draw_masks

while True:
Expand Down
4 changes: 2 additions & 2 deletions examples/stereo_preview.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import time
from threading import Lock

from picamera2 import MappedArray, Picamera2, libcamera
from picamera2 import MappedArray, Picamera2, Preview, libcamera

cam2_request = None
lock = Lock()
Expand Down Expand Up @@ -57,7 +57,7 @@ def save_request(request):
controls={"ScalerCrop": (0, 0, picam2a.sensor_resolution[0], picam2a.sensor_resolution[1])}
)
picam2a.configure(main_config)
picam2a.start_preview(True)
picam2a.start_preview(Preview.auto())

# Configure as half frame normally
picam2b = Picamera2(1)
Expand Down
4 changes: 2 additions & 2 deletions examples/still_capture_with_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import time

from picamera2 import Picamera2
from picamera2 import Picamera2, Preview

picam2 = Picamera2()

Expand All @@ -15,7 +15,7 @@
picam2.still_configuration.enable_raw()
picam2.still_configuration.raw.size = picam2.sensor_resolution

picam2.start("preview", show_preview=True)
picam2.start("preview", preview=Preview.auto())
time.sleep(2)

picam2.switch_mode_and_capture_file("still", "test_full.jpg")
4 changes: 2 additions & 2 deletions examples/title_bar.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

import time

from picamera2 import Picamera2
from picamera2 import Picamera2, Preview

picam2 = Picamera2()
picam2.start(show_preview=True)
picam2.start(preview=Preview.auto())
time.sleep(0.5)

# Or you could do this before starting the camera.
Expand Down
121 changes: 61 additions & 60 deletions picamera2/picamera2.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,19 @@ class Preview(Enum):
DRM = DrmPreview
QT = QtPreview
QTGL = QtGlPreview
NO = None

@staticmethod
def auto():
# Crude attempt at "autodetection" but which will mostly (?) work. We will
# probably find situations that need fixing, VNC perhaps.
display = os.getenv('DISPLAY')
if display is None:
return Preview.DRM
elif display.startswith(':'):
return Preview.QTGL
else:
return Preview.QT


class GlobalCameraInfo(TypedDict):
Expand Down Expand Up @@ -578,34 +591,26 @@ def start_preview(self, preview=None, **kwargs) -> None:
"""
Start the given preview which drives the camera processing.

The preview may be either:
None or False - in which case a NullPreview is made,
True - which we hope in future to use to autodetect
a Preview enum value - in which case a preview of that type is made,
or an actual preview object.

When using the enum form, extra keyword arguments can be supplied that
will be forwarded to the preview class constructor.
preview - a Preview enum or an actual preview object.
Pass Preview.auto() to autodetect. Defaults to NullPreview.
Additional keyword arguments may be supplied which will be
forwarded to the preview class constructor.
"""
if self._event_loop_running:
raise RuntimeError("An event loop is already running")
if isinstance(preview, bool):
_log.error("Passing bool to preview parameter is deprecated")
preview = Preview.auto() if preview else None

if preview is True:
# Crude attempt at "autodetection" but which will mostly (?) work. We will
# probably find situations that need fixing, VNC perhaps.
display = os.getenv('DISPLAY')
if display is None:
preview = Preview.DRM.value(**kwargs)
elif display.startswith(':'):
preview = Preview.QTGL.value(**kwargs)
else:
preview = Preview.QT.value(**kwargs)
elif preview is False or preview is None:
preview = Preview.NULL.value(**kwargs)
if preview is None:
preview = NullPreview(**kwargs)
elif isinstance(preview, Preview):
if preview is Preview.NO:
return
preview = preview.value(**kwargs)
# Assume it's already a preview object.

if self._event_loop_running:
raise RuntimeError("An event loop is already running")

# The preview windows call the attach_preview method.
self._preview_stopped.clear()
preview.start(self)
Expand Down Expand Up @@ -1183,32 +1188,27 @@ def start_(self):
_log.info("Camera started")
self.started = True

def start(self, config=None, show_preview=False) -> None:
def start(self, config=None, show_preview=False, preview=None) -> None:
"""
Start the camera system running.

Camera controls may be sent to the camera before it starts running.

The following parameters may be supplied:
config - Camera configuration to be set. Defaults to 'preview' configuration.
Note: if the camera is already configured, this has no effect.

config - if not None this is used to configure the camera. This is just a
convenience so that you don't have to call configure explicitly.

show_preview - whether to show a preview window. You can pass in the preview
type or True to attempt to autodetect. If left as False you'll get no
visible preview window but the "NULL preview" will still be run. The
value None would mean no event loop runs at all and you would have to
implement your own.
preview - A Preview enum or an actual preview object.
Pass Preview.auto() to autodetect. Defaults to NullPreview.
Note: if an event loop is already running, this parameter has no effect.
"""
if not self.camera_config and config is None:
config = "preview"
if config is not None:
self.configure(config)
if preview is None and show_preview is not False:
_log.error("show_preview is deprecated, use preview instead")
preview = Preview.NO if show_preview is None else show_preview

if not self.camera_config:
raise RuntimeError("Camera has not been configured")
# By default we will create an event loop if there isn't one running already.
if show_preview is not None and not self._event_loop_running:
self.start_preview(show_preview)
self.configure(config)
if not self._event_loop_running:
self.start_preview(preview)
self.start_()

def cancel_all_and_flush(self) -> None:
Expand Down Expand Up @@ -2394,7 +2394,7 @@ def set_overlay(self, overlay) -> None:
def start_and_capture_files(self, name="image{:03d}.jpg",
initial_delay=1, preview_mode="preview",
capture_mode="still", num_files=1, delay=1,
show_preview=True, exif_data=None) -> None:
show_preview=True, exif_data=None, preview=None) -> None:
"""This function makes capturing multiple images more convenient.

Should only be used in command line line applications (not from a Qt application, for example).
Expand All @@ -2417,34 +2417,35 @@ def start_and_capture_files(self, name="image{:03d}.jpg",

delay - the time delay for every capture after the first (default 1s).

show_preview - whether to show a preview window (default: yes). The preview window only
displays an image by default during the preview phase, so if captures are back-to-back
with delay zero, then there may be no images shown. This parameter only has any
effect if a preview is not already running. If it is, it would have to be stopped first
(with the stop_preview method).
preview - which preview to start (current-default: auto-detect; in-future: NullPreview).
The preview window only displays an image by default during the preview phase,
so if captures are back-to-back with delay zero, then there may be no images shown.
Note: if a preview is already running, this parameter has no effect.

exif_data - dictionary containing user defined exif data (based on `piexif`). This will
overwrite existing exif information generated by picamera2.
"""
_log.warning("FutureWarning: Parameter preview will default to NullPreview in a future release")

if self.started:
self.stop()
if delay:
# Show a preview between captures, so we will switch mode and back for each capture.
self.configure(preview_mode)
self.start(show_preview=show_preview)
self.start(show_preview=show_preview, preview=preview)
for i in range(num_files):
time.sleep(initial_delay if i == 0 else delay)
self.switch_mode_and_capture_file(capture_mode, name.format(i), exif_data=exif_data)
else:
# No preview between captures, it's more efficient just to stay in capture mode.
if initial_delay:
self.configure(preview_mode)
self.start(show_preview=show_preview)
self.start(show_preview=show_preview, preview=preview)
time.sleep(initial_delay)
self.switch_mode(capture_mode)
else:
self.configure(capture_mode)
self.start(show_preview=show_preview)
self.start(show_preview=show_preview, preview=preview)
for i in range(num_files):
self.capture_file(name.format(i), exif_data=exif_data)
if i == num_files - 1:
Expand All @@ -2453,7 +2454,7 @@ def start_and_capture_files(self, name="image{:03d}.jpg",
self.stop()

def start_and_capture_file(self, name="image.jpg", delay=1, preview_mode="preview",
capture_mode="still", show_preview=True, exif_data=None) -> None:
capture_mode="still", show_preview=True, exif_data=None, preview=None) -> None:
"""This function makes capturing a single image more convenient.

Should only be used in command line line applications (not from a Qt application, for example).
Expand All @@ -2471,21 +2472,22 @@ def start_and_capture_file(self, name="image.jpg", delay=1, preview_mode="previe
capture_mode - the camera mode to use to capture the still images (defaulting to the
Picamera2 object's still_configuration field).

show_preview - whether to show a preview window (default: yes). The preview window only
displays an image by default during the preview phase. This parameter only has any
effect if a preview is not already running. If it is, it would have to be stopped first
(with the stop_preview method).
preview - which preview to start (current-default: auto-detect; in-future: NullPreview).
The preview window only displays an image by default during the preview phase.
Note: if a preview is already running, this parameter has no effect.

exif_data - dictionary containing user defined exif data (based on `piexif`). This will
overwrite existing exif information generated by picamera2.
"""
_log.warning("FutureWarning: Parameter preview will default to NullPreview in a future release")

self.start_and_capture_files(name=name, initial_delay=delay, preview_mode=preview_mode,
capture_mode=capture_mode, num_files=1,
show_preview=show_preview,
show_preview=show_preview, preview=preview,
exif_data=exif_data)

def start_and_record_video(self, output, encoder=None, config=None, quality=Quality.MEDIUM,
show_preview=False, duration=0, audio=False) -> None:
show_preview=False, duration=0, audio=False, preview=None) -> None:
"""This function makes video recording more convenient.

Should only be used in command line applications (not from a Qt application, for example).
Expand All @@ -2507,9 +2509,8 @@ def start_and_record_video(self, output, encoder=None, config=None, quality=Qual
quality - an indication of the video quality to use. This will be ignored if the encoder
object was created with all its quality parameters (such as bitrate) filled in.

show_preview - whether to show a preview window (default: no). This parameter only has an
effect if a preview is not already running, in which case that preview would need
stopping first (using stop_preview) for any change to take effect.
preview - which preview to start (default: NullPreview).
Note: if a preview is already running, this parameter has no effect.

duration - the duration of the video. The function will wait this amount of time before
stopping the recording and returning. The default behaviour is to return immediately
Expand Down Expand Up @@ -2538,7 +2539,7 @@ def start_and_record_video(self, output, encoder=None, config=None, quality=Qual
if encoder is None:
encoder = H264Encoder()
self.start_encoder(encoder=encoder, output=output, quality=quality)
self.start(show_preview=show_preview)
self.start(show_preview=show_preview, preview=preview)
if duration:
time.sleep(duration)
self.stop_recording()
Expand Down
4 changes: 2 additions & 2 deletions tests/crop_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import cv2

from picamera2 import Picamera2, Platform
from picamera2 import Picamera2, Platform, Preview

# VC4 platforms do not support different crops for the two outputs.
if Picamera2.platform == Platform.VC4:
Expand All @@ -18,7 +18,7 @@
lores={"size": (320, 320), "format": 'XRGB8888', "preserve_ar": l},
display="main")
picam2.configure(cfg)
picam2.start(show_preview=True)
picam2.start(preview=Preview.auto())

for _ in range(50):
im = picam2.capture_array("lores")
Expand Down
Loading