11
11
from viz import camera , streamer , image , blob
12
12
import config
13
13
14
+ import picamera
15
+ import picamera .array
16
+ import io
17
+
14
18
CAMERA_REFRESH_INTERVAL = 0.1
15
19
MAX_IMAGE_AGE = 0.0
16
20
PHOTO_PATH = "./photos"
20
24
PHOTO_THUMB_SUFFIX = "_thumb"
21
25
PHOTO_THUMB_SIZE = (240 ,180 )
22
26
VIDEO_ELAPSE_MAX = 900
27
+ PHOTO_FILE_EXT = ".jpg"
28
+ FFMPEG_CMD = "MP4Box"
29
+ VIDEO_FILE_EXT = ".mp4"
30
+ VIDEO_FILE_EXT_H264 = ".h264"
23
31
24
32
class Camera (Thread ):
25
33
@@ -28,6 +36,8 @@ class Camera(Thread):
28
36
_warp_corners_1 = [(0 , - 120 ), (640 , - 120 ), (380 , 480 ), (260 , 480 )]
29
37
_warp_corners_2 = [(0 , - 60 ), (320 , - 60 ), (190 , 240 ), (130 , 240 )]
30
38
_warp_corners_4 = [(0 , - 30 ), (160 , - 30 ), (95 , 120 ), (65 , 120 )]
39
+ _image_cache = None
40
+ _image_cache_updated = False
31
41
stream_port = 9080
32
42
33
43
@classmethod
@@ -39,19 +49,7 @@ def get_instance(cls):
39
49
40
50
def __init__ (self ):
41
51
logging .info ("starting camera" )
42
- cam_props = {
43
- "width" :640 ,
44
- "height" :480 ,
45
- "exposure_mode" : config .Config .get ().get ("camera_exposure_mode" ),
46
- "rotation" : config .Config .get ().get ("camera_rotation" )
47
- }
48
- #try initialising the camera
49
- try :
50
- self ._camera = camera .Camera (props = cam_props )
51
- except :
52
- self ._camera = None
53
- logging .error ("Unexpected error:" + str (sys .exc_info ()[0 ]))
54
- pass
52
+ self .init_camera ()
55
53
56
54
self ._streamer = streamer .JpegStreamer ("0.0.0.0:" + str (self .stream_port ), st = 0.1 )
57
55
#self._cam_off_img.save(self._streamer)
@@ -70,39 +68,100 @@ def __init__(self):
70
68
71
69
super (Camera , self ).__init__ ()
72
70
71
+ def init_camera (self ):
72
+ try :
73
+ props = {
74
+ "width" :640 ,
75
+ "height" :480 ,
76
+ "exposure_mode" :config .Config .get ().get ("camera_exposure_mode" ),
77
+ "rotation" :config .Config .get ().get ("camera_rotation" )
78
+ }
79
+ self ._camera = picamera .PiCamera ()
80
+ cam = self ._camera
81
+ res = (props .get ("width" ,640 ), props .get ("height" ,480 ))
82
+ cam .resolution = res
83
+ cam .framerate = 30
84
+ cam .exposure_mode = props .get ("exposure_mode" )
85
+ cam .rotation = props .get ("rotation" )
86
+ self .out_jpeg = io .BytesIO ()
87
+ self .out_rgb = picamera .array .PiRGBArray (cam , size = res )
88
+ self .h264_encoder = None
89
+ self .recording = None
90
+ self .video_filename = None
91
+ except :
92
+ self ._camera = None
93
+ logging .error ("Could not initialise camera:" + str (sys .exc_info ()[0 ]))
94
+ pass
95
+
96
+ def grab_start (self ):
97
+ logging .debug ("grab_start" )
98
+ camera_port_0 , output_port_0 = self ._camera ._get_ports (True , 0 )
99
+ self .jpeg_encoder = self ._camera ._get_image_encoder (camera_port_0 , output_port_0 , 'jpeg' , None , quality = 40 )
100
+ camera_port_1 , output_port_1 = self ._camera ._get_ports (True , 1 )
101
+ self .rgb_encoder = self ._camera ._get_image_encoder (camera_port_1 , output_port_1 , 'bgr' , res )
102
+
103
+ with self ._camera ._encoders_lock :
104
+ self ._camera ._encoders [0 ] = self .jpeg_encoder
105
+ self ._camera ._encoders [1 ] = self .rgb_encoder
106
+
107
+ def grab_one (self ):
108
+ self .out_jpeg .seek (0 )
109
+ self .out_rgb .seek (0 )
110
+ self .jpeg_encoder .start (self .out_jpeg )
111
+ self .rgb_encoder .start (self .out_rgb )
112
+ if not self .jpeg_encoder .wait (10 ):
113
+ raise picamera .PiCameraError ('Timed Out' )
114
+ if not self .rgb_encoder .wait (10 ):
115
+ raise picamera .PiCameraError ('Timed Out' )
116
+
117
+ def grab_stop (self ):
118
+ logging .debug ("grab_stop" )
119
+
120
+ with self ._camera ._encoders_lock :
121
+ del self ._camera ._encoders [0 ]
122
+ del self ._camera ._encoders [1 ]
123
+
124
+ self .jpeg_encoder .close ()
125
+ self .rgb_encoder .close ()
126
+
73
127
def run (self ):
74
128
if self ._camera is None :
75
129
return
76
130
try :
77
- self ._camera . grab_start ()
131
+ self .grab_start ()
78
132
while self ._run :
79
133
sleep_time = CAMERA_REFRESH_INTERVAL - (time .time () - self ._image_time )
80
134
if sleep_time <= 0 :
81
135
ts = time .time ()
82
136
#print "run.1"
83
137
self ._image_lock .acquire ()
84
- self ._camera . grab_one ()
138
+ self .grab_one ()
85
139
self ._image_lock .release ()
86
140
#print "run.2: " + str(time.time()-ts)
87
141
#self.save_image(image.Image(self._camera.get_image_bgr()).open().binarize().to_jpeg())
88
- self .save_image (self ._camera .get_image_jpeg ())
142
+ if self ._image_cache_updated is True :
143
+ self .save_image (self ._image_cache .to_jpeg ())
144
+ self ._image_cache_updated = False
145
+ else :
146
+ self .save_image (self .out_jpeg .getvalue ())
89
147
#print "run.3: " + str(time.time()-ts)
90
148
else :
91
149
time .sleep (sleep_time )
92
150
93
151
if self .recording and time .time () - self .video_start_time > VIDEO_ELAPSE_MAX :
94
152
self .video_stop ()
95
153
96
- self ._camera . grab_stop ()
154
+ self .grab_stop ()
97
155
except :
98
156
logging .error ("Unexpected error:" + str (sys .exc_info ()[0 ]))
99
157
raise
100
158
101
159
def get_image (self , maxage = MAX_IMAGE_AGE ):
102
160
if self ._camera is None :
161
+ print "get_image: Default image"
103
162
return Image (cv2 .imread (DEFAULT_IMAGE ))
104
163
else :
105
- return image .Image (self ._camera . get_image_bgr () )
164
+ return image .Image (self .out_rgb . array )
106
165
107
166
def save_image (self , image_jpeg ):
108
167
self ._streamer .set_image (image_jpeg )
@@ -111,13 +170,13 @@ def save_image(self, image_jpeg):
111
170
def set_text (self , text ):
112
171
if self ._camera is None :
113
172
return
114
- self ._camera .set_overlay_text (str (text ))
173
+ self ._camera .annotate_text (str (text ))
115
174
116
175
def get_next_photo_index (self ):
117
176
last_photo_index = 0
118
177
for p in self ._photos :
119
178
try :
120
- index = int (p [len (PHOTO_PREFIX ):- len (self ._camera . PHOTO_FILE_EXT )])
179
+ index = int (p [len (PHOTO_PREFIX ):- len (self .PHOTO_FILE_EXT )])
121
180
if index > last_photo_index :
122
181
last_photo_index = index
123
182
except :
@@ -127,21 +186,21 @@ def get_next_photo_index(self):
127
186
def rotate (self ):
128
187
if self ._camera is None :
129
188
return
130
- rot = self ._camera .camera . rotation
189
+ rot = self ._camera .rotation
131
190
rot = rot + 90
132
191
if rot > 271 :
133
192
rot = 0
134
- self ._camera .camera . rotation = rot
193
+ self ._camera .rotation = rot
135
194
136
195
def photo_take (self ):
137
196
if self ._camera is None :
138
197
return
139
198
photo_index = self .get_next_photo_index ()
140
- filename = PHOTO_PREFIX + str (photo_index ) + self . _camera . PHOTO_FILE_EXT ;
141
- filename_thumb = PHOTO_PREFIX + str (photo_index ) + PHOTO_THUMB_SUFFIX + self . _camera . PHOTO_FILE_EXT ;
199
+ filename = PHOTO_PREFIX + str (photo_index ) + PHOTO_FILE_EXT ;
200
+ filename_thumb = PHOTO_PREFIX + str (photo_index ) + PHOTO_THUMB_SUFFIX + PHOTO_FILE_EXT ;
142
201
of = open (PHOTO_PATH + "/" + filename , "w+" )
143
202
oft = open (PHOTO_PATH + "/" + filename_thumb , "w+" )
144
- im_str = self ._camera . get_image_jpeg ()
203
+ im_str = self .out_jpeg . getvalue ()
145
204
of .write (im_str )
146
205
# thumb
147
206
im_pil = PILImage .open (StringIO (im_str ))
@@ -152,12 +211,11 @@ def is_recording(self):
152
211
return self .recording
153
212
154
213
def video_rec (self , video_name = None ):
155
- if self .is_recording () :
214
+ if self .recording :
156
215
return
157
- self .recording = True
158
216
if self ._camera is None :
159
217
return
160
-
218
+ self . recording = True
161
219
if video_name is None :
162
220
video_index = self .get_next_photo_index ()
163
221
filename = VIDEO_PREFIX + str (video_index ) + self ._camera .VIDEO_FILE_EXT ;
@@ -328,29 +386,48 @@ def find_color(self, s_color):
328
386
self ._image_lock .acquire ()
329
387
img = self .get_image (0 )
330
388
self ._image_lock .release ()
389
+ if img is None :
390
+ print "Image from get_image is None!"
391
+ return [0 ,0 ]
331
392
bw = img .filter_color (color )
393
+ contours , hierarchy = bw .find_contours ()
394
+ for contour in contours :
395
+ img .draw_contour_bound_circle (contour )
396
+ self ._image_cache = img
397
+ self ._image_cache_updated = True
398
+ if self ._image_cache is None :
399
+ print "Image cache is None!"
332
400
#self.save_image(bw.to_jpeg())
333
- objects = bw .find_blobs (minsize = 20 , maxsize = 1000 )
334
- logging .debug ("objects: " + str (objects ))
335
- dist = - 1
336
- angle = 180
337
-
338
- if objects and len (objects ):
339
- obj = objects [- 1 ]
340
- bottom = obj .bottom
341
- logging .info ("bottom: " + str (obj .center [0 ]) + " " + str (obj .bottom ))
342
- coords = bw .transform ([(obj .center [0 ], obj .bottom )])
343
- logging .info ("coordinates: " + str (coords ))
344
- x = coords [0 ][0 ]
345
- y = coords [0 ][1 ]
346
- dist = math .sqrt (math .pow (12 + (68 * (120 - y ) / 100 ),2 ) + (math .pow ((x - 80 )* 60 / 160 ,2 )))
347
- angle = math .atan2 (x - 80 , 120 - y ) * 180 / math .pi
348
- logging .info ("object found, dist: " + str (dist ) + " angle: " + str (angle ))
401
+ # objects = bw.find_blobs(minsize=5 , maxsize=100 )
402
+ # logging.debug("objects: " + str(objects))
403
+ # dist = -1
404
+ # angle = 180
405
+
406
+ # if objects and len(objects):
407
+ # obj = objects[-1]
408
+ # bottom = obj.bottom
409
+ # logging.info("bottom: " + str(obj.center[0]) + " " +str(obj.bottom))
410
+ # coords = bw.transform([(obj.center[0], obj.bottom)])
411
+ # logging.info("coordinates: " + str(coords))
412
+ # x = coords[0][0]
413
+ # y = coords[0][1]
414
+ # dist = math.sqrt(math.pow(12 + (68 * (120 - y) / 100),2) + (math.pow((x-80)*60/160,2)))
415
+ # angle = math.atan2(x - 80, 120 - y) * 180 / math.pi
416
+ # logging.info("object found, dist: " + str(dist) + " angle: " + str(angle))
349
417
#self.save_image(img.to_jpeg())
350
418
#print "object: " + str(time.time() - ts)
351
- return [dist , angle ]
419
+ #return [dist, angle]
420
+ return [0 ,0 ]
421
+
352
422
353
423
def sleep (self , elapse ):
354
424
logging .debug ("sleep: " + str (elapse ))
355
425
time .sleep (elapse )
356
426
427
+ def drawCircle (self ,colour ,x ,y ):
428
+ cv2 .circle (self ._camera .get_image_bgr (),(x ,y ),30 ,(0 ,0 ,255 ), - 1 )
429
+ #cv2.circle(self.get_image(0)
430
+
431
+
432
+
433
+
0 commit comments