예제 #1
0
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)