Source code for AutoHeadFix.AHF_Camera

#! /usr/bin/python3
#-*-coding: utf-8 -*-

from picamera import PiCamera
from time import sleep



[docs]class AHF_Camera (PiCamera): """ AHF_Camera is subclassed from PiCamera to hold a few extra settings and to initialize the camera for constant exposure. """
[docs] 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', (640, 480)) 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
[docs] 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
[docs] 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
[docs] 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
[docs] 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 ()
[docs] 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
[docs] 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(output=video_name_path, format=self.AHFvideoFormat, quality = self.AHFvideoQuality) super().start_preview(fullscreen = False, window= self.AHFpreview) return
[docs] def stop_recording(self): """ Stops a video recording previously started with start_recording. """ if self.recording: super().stop_recording() super().stop_preview() return
[docs] 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
[docs] 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__': videoFormat = 'rgb' quality = 0 resolution = (640,480) frameRate = 30 iso = 0 whiteBalance = True previewWin =(0,0,320,240) 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/Documents/test.' + camera.AHFvideoFormat camera.start_recording(videoPath) sleep (2.5) print ('Recording 5 sec video') sleep (2.5) 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)