Esempio n. 1
0
class AsyncFrameRead(threading.Thread):
    """
    Read an image asynchronously
    """
    def __init__(self, input_image: str, controller=Controller()):
        # calling superclass init
        threading.Thread.__init__(self, name="asyncframeread")
        self.input_image = input_image
        self.loaded_image = Frame()
        self.load_complete = False
        self.controller = controller

    def run(self):
        self.loaded_image.load_from_string_controller(self.input_image,
                                                      self.controller)
        self.load_complete = True
Esempio n. 2
0
    def run(self):
        self.log.info("Started")
        self.pipe.start()

        # Load the genesis image + the first upscaled image.
        frame_previous = Frame()
        frame_previous.load_from_string_controller(
            self.merged_dir + "merged_" + str(self.start_frame) +
            self.extension_type, self.context.controller)

        # Load and pipe the 'first' image before we start the for loop procedure, since all the other images will
        # inductively build off this first frame.
        frame_previous = Frame()
        frame_previous.load_from_string_controller(
            self.merged_dir + "merged_" + str(self.start_frame) +
            self.extension_type, self.context.controller)
        self.pipe.save(frame_previous)

        current_upscaled_residuals = Frame()
        current_upscaled_residuals.load_from_string_controller(
            self.upscaled_dir + "output_" +
            get_lexicon_value(6, self.start_frame) + ".png",
            self.context.controller)

        last_frame = False
        for x in range(self.start_frame, self.frame_count):
            ########################################
            # Pre-loop logic checks and conditions #
            ########################################

            # Check if we're at the last image, which affects the behaviour of the loop.
            if x == self.frame_count - 1:
                last_frame = True

            # Pre-load the next iteration of the loop image ahead of time, if we're not on the last frame.
            if not last_frame:
                """ 
                By asynchronously loading frames ahead of time, this provides a small but meaningful
                boost in performance when spanned over N frames. There's some code over head but 
                it's well worth it. 
                """
                background_frame_load = AsyncFrameRead(
                    self.upscaled_dir + "output_" +
                    get_lexicon_value(6, x + 1) + ".png",
                    self.context.controller)
                background_frame_load.start()

            ######################
            # Core Logic of Loop #
            ######################

            # Load the needed vectors to create the merged image.

            prediction_data_list = get_list_from_file_and_wait(
                self.pframe_data_dir + "pframe_" + str(x) + ".txt",
                self.context.controller)
            residual_data_list = get_list_from_file_and_wait(
                self.residual_data_dir + "residual_" + str(x) + ".txt",
                self.context.controller)
            correction_data_list = get_list_from_file_and_wait(
                self.correction_data_dir + "correction_" + str(x) + ".txt",
                self.context.controller)
            fade_data_list = get_list_from_file_and_wait(
                self.fade_data_dir + "fade_" + str(x) + ".txt",
                self.context.controller)

            if not self.context.controller.is_alive():
                self.log.info(" Merge thread killed at frame %s " % str(x))
                break

            # Create the actual image itself.
            current_frame = self.make_merge_image(
                self.context, current_upscaled_residuals, frame_previous,
                prediction_data_list, residual_data_list, correction_data_list,
                fade_data_list)
            ###############
            # Saving Area #
            ###############
            # Directly write the image to the ffmpeg pipe line.
            self.pipe.save(current_frame)

            # Manually write the image if we're preserving frames (this is for enthusiasts / debugging).
            if self.preserve_frames:
                output_file = self.workspace + "merged/merged_" + str(
                    x + 1) + self.extension_type
                background_frame_write = AsyncFrameWrite(
                    current_frame, output_file)
                background_frame_write.start()

            #######################################
            # Assign variables for next iteration #
            #######################################
            if not last_frame:
                # We need to wait until the next upscaled image exists before we move on.
                while not background_frame_load.load_complete:
                    wait_on_file(
                        self.upscaled_dir + "output_" +
                        get_lexicon_value(6, x + 1) + ".png",
                        self.context.controller)
            """
            Now that we're all done with the current frame, the current `current_frame` is now the frame_previous
            (with respect to the next iteration). We could obviously manually load frame_previous = Frame(n-1) each
            time, but this is an optimization that makes a substantial difference over N frames.
            """
            frame_previous = current_frame
            current_upscaled_residuals = background_frame_load.loaded_image
            self.context.controller.update_frame_count(x)

        self.pipe.kill()
Esempio n. 3
0
    def run(self):
        self.log.info("Run called.")

        for x in range(self.start_frame, self.frame_count):

            # Stop if thread is killed
            if not self.context.controller.is_alive():
                break

            # Files needed to create a residual image
            f1 = Frame()
            f1.load_from_string_controller(
                self.input_frames_dir + "frame" + str(x + 1) +
                self.extension_type, self.context.controller)
            # Load the neccecary lists to compute this iteration of residual making
            residual_data = get_list_from_file_and_wait(
                self.residual_data_dir + "residual_" + str(x) + ".txt",
                self.context.controller)

            prediction_data = get_list_from_file_and_wait(
                self.pframe_data_dir + "pframe_" + str(x) + ".txt",
                self.context.controller)

            # stop if thread is killed
            if not self.context.controller.is_alive():
                break

            # Create the output files..
            debug_output_file = self.debug_dir + "debug" + str(
                x + 1) + self.extension_type
            output_file = self.residual_images_dir + "output_" + get_lexicon_value(
                6, x) + ".jpg"

            # Save to a temp folder so waifu2x-vulkan doesn't try reading it, then move it
            out_image = self.make_residual_image(self.context, f1,
                                                 residual_data,
                                                 prediction_data)

            if out_image.get_res() == (1, 1):
                """
                If out_image is (1,1) in size, then frame_x and frame_x+1 are identical.

                We still need to save an outimage for sake of having N output images for N input images, so we
                save these meaningless files anyways.

                However, these 1x1 can slow whatever waifu2x implementation down, so we 'cheat' d2x 
                but 'fake' upscaling them, so that they don't need to be processed by waifu2x.
                """

                # Location of the 'fake' upscaled image.
                out_image = Frame()
                out_image.create_new(2, 2)
                output_file = self.residual_upscaled_dir + "output_" + get_lexicon_value(
                    6, x) + ".png"
                out_image.save_image(output_file)

            else:
                # This image has things to upscale, continue normally
                out_image.save_image_temp(output_file, self.temp_image)

            # With this change the wrappers must be modified to not try deleting the non existing residual file
            if self.context.debug == 1:
                self.debug_image(self.block_size, f1, prediction_data,
                                 residual_data, debug_output_file)
Esempio n. 4
0
    def run(self):

        self.pipe.start()
        # Load the genesis image + the first upscaled image.
        frame_previous = Frame()
        frame_previous.load_from_string_controller(
            self.merged_dir + "merged_" + str(self.start_frame) +
            self.extension_type, self.context.controller)

        self.pipe.save(frame_previous)

        f1 = Frame()
        f1.load_from_string_controller(
            self.upscaled_dir + "output_" +
            get_lexicon_value(6, self.start_frame) + ".png",
            self.context.controller)

        last_frame = False
        for x in range(self.start_frame, self.frame_count):
            ###################################
            # Loop-iteration pre-requirements #
            ###################################
            # Check if we're at the last image, which affects the behaviour of the loop.
            if x == self.frame_count - 1:
                last_frame = True

            # Pre-load the next iteration of the loop image ahead of time, if we're not on the last frame.
            if not last_frame:
                background_frame_load = \
                    AsyncFrameRead(
                        self.upscaled_dir + "output_" + get_lexicon_value(6, x + 1) + ".png", self.context.controller)

                background_frame_load.start()

            #######################
            # Loop-iteration Core #
            #######################
            # Load the needed vectors to create the merged image.
            prediction_data_list = get_list_from_file_wait_controller(
                self.pframe_data_dir + "pframe_" + str(x) + ".txt",
                self.context.controller)
            residual_data_list = get_list_from_file_wait_controller(
                self.residual_data_dir + "residual_" + str(x) + ".txt",
                self.context.controller)
            correction_data_list = get_list_from_file_wait_controller(
                self.correction_data_dir + "correction_" + str(x) + ".txt",
                self.context.controller)
            fade_data_list = get_list_from_file_wait_controller(
                self.fade_data_dir + "fade_" + str(x) + ".txt",
                self.context.controller)

            if not self.context.controller.is_alive():
                self.logger.info("Merge.py killed at frame " + str(x))
                break

            self.logger.info("Upscaling frame " + str(x))
            # Create the actual image itself.
            frame_next = self.make_merge_image(
                self.context, f1, frame_previous, prediction_data_list,
                residual_data_list, correction_data_list, fade_data_list)

            ###############
            # Saving Area #
            ###############

            # Directly write the image to the ffmpeg pipe line.
            self.pipe.save(frame_next)

            # Manually write the image if we're preserving frames (this is for enthusiasts / debugging).
            if self.preserve_frames:
                output_file = self.workspace + "merged/merged_" + str(
                    x + 1) + self.extension_type
                background_frame_write = AsyncFrameWrite(
                    frame_next, output_file)
                background_frame_write.start()

            #######################################
            # Assign variables for next iteration #
            #######################################
            # last_frame + 1 does not exist, so don't load.
            if not last_frame:
                # We need to wait until the next upscaled image exists before we move on.
                while not background_frame_load.load_complete:
                    wait_on_file_controller(
                        self.upscaled_dir + "output_" +
                        get_lexicon_value(6, x + 1) + ".png",
                        self.context.controller)

                f1 = background_frame_load.loaded_image

            frame_previous = frame_next

            # Signal to the rest of the dandere2x process we've finished upscaling frame 'x'.
            self.context.controller.update_frame_count(x)

        self.pipe.kill()