46
46
PHOTO_THUMB_SIZE = (240 ,180 )
47
47
VIDEO_ELAPSE_MAX = 900
48
48
49
- class Camera (Thread ):
49
+ class Camera (object ):
50
50
51
51
_instance = None
52
52
_img_template = image .Image .load ("coderdojo-logo.png" )
@@ -56,19 +56,23 @@ class Camera(Thread):
56
56
def get_instance (cls ):
57
57
if cls ._instance is None :
58
58
cls ._instance = Camera ()
59
- cls ._instance .start ()
59
+ # cls._instance.start()
60
60
return cls ._instance
61
61
62
62
def __init__ (self ):
63
63
logging .info ("starting camera" )
64
- cam_props = {"width" :640 , "height" :512 , "cv_image_factor" :config .Config .get ().get ("cv_image_factor" , 4 ), "exposure_mode" : config .Config .get ().get ("camera_exposure_mode" ), "jpeg_quality" : int (config .Config .get ().get ("camera_jpeg_quality" , 20 ))}
64
+ cam_props = {"width" :640 , "height" :512 ,
65
+ "cv_image_factor" : config .Config .get ().get ("cv_image_factor" ),
66
+ "exposure_mode" : config .Config .get ().get ("camera_exposure_mode" ),
67
+ "framerate" : config .Config .get ().get ("camera_framerate" ),
68
+ "bitrate" : config .Config .get ().get ("camera_jpeg_bitrate" ),
69
+ "jpeg_quality" : int (config .Config .get ().get ("camera_jpeg_quality" ))}
65
70
self ._camera = camera .Camera (props = cam_props )
66
71
self .recording = False
67
72
self .video_start_time = time .time () + 8640000
68
- self ._run = True
69
73
self ._image_time = 0
70
74
self ._cv_image_factor = int (config .Config .get ().get ("cv_image_factor" , 4 ))
71
- self ._image_lock = Lock ()
75
+ # self._image_lock = Lock()
72
76
self ._image_refresh_timeout = float (config .Config .get ().get ("camera_refresh_timeout" , 0.1 ))
73
77
self ._color_object_size_min = int (config .Config .get ().get ("camera_color_object_size_min" , 80 )) / (self ._cv_image_factor * self ._cv_image_factor )
74
78
self ._color_object_size_max = int (config .Config .get ().get ("camera_color_object_size_max" , 32000 )) / (self ._cv_image_factor * self ._cv_image_factor )
@@ -89,45 +93,16 @@ def __init__(self):
89
93
if cnn_model != "" :
90
94
self ._cnn_classifiers [cnn_model ] = CNNManager .get_instance ().load_model (cnn_model )
91
95
self ._cnn_classifier_default = self ._cnn_classifiers [cnn_model ]
92
-
96
+
97
+ self ._camera .grab_start ()
98
+
93
99
super (Camera , self ).__init__ ()
94
100
95
- def run (self ):
96
- try :
97
- self ._camera .grab_start ()
98
- while self ._run :
99
- sleep_time = self ._image_refresh_timeout - (time .time () - self ._image_time )
100
- if sleep_time <= 0 :
101
- ts = time .time ()
102
- #print "run.1"
103
- self ._image_lock .acquire ()
104
- self ._camera .grab_one ()
105
- self ._image_lock .release ()
106
- #print "run.2: " + str(time.time()-ts)
107
-
108
- #self.save_image(image.Image(self._camera.get_image_bgr()).filter_color((124,50,74)).to_jpeg())
109
- self .save_image (self ._camera .get_image_jpeg ())
110
- #print "run.3: " + str(time.time()-ts)
111
- else :
112
- time .sleep (sleep_time )
113
-
114
- if self .recording and time .time () - self .video_start_time > VIDEO_ELAPSE_MAX :
115
- self .video_stop ()
116
-
117
- self ._camera .grab_stop ()
118
- except :
119
- logging .error ("Unexpected error:" + str (sys .exc_info ()[0 ]))
120
- raise
121
-
122
- def get_image (self , maxage = MAX_IMAGE_AGE ):
101
+ def get_image (self ):
123
102
return image .Image (self ._camera .get_image_bgr ())
124
103
125
- def save_image (self , image_jpeg ):
126
- #self._streamer.set_image(image_jpeg)
127
- self ._image_time = time .time ()
128
-
129
104
def get_image_jpeg (self ):
130
- return copy . copy ( self ._camera .get_image_jpeg () )
105
+ return self ._camera .get_image_jpeg ()
131
106
132
107
def set_text (self , text ):
133
108
self ._camera .set_overlay_text (str (text ))
@@ -168,7 +143,7 @@ def photo_take(self):
168
143
filename_thumb = PHOTO_PREFIX + str (photo_index ) + PHOTO_THUMB_SUFFIX + self ._camera .PHOTO_FILE_EXT ;
169
144
of = open (PHOTO_PATH + "/" + filename , "w+" )
170
145
oft = open (PHOTO_PATH + "/" + filename_thumb , "w+" )
171
- im_str = self ._camera . get_image_jpeg ()
146
+ im_str = self .get_image_jpeg ()
172
147
of .write (im_str )
173
148
# thumb
174
149
im_pil = PILImage .open (StringIO (im_str ))
@@ -231,24 +206,20 @@ def delete_photo(self, filename):
231
206
self .save_photo_metadata ()
232
207
233
208
def exit (self ):
234
- #self._streamer.server.shutdown()
235
- #self._streamer.server_thread.join()
236
- self ._run = False
237
- self .join ()
209
+ #self.join()
210
+ self .video_stop ()
211
+ self ._camera .grab_stop ()
238
212
239
213
def calibrate (self ):
240
214
img = self ._camera .getImage ()
241
215
self ._background = img .hueHistogram ()[- 1 ]
242
216
243
217
def get_average (self ):
244
- self ._image_lock .acquire ()
245
- avg = self .get_image (0 ).get_average ()
246
- self ._image_lock .release ()
218
+ avg = self .get_image ().get_average ()
247
219
return avg
248
220
249
221
def find_line (self ):
250
- self ._image_lock .acquire ()
251
- img = self .get_image (0 ).binarize ()
222
+ img = self .get_image ().binarize ()
252
223
slices = [0 ,0 ,0 ]
253
224
blobs = [0 ,0 ,0 ]
254
225
slices [0 ] = img .crop (0 , int (self ._camera .out_rgb_resolution [1 ]/ 1.2 ), self ._camera .out_rgb_resolution [0 ], self ._camera .out_rgb_resolution [1 ])
@@ -261,33 +232,32 @@ def find_line(self):
261
232
coords [idx ] = (blobs [idx ][0 ].center [0 ] * 100 ) / self ._camera .out_rgb_resolution [0 ]
262
233
logging .info ("line coord: " + str (idx ) + " " + str (coords [idx ])+ " area: " + str (blobs [idx ][0 ].area ()))
263
234
264
- self ._image_lock .release ()
265
235
return coords [0 ]
266
236
267
237
def find_signal (self ):
268
238
#print "signal"
269
239
angle = None
270
240
ts = time .time ()
271
- self ._image_lock .acquire ()
272
- img = self .get_image (0 )
241
+ # self._image_lock.acquire()
242
+ img = self .get_image ()
273
243
signals = img .find_template (self ._img_template )
274
244
275
245
logging .info ("signal: " + str (time .time () - ts ))
276
246
if len (signals ):
277
247
angle = signals [0 ].angle
278
248
279
- self ._image_lock .release ()
249
+ # self._image_lock.release()
280
250
281
251
return angle
282
252
283
253
def find_face (self ):
284
254
face_x = face_y = face_size = None
285
- self ._image_lock .acquire ()
286
- img = self .get_image (0 )
255
+ # self._image_lock.acquire()
256
+ img = self .get_image ()
287
257
ts = time .time ()
288
258
faces = img .grayscale ().find_faces ()
289
259
logging .info ("face.detect: " + str (time .time () - ts ))
290
- self ._image_lock .release ()
260
+ # self._image_lock.release()
291
261
if len (faces ):
292
262
# Get the largest face, face is a rectangle
293
263
x , y , w , h = faces [0 ]
@@ -301,14 +271,13 @@ def find_face(self):
301
271
return [face_x , face_y , face_size ]
302
272
303
273
def path_ahead (self ):
274
+
304
275
image_size = self ._camera .out_rgb_resolution
305
276
ts = time .time ()
306
- self ._image_lock .acquire ()
307
- img = self .get_image (0 )
277
+ img = self .get_image ()
308
278
309
279
size_y = img ._data .shape [0 ]
310
280
size_x = img ._data .shape [1 ]
311
-
312
281
threshold = img .crop (0 , size_y - (size_y / 12 ), size_x , size_y )._data .mean () / 2
313
282
314
283
blobs = img .binarize (threshold ).dilate ().find_blobs (minsize = self ._path_object_size_min , maxsize = self ._path_object_size_max )
@@ -323,18 +292,18 @@ def path_ahead(self):
323
292
coordY = 60 - ((y * 48 ) / (480 / self ._cv_image_factor ))
324
293
logging .info ("x: " + str (x ) + " y: " + str (y ) + " coordY: " + str (coordY ))
325
294
326
- self ._image_lock .release ()
295
+ # self._image_lock.release()
327
296
return coordY
328
297
329
298
def find_color (self , s_color ):
330
299
image_size = self ._camera .out_rgb_resolution
331
300
color = (int (s_color [1 :3 ],16 ), int (s_color [3 :5 ],16 ), int (s_color [5 :7 ],16 ))
332
301
code_data = None
333
302
ts = time .time ()
334
- self ._image_lock .acquire ()
335
- img = self .get_image (0 )
303
+ # self._image_lock.acquire()
304
+ img = self .get_image ()
336
305
bw = img .filter_color (color )
337
- self ._image_lock .release ()
306
+ # self._image_lock.release()
338
307
objects = bw .find_blobs (minsize = self ._color_object_size_min , maxsize = self ._color_object_size_max )
339
308
logging .debug ("objects: " + str (objects ))
340
309
dist = - 1
@@ -361,9 +330,9 @@ def find_color(self, s_color):
361
330
def find_text (self , accept , back_color ):
362
331
text = None
363
332
color = (int (back_color [1 :3 ],16 ), int (back_color [3 :5 ],16 ), int (back_color [5 :7 ],16 ))
364
- self ._image_lock .acquire ()
365
- img = self .get_image (0 )
366
- self ._image_lock .release ()
333
+ # self._image_lock.acquire()
334
+ img = self .get_image ()
335
+ # self._image_lock.release()
367
336
image = img .find_rect (color = color )
368
337
if image :
369
338
logging .info ("image: " + str (image ))
@@ -373,9 +342,9 @@ def find_text(self, accept, back_color):
373
342
return text
374
343
375
344
def find_code (self ):
376
- self ._image_lock .acquire ()
377
- img = self .get_image (0 )
378
- self ._image_lock .release ()
345
+ # self._image_lock.acquire()
346
+ img = self .get_image ()
347
+ # self._image_lock.release()
379
348
return img .grayscale ().find_code ()
380
349
381
350
def cnn_classify (self , model_name = None ):
@@ -388,9 +357,9 @@ def cnn_classify(self, model_name=None):
388
357
else :
389
358
classifier = self ._cnn_classifier_default
390
359
391
- self ._image_lock .acquire ()
392
- img = self .get_image (0 )
393
- self ._image_lock .release ()
360
+ # self._image_lock.acquire()
361
+ img = self .get_image ()
362
+ # self._image_lock.release()
394
363
classes = classifier .classify_image (img .mat ())
395
364
s_classes = sorted (classes .items (), key = lambda x : x [1 ], reverse = True )
396
365
return s_classes
0 commit comments