9
9
logger = logging .getLogger (__name__ )
10
10
logging .basicConfig (level = logging .INFO )
11
11
12
+
12
13
class CameraError (Exception ):
13
14
pass
14
15
16
+
15
17
class BaseCamera :
16
18
17
19
def run_threaded (self ):
18
20
return self .frame
19
21
20
- class PiCamera (BaseCamera ):
21
- def __init__ (self , image_w = 160 , image_h = 120 , image_d = 3 , framerate = 20 , vflip = False , hflip = False ):
22
- from picamera .array import PiRGBArray
23
- from picamera import PiCamera
24
22
25
- resolution = (image_w , image_h )
26
- # initialize the camera and stream
27
- self .camera = PiCamera () #PiCamera gets resolution (height, width)
28
- self .camera .resolution = resolution
29
- self .camera .framerate = framerate
30
- self .camera .vflip = vflip
31
- self .camera .hflip = hflip
32
- self .rawCapture = PiRGBArray (self .camera , size = resolution )
33
- self .stream = self .camera .capture_continuous (self .rawCapture ,
34
- format = "rgb" , use_video_port = True )
23
+ class PiCamera (BaseCamera ):
24
+ """
25
+ RPi Camera class based on Bullseye's python class Picamera2.
26
+ """
27
+ def __init__ (self , image_w = 160 , image_h = 120 , image_d = 3 ,
28
+ vflip = False , hflip = False ):
29
+ from picamera2 import Picamera2
30
+ from libcamera import Transform
31
+
32
+ # it's weird but BGR returns RGB images
33
+ config_dict = {"size" : (image_w , image_h ), "format" : "BGR888" }
34
+ transform = Transform (hflip = hflip , vflip = vflip )
35
+ self .camera = Picamera2 ()
36
+ config = self .camera .create_preview_configuration (
37
+ config_dict , transform = transform )
38
+ self .camera .align_configuration (config )
39
+ self .camera .configure (config )
40
+ # try min / max frame rate as 0.1 / 1 ms (it will be slower though)
41
+ self .camera .set_controls ({"FrameDurationLimits" : (100 , 1000 )})
42
+ self .camera .start ()
35
43
36
44
# initialize the frame and the variable used to indicate
37
45
# if the thread should be stopped
@@ -40,31 +48,23 @@ def __init__(self, image_w=160, image_h=120, image_d=3, framerate=20, vflip=Fals
40
48
self .image_d = image_d
41
49
42
50
# get the first frame or timeout
43
- logger .info ('PiCamera loaded...' )
44
- if self .stream is not None :
45
- logger .info ('PiCamera opened...' )
46
- warming_time = time .time () + 5 # quick after 5 seconds
47
- while self .frame is None and time .time () < warming_time :
48
- logger .info ("...warming camera" )
49
- self .run ()
50
- time .sleep (0.2 )
51
+ logger .info ('PiCamera opened...' )
52
+ warming_time = time .time () + 5 # quick after 5 seconds
53
+ while self .frame is None and time .time () < warming_time :
54
+ logger .info ("...warming camera" )
55
+ self .run ()
56
+ time .sleep (0.2 )
57
+
58
+ if self .frame is None :
59
+ raise CameraError ("Unable to start PiCamera." )
51
60
52
- if self .frame is None :
53
- raise CameraError ("Unable to start PiCamera." )
54
- else :
55
- raise CameraError ("Unable to open PiCamera." )
56
61
logger .info ("PiCamera ready." )
57
62
58
63
def run (self ):
59
- # grab the frame from the stream and clear the stream in
60
- # preparation for the next frame
61
- if self .stream is not None :
62
- f = next (self .stream )
63
- if f is not None :
64
- self .frame = f .array
65
- self .rawCapture .truncate (0 )
66
- if self .image_d == 1 :
67
- self .frame = rgb2gray (self .frame )
64
+ # grab the next frame from the camera buffer
65
+ self .frame = self .camera .capture_array ("main" )
66
+ if self .image_d == 1 :
67
+ self .frame = rgb2gray (self .frame )
68
68
69
69
return self .frame
70
70
@@ -78,16 +78,13 @@ def shutdown(self):
78
78
self .on = False
79
79
logger .info ('Stopping PiCamera' )
80
80
time .sleep (.5 )
81
- self .stream .close ()
82
- self .rawCapture .close ()
83
81
self .camera .close ()
84
- self .stream = None
85
- self .rawCapture = None
86
82
self .camera = None
87
83
88
84
89
85
class Webcam (BaseCamera ):
90
- def __init__ (self , image_w = 160 , image_h = 120 , image_d = 3 , framerate = 20 , camera_index = 0 ):
86
+ def __init__ (self , image_w = 160 , image_h = 120 , image_d = 3 ,
87
+ framerate = 20 , camera_index = 0 ):
91
88
#
92
89
# pygame is not installed by default.
93
90
# Installation on RaspberryPi (with env activated):
@@ -270,18 +267,20 @@ def shutdown(self):
270
267
self .running = False
271
268
logger .info ('Stopping CSICamera' )
272
269
time .sleep (.5 )
273
- del ( self .camera )
270
+ del self .camera
274
271
275
272
276
273
class V4LCamera (BaseCamera ):
277
274
'''
278
- uses the v4l2capture library from this fork for python3 support: https://github.com/atareao/python3-v4l2capture
275
+ uses the v4l2capture library from this fork for python3 support:
276
+ https://github.com/atareao/python3-v4l2capture
279
277
sudo apt-get install libv4l-dev
280
278
cd python3-v4l2capture
281
279
python setup.py build
282
280
pip install -e .
283
281
'''
284
- def __init__ (self , image_w = 160 , image_h = 120 , image_d = 3 , framerate = 20 , dev_fn = "/dev/video0" , fourcc = 'MJPG' ):
282
+ def __init__ (self , image_w = 160 , image_h = 120 , image_d = 3 , framerate = 20 ,
283
+ dev_fn = "/dev/video0" , fourcc = 'MJPG' ):
285
284
286
285
self .running = True
287
286
self .frame = None
0 commit comments