-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathAHF_Camera.py
383 lines (344 loc) · 17.2 KB
/
AHF_Camera.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
#! /usr/bin/python3
#-*-coding: utf-8 -*-
from picamera import PiCamera
from time import sleep
class AHF_Camera (PiCamera):
"""
AHF_Camera is subclassed from PiCamera to hold a few extra settings and to initialize the camera for constant exposure.
"""
def __init__(self, paramDict):
"""
Initializes an AHF_Camera object from a dictonary and sets the gain as appropriate
:param paramDict.format: video format for recording, default='.h264'
:param paramDict.quality: different video formats interpret quality paramater differently, default = 10
:param paramDict.resolution: two-tuple of horizontal pixel number and vertical pixel number default= (640, 480)
:param paramDict.framerate: rate,1 in Hz, at which to record video, default = 30
:param paramDict.shutter_speed: camera exposure time, in microseconds, inverse must be less than frame rate default = 30
:param paramDict.iso: used to set gain of camera directly, or use 0 to have camera calculate gain automatically
:param paramDict.whiteBalance: set to True if you want camera to auto white balance, set to False to set all color gains to 1, default = False
:param paramDict.previewWin: set the size of the preview window, in pixels a tuple of (left, top, right, bottom) coordinates. default = (0,0,640,480)
:raises PiCameraError: error raised by superclass PiCamera if camera is not found, or can't be initialized
"""
# init superClass
try:
super().__init__()
except Exception as anError:
print ("Error initializing camera.." + str (anError))
raise anError
# set fields in super-class
self.resolution = paramDict.get ('resolution', (256, 256))
self.framerate = paramDict.get ('framerate', 30)
self.iso = paramDict.get ('iso', 0)
self.shutter_speed = paramDict.get ('shutter_speed', 30000)
# set fields that are in AFF_Camera class
self.AHFvideoFormat = paramDict.get ('format', 'h264')
self.AHFvideoQuality = paramDict.get ('quality', 20)
self.AHFframerate= paramDict.get ('framerate', 30)
self.AHFpreview = paramDict.get('previewWin', (0,0,640,480))
whiteBalance = paramDict.get ('whiteBalance', False)
self.AHFgainMode = (whiteBalance == True) # set bit 0 of gain for auto white balancing
self.AHFgainMode += 2 * (self.iso == 0) # set bit 1 for auto gain
# turn off LED on camera
self.led = False
# set gain based on 2 sec preview
self.set_gain ()
return
def get_configDict (self):
"""
Loads camera settings into a dictionary with same keys as used in __init__ and returns that dictionary
Note that we use float () on framerate becuase it is a Fraction, i,e, 30 is represented as Fraction (30, 1)
and it doen't serialize for storing as a JSON dict
"""
paramDict = {'resolution' : self.resolution, 'framerate' : float (self.framerate), 'iso' : self.iso}
paramDict.update ({'shutter_speed' : self.shutter_speed, 'format' : self.AHFvideoFormat})
paramDict.update ({'quality' : self.AHFvideoQuality, 'framerate' : self.AHFframerate})
paramDict.update ({'previewWin' : self.AHFpreview, 'whiteBalance' : bool(self.AHFgainMode & 1)})
return paramDict
def set_params (self, paramDict):
"""
modifies paramaters for an AHF_Camera object from a dictonary
:param paramDict: dictionary of setings to change, same format as for __init__()
"""
# set fields in super-class
if 'resolution' in paramDict:
self.resolution = paramDict ['resolution']
if 'framerate' in paramDict:
self.framerate = paramDict ['framerate']
if 'iso' in paramDict:
self.iso = paramDict ['iso']
if self.iso == 0 and (self.AHFgainMode & 2) == 0:
self.AHFgainMode = self.AHFgainMode | 2 # set bit 1 for auto gain
elif self.iso != 0 and (self.AHFgainMode & 2) == 2:
self.AHFgainMode -= 2 # unset bit 1 for auto gain
if 'shutter_speed' in paramDict:
self.shutter_speed = paramDict ['shutter_speed']
# set fields that are in AFF_Camera class
if 'format' in paramDict:
self.AHFvideoFormat = str (paramDict ['format'])
if 'quality' in paramDict:
self.AHFvideoQuality = int (paramDict ['quality'])
if 'framerate' in paramDict:
self.AHFframerate= paramDict ['framerate']
if 'previewWin' in paramDict:
self.AHFpreview = paramDict['previewWin']
if 'whiteBalance' in paramDict:
if paramDict ['whiteBalance'] == True and (self.AHFgainMode & 1) == 0:
self.AHFgainMode = self.AHFgainMode | 1 # set bit 0 of gain for auto white balancing
elif paramDict ['whiteBalance'] == False and (self.AHFgainMode & 1) == 1:
self.AHFgainMode -= 1 # unset bit 0 of gain for auto white balancing
return
def show_config (self):
"""
prints the settings for the camera
"""
print ('----------------Current Settings for AHFCamera----------------')
print ('1:Video resolution = ' + str (self.resolution))
print ('2:Video Frame Rate = ' + str(self.framerate))
print ('3:Camera ISO = ' + str (self.iso) + '; Do Auto-Gain = ' + str (bool(self.AHFgainMode & 2)))
print ('4:Shutter Speed (in microseconds) = ' + str (self.shutter_speed))
print ('5:Video Format = ' + self.AHFvideoFormat)
print ('6:Video Quality =' + str (self.AHFvideoQuality))
print ('7:Frame Rate = ' + str (self.AHFframerate))
print ('8:Preview Window = ' + str (self.AHFpreview))
print ('9:White Balancing =' + str (bool(self.AHFgainMode & 1)))
return
def adjust_config_from_user (self):
"""
Lets the user change the settings for the camera
:returns: a dictionary containing the new, modified version fo the settings
"""
while True:
try:
self.show_config()
print ('10:Run Auto-Gain Now')
event = int (input ('Enter number of paramater to Edit, or 0 when done:'))
except ValueError:
continue
if event == 1:
self.resolution = tuple (int(x) for x in input('X/Y resolution for video, e.g. 640, 480:').split (','))
elif event == 2:
self.framerate = float (input ('Frame rate in Hz of recorded movie:'))
elif event == 3:
self.iso= int (input ('ISO for video, or 0 to auto set gains:'))
if self.iso == 0 and (self.AHFgainMode & 2) == 0:
self.AHFgainMode = self.AHFgainMode | 2 # set bit 1 for auto gain
elif self.iso != 0 and (self.AHFgainMode & 2) == 2:
self.AHFgainMode -= 2 # unset bit 1 for auto gain
elif event == 4:
self.shutter_speed = int (input ('Shutter speed (in microseconds) for recorded video:'))
elif event == 5:
self.AHFvideoFormat = str (input ('Video format for recording movies, e.g. h264 or rgb:'))
elif event == 6:
self.AHFvideoQuality = int (input ('Video quality for h264 movies (best=1, worst =40,0 for auto, not used for rgb format):'))
elif event == 7:
self.AHFframerate = float (input ('Frame rate in Hz of recorded movie:'))
elif event == 8:
self.AHFpreview = tuple (int(x) for x in input ('video preview window, a tuple (left, top, right, bottom):').split (','))
elif event == 9:
tempVal = bool(int (input('Do white balance for video (1 for yes, or 0 for no:')))
if tempVal == True and (self.AHFgainMode & 1) == 0:
self.AHFgainMode = self.AHFgainMode | 1 # set bit 0 of gain for auto white balancing
elif tempVal == False and (self.AHFgainMode & 1) == 1:
self.AHFgainMode -= 1 # unset bit 0 of gain for auto white balancing
elif event == 10:
self.set_gain()
elif event == 0:
break
else:
print ('Enter a number from 0 to 10')
return self.get_configDict ()
def set_gain (self):
"""
Sets the gain and white balance of the camera based on a 2 second preview - so set illumination as you like before calling
If ISO for the camera is set to non-zero value, gain is not settable. If pWhiteBalance was set to False, white balancing is not done,
and gains for red and green are set to 1.
:raises PiCameraError: error raised by superclass PiCamera from preview
"""
DescStr = 'Setting Gain for AHF_Camera '
if (self.AHFgainMode & 2):
DescStr += 'from current illumination'
else:
DescStr += "from ISO " + str (self.iso)
if (self.AHFgainMode & 1):
DescStr += ' with white balancing'
else:
DescStr += " with No white balancing"
print (DescStr)
if (self.AHFgainMode & 1):
self.awb_mode='auto'
else:
self.awb_mode='off'
self.awb_gains = (1,1)
#if (self.AHFgainMode & 2):
self.exposure_mode = 'auto'
#else:
# self.exposure_mode = 'off'
super().start_preview(fullscreen = False, window=self.AHFpreview)
sleep(2.0) # let gains settle, then fix values
if (self.AHFgainMode & 1):
savedGain = self.awb_gains
self.awb_gains = savedGain
self.awb_mode = "off"
#if (self.AHFgainMode & 2):
self.exposure_mode = 'off'
super().stop_preview ()
print ("Red Gain for white balance =" + str (float(self.awb_gains [0])))
print ("Blue Gain for white balance =" + str (float(self.awb_gains [1])))
print ("Analog Gain = " + str(float (self.analog_gain)))
print ("Digital Gain = " + str (float(self.digital_gain)))
return
def start_recording(self, video_name_path):
"""
Starts a video recording using the saved settings for format, quality, gain, etc.
A preview of the recording is always shown
:param video_name_path: a full path to the file where the video will be stored. Always save to a file, not a PIL, for, example
"""
if self.AHFvideoFormat == 'rgb':
super().start_recording(output=video_name_path, format=self.AHFvideoFormat)
else:
super().start_recording(video_name_path, format = self.AHFvideoFormat, quality = self.AHFvideoQuality)
super().start_preview(fullscreen = False, window= self.AHFpreview)
return
def stop_recording(self):
"""
Stops a video recording previously started with start_recording.
"""
if self.recording:
super().stop_recording()
super().stop_preview()
return
def timed_recording(self, video_name_path, recTime):
"""
Does a timed video recording using the PiCamera wait_recording function.
A preview of the recording is always shown
Control does not pass back to the calling function until the recording is finished
:param video_name_path: a full path to the file where the video will be stored.
:param recTime: duration of the recorded video, in seconds
"""
if self.AHFvideoFormat == 'rgb':
super().start_recording(output=video_name_path, format=self.AHFvideoFormat)
else:
super().start_recording(output=video_name_path, format=self.AHFvideoFormat)
super().start_preview(fullscreen = False, window= self.AHFpreview)
super().wait_recording(timeout=recTime)
self.stop_recording ()
return
def __del__(self):
super().close()
@staticmethod
def dict_from_user (paramDict):
"""
static method that leys user make or edit a dictionary object that holds camera setttings
configure gets info from user with the input function, which returns strings
"""
if paramDict is None:
paramDict = {}
# resolution
resolution = paramDict.get ('resolution', (640, 480))
tempInput = input ('set X,Y resolution (currently ' + str (resolution) + ') to :')
if tempInput != '':
resolution = tuple (int(x) for x in tempInput.split (','))
paramDict.update ({'resolution' : resolution})
# framerate
frameRate = paramDict.get ('framerate', 30)
tempInput = input ('Set Frame rate in Hz of recorded movie (currently ' + str (frameRate) + ') to :')
if tempInput != '':
frameRate = float (tempInput)
paramDict.update ({'framerate' : frameRate})
# ISO
iso = paramDict.get ('iso', 0)
tempInput = input ('Set ISO for video, or 0 to auto set gains (currently ' + str (iso) + ') to :')
if tempInput != '':
iso = int (tempInput)
paramDict.update ({'iso' : iso})
# shutter speed
shutter_speed = paramDict.get ('shutter_speed', 30000)
tempInput = input ('Set Shutter speed (in microseconds) for recorded video (currently ' + str (shutter_speed) + ') to :')
if tempInput != '':
shutter_speed= int (tempInput)
paramDict.update ({'shutter_speed' : shutter_speed})
# videoFormat
videoFormat = paramDict.get ('format', 'h264' )
tempInput = input ('Set Video format for recording movies (currently ' + videoFormat + ') to :')
if tempInput != '':
videoFormat = tempInput
paramDict.update ({'format' : videoFormat})
# quality
quality = paramDict.get ('quality', 20)
tempInput = input ('Set Video quality for h264 movies, best=1, worst =40,0 for auto (currently ' + str (quality) + ') to :')
if tempInput != '':
quality = int (tempInput)
paramDict.update ({'quality' : quality})
# preview window
previewWin = paramDict.get ('previewWin', (0,0,640,480))
tempInput = input ('Set video preview window, left, top, right, bottom, (currently ' + str(previewWin) + ') to :')
if tempInput != '':
previewWin = tuple (int(x) for x in tempInput.split (','))
paramDict.update ({'previewWin' : previewWin})
# white balance
whiteBalance = paramDict.get ('whiteBalance', False)
tempInput = input ('Set white balancing for video, 1 for True, or 0 for Flase (currently ' + str (whiteBalance) + ') to :')
if tempInput !='':
tempInput = bool (int (tempInput))
paramDict.update ({'whiteBalance' : whiteBalance})
# return already modified dictionary, needed when making a new dictionary
return paramDict
if __name__ == '__main__':
import time
import PTSimpleGPIO
from PTSimpleGPIO import PTSimpleGPIO, Pulse, Train, Infinite_train
t1 = Train (PTSimpleGPIO.INIT_FREQ, 14.4, 0.5, 30, 17, PTSimpleGPIO.ACC_MODE_SLEEPS_AND_SPINS)
videoFormat = 'rgb'
quality = 0
resolution = (256,256)
frameRate = 30
iso = 0
whiteBalance = True
previewWin =(0,0,256,256)
#userDict = AHF_Camera.dict_from_user ({})
#camera=AHF_Camera (userDict)
camera=AHF_Camera ({'format': videoFormat, 'quality' : quality, 'resolution' : resolution, 'iso' : iso, 'whiteBalance': whiteBalance, 'previewWin' :(0,0,320, 240)})
videoPath = '/home/pi/lolcat.' + camera.AHFvideoFormat
t1.do_train()
camera.start_recording(videoPath)
sleep (1.5)
print ('Recording 5 sec video')
frameNow = camera.frame
frameIndex = frameNow.index
frameStop = 500
frameOld = 0
indexOld=0
frameNow_array = []
frameIndex_array = []
time_start = time.time()
while camera.frame.index < frameStop:
#frameNow = camera.frame
frameIndex = camera.frame.index
#print (frameNow.index)
#frameNow = camera.frame
#frameIndex = frameNow.index
#print (frameNow.timestamp, frameIndex)
if frameIndex == indexOld: continue
frameNow_array.append(camera.frame.timestamp)
frameIndex_array.append(camera.frame.index)
indexOld = frameIndex
#sleep (0.01)
time_end=time.time()
previous_frame = 0
total_time = 0
for k in range(len(frameNow_array)-1):
#if frameIndex_array[k] == previous_frame: continue
#previous_frame = frameIndex_array[k]
if (frameNow_array[k+1] is None) or (frameNow_array[k] is None):
print (frameIndex_array[k], frameNow_array[k-1], frameNow_array[k], frameNow_array[k+1])
continue
print (frameIndex_array[k], 1E6/(frameNow_array[k+1]-frameNow_array[k]))
total_time +=(frameNow_array[k+1]-frameNow_array[k])*1E-6
print (time_start, time_end, time_end-time_start)
print (total_time)
#class picamera.PiVideoFrame(index, frame_type, frame_size, video_size, split_size, timestamp)
camera.stop_recording()
#camera.adjust_config_from_user ()
#videoPath = '/home/pi/Documents/testMod.' + camera.AHFvideoFormat
#print ('About to record a 5 sec timed video')
#camera.timed_recording(videoPath, 5.0)