class Main(object): """ Runs the application, manages the GUI, manages the command line, manages the pipeline. TODO: maybe move? Arguments: TODO: decide! args: args directly taken from the command line source_name: string used in open_source """ def __init__(self, source_name="camera", calibrate=True, create_gui=True): # TODO: way too much responsibility... # set and start the GUI, if it exists if create_gui: app = QtGui.QApplication(sys.argv) self.gui = init.init(self) sys.exit(app.exec_()) # load source, pause, record, and play the video self.is_recording = False self.recorded = [] # TODO: set defaults with dc .py self.displays = [] # update self.camera_gain = ( 0.0 ) # TODO: not right yet!!! #Should they be used to control the camera directly? firewirevideo.c's feature register self.camera_bias = 0.0 self.camera_gamma = 1.0 self.camera_framerate = FirewireVideo.DC1394_FRAMERATE_15 self.video_mode = FirewireVideo.DC1394_VIDEO_MODE_640x480_RGB8 self.parse_args() self.open_source(source_name) # display pipeline # source -> corrector -> scale_offset (with autocontrast on/off?) # calibrate camera ??? (TODO: load calibration data if available?) self.calibrator = Calibrator(input=self.source, calibrate_now=calibrate) # keep the last ProcessObject in the pipeline self.source.updatePlayMode() self.calibrator.getOutput().update() self.scale_offset = Scale_Offset(input=self.calibrator.getOutput(), auto_contrast=False) self.output = self.scale_offset # TODO: manage displays with GUI, only show the final result at end if calibrate: self.add_image_display(input=self.calibrator.dark_current_image, title="dc") self.add_image_display(input=self.calibrator.flat_field_image * 255, title="ff") self.add_display(input=self.source, title="source") self.add_display(input=self.calibrator.getOutput(), title="corrected") self.add_display(input=self.output, title="microscope") self.main_loop() # TODO: move this out # histogram = Histogram(input=self.source) # TODO: open GUI, attach displays # create a GUI with cv.CreateTrackbar, cv.CreateButton, def add_display(self, input=None, title="default"): """ Given a ProcessObject to draw input from, adds a display to manage. Arguments: input - ProcessObject to display title - unique window title """ self.displays.append(Display(input=input, title=title)) def add_image_display(self, input=None, title="image_default"): """ Given a numpy image, display with a ProcessObject with title. Arguments: input - valid numpy array for ProcessObject's output title - unique window title to display """ image = pipeline.ProcessObject(input=None, inputCount=0) image.getOutput(0).setData(input) self.add_display(input=image, title=title) # def print_modes(): # def print_framerates(): # present the user with available video modes dc1394.VIDEO_MODES # present the user with available frame rates dc1394.FRAMERATES # present the user with a way to change: # gain, bias, gamma def start_recording(self): """ Clears the recorded buffer and starts recording. """ self.is_recording = True self.recorded = [] # TODO: save file in folder/folder name+number+.png def stop_recording(self): """ Stops recording and offers to save, if desired. """ self.is_recording = False filename = None filenumber = None for image in enumerate(self.recorded): filenumber = None cv2.imwrite(filename + filenumber + ".png", image) def main_loop(self): """ Runs the main loop and the gui responsibly; update displays. """ key = None frame = 0 t0 = time.time() span = 30 while key != 27: self.source.updatePlayMode() self.output.update() for display in self.displays: display.update() # record here... if self.is_recording: self.recorded.append(self.scale_offset.getInput().getOutput().getData()) # respond to key presses key = cv2.waitKey(33) # sets the framerate to ~30 frames/second if key >= 0: char = chr(key & 255) print "Key: ", key, char if char == "-": scale = self.scale_offset.getScale() self.scale_offset.setScale(scale * 0.95) print "Scale:", str(self.scale_offset.getScale()) elif char == "=": scale = self.scale_offset.getScale() self.scale_offset.setScale(scale * 1.05) print "Scale:", str(self.scale_offset.getScale()) elif char == "[": offset = self.scale_offset.getOffset() self.scale_offset.setOffset(offset - 5.0) print "Offset:", str(self.scale_offset.getOffset()) elif char == "]": offset = self.scale_offset.getOffset() self.scale_offset.setOffset(offset + 5.0) print "Offset:", str(self.scale_offset.getOffset()) elif char == "r": self.scale_offset.setScale(1.0) self.scale_offset.setOffset(0.0) print ("scale and offset reset") elif char == "o": auto_contrast = self.scale_offset.auto_contrast_enabled self.scale_offset.auto_contrast_enabled = not (auto_contrast) print "Auto contrast enabled:", str(not (auto_contrast)) elif char == "a": self.scale_offset.autocontrast() print "Scale:", str(self.scale_offset.getScale()) print "Offset:", str(self.scale_offset.getOffset()) frame += 1 if frame % span == 0: t1 = time.time() print "{0:8.5f} fps".format(span / (t1 - t0)) t0 = t1 def open_source(self, source_name="camera"): """ Opens the original video source at self.source Arguments: source_name: can be 'camera', 'microscope', or a valid directory name """ if source_name == "microscope": self.source = source.CameraFW( 0, FirewireVideo.DC1394_VIDEO_MODE_640x480_RGB8, FirewireVideo.DC1394_FRAMERATE_15 ) self.source.getCamera().setColorAbsolute(whiteBlue=1023, whiteRed=276) elif source_name == "camera": self.source = source.CameraCV() # otherwise, try to open it as a directory else: # get files from directory and set the source path = os.curdir + os.sep + source_name files = os.listdir(path) files = [path + os.sep + filename for filename in files] self.source = source.FileStackReader(files) # TODO: fail gracefully? self.source.setLoop() self.source.setPlayMode(source.ImageSource.play) # TODO: allow user to control video instead of infinite loop # TODO: increment, but at a reasonable time :| def parse_args(self): """ Parse command line input and set appropriate options. Arguments: TODO: decide! argv: a list taken from sys.argv[1:] """ short_options = "hf:c:r:g:G:b:" long_options = ["help", "format=", "color=", "framerate=", "gain=", "gamma=", "bias="] try: options, args = getopt.getopt(sys.argv[1:], short_options, long_options) for option, arg in options: # if option == '-f' or option == '--format': # self.camera_format = arg # elif option == '-c' or option == '--color': # self.camera_color = arg # elif option == '-r' or option == '--framerate': # self.camera_framerate = arg if option == "-g" or option == "--gain": self.camera_gain = arg elif option == "-b" or option == "--bias": self.camera_bias = arg elif option == "-G" or option == "--gamma": self.camera_gamma = arg elif option == "-h" or option == "--help": print "Command line options:" print " Camera settings:" # print " -c <mode> or --color <mode> :" # print " -r <int> or --framerate <int>:" print " -b <float> or --bias <float> : set camera bias" print " -g <float> or --gain <float> : set camera gain" print " -G <float> or --gamma <float> : set camera gamma" print "" # print " -m or --modes : print camera modes" print " -h or --help : prints this help" exit(0) except Exception as err: print str(err)